9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ElixirAdvent Calendar 2024

Day 23

Elixir で ArtNet パケットを Parse してみる

Last updated at Posted at 2024-12-22

はじめに

この記事は Elixir Advent Calendar 2024 の 12/23 の記事です。

Unity(C#) で ArtNet を送受信する内容を以前投稿し、GitHub にライブラリとして公開していますが、今回は同様の ArtNet パケットの Parse を Elixir でやってみようと思います。

ArtNet とは

以前書いた記事にも書いてますが、ArtNet とは舞台照明などの制御で使われているプロトコルの一つです。舞台照明の制御は RS-485 を基にした DMX512-A という規格で制御されているのが一般的です。
この DMX512-A は 1 本のケーブルで 512 チャンネルで、1チャンネルあたり 0~255(8bit) の値で制御することができます。
この DMX を Ethernet を介してやり取りできるようにしたものの一つが ArtNet です。

ArtNet は UDP 6454 番ポートが使われ、ArtNet の規格は以下のドキュメントに書かれています。

ArtNet の 1~8 バイト目はそのパケットが ArtNet のパケットかどうかを識別するための場所で、Art-Net\0 の固定値になっています。9~10 バイト目は OpCode(operation code) と呼ばれる値で、この値で ArtNet パケットの種類を識別します。

11 バイト目以降は OpCode によって内容が異なりますが、
OpCode が OpDmx(DMXパケット) の場合、11~12 バイト目はプロトコルバージョン、13 バイト目は シーケンス番号、15~16 バイト目には Universe 番号が入ります。

18 バイト目以降から DMX の値が順に入れられているのですが、16~17 バイト目には、18 バイト目以降の DMX の長さが格納されています。
image.png

実装

Elixir はバイナリに対してパターンマッチが可能です。

今回 OpCode が ArtDmx で、DMX のデータが 255 の値が 1 つだけが入ってる Universe 0 の ArtNet パケットを Parse してみます。

まずはじめに、ArtNet のパケットかどうかの判別は、パケットの先頭 8 バイト目が Art-Net\0 になっているかどうかで判別できます。
Elixir ではパターンマッチを使って、以下の様な感じで行えます。

packet = <<0x41, 0x72, 0x74, 0x2D, 0x4E, 0x65, 0x74, 0x00, 0x00, 0x50, 0x00, 0x0E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF>>
<<65, 114, 116, 45, 78, 101, 116, 0, 0, 80, 0, 14, 1, 0, 0, 0, 0, 1, 255>>

case packet do
 "Art-Net\0" <> _ -> true
 _ -> false
end

結果: true

また、9~10 バイト目の OpCode(little endian) を文字列で以下のようにすることで取得できます。
今回は OpCode の値が分かりやすいように 16 進数の文字列に変換して返しています。

case packet do
  "Art-Net\0" <> <<op_code::little-size(16)>> <> _rest -> {:ok, "0x" <> Integer.to_string(op_code, 16)}
  _ -> :error
end

結果: {:ok, "0x5000"}

11~12 バイト目はプロトコルバージョンは 14 の固定値なので、ArtDmx のパケットを Parse するには以下の様になります。

case packet do
  <<
    "Art-Net\0"::binary,
    0x5000::little-size(16),
    14::size(16),
    sequence::size(8),
    physical::size(8),
    sub_universe::size(8),
    net::size(8),
    length::size(16),
    data::size(length)-bytes
  >> ->
    {:ok,
      %{
        sequence: sequence,
        physical: physical,
        sub_universe: sub_universe,
        net: net,
        length: length,
        data: (for <<byte::size(8) <- data>>, do: byte)
      }}

  _ ->
    :error
end

結果: {:ok,
  %{
    sequence: 0,
    physical: 0,
    sub_universe: 0,
    net: 0,
    length: 1,
    data: [255]
  }}

このように Elixir のパターンマッチを使うことで、ArtNet のパケットを簡単に Parse することができます。

9
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?