全年3月5日の投稿[5件]
2026年 この範囲を時系列順で読む この範囲をファイルに出力する
C言語の共用体(union)ですが、教科書やら動画を見ますと「あまり使い道が無い」的な解説が多いような気がします。
されど、今回のArt-Net系の装置では便利です。Art-Net のポート番号 0x1936(6454) の受信値をとりあえず突っ込むだけで要素毎に取り出すことも出来るからです。例えば ArtDMX は530バイトのパケットですが、受信値を uint8_t[530] (または unsigned char[530]) の配列として保存するだけで ArtDMX の構造体としても扱えます。パディングに注意は必要ですが、便利に使えると思うのです。ID、OpCode、ProVer をまとめて評価するのに先頭12バイトを uint8_t[12] としておいて memcmp で判別することも出来ます。AertDMX と別種の Art-Net パケットもシームレスに扱えそうです。
天才を超越した神たちが何故 union を作ったのかを考えるとワクワクします。
とまぁ、最近C言語の理解が進んで一人笑いが止まらないアホの戯言でした。
オレメモです。
gccで構造体のパディングを回避する書き方。struct に続いて「__attribute__((__packed__))」を入れるそうな。gcc独特の書式らしいので、コンパイラに合わせた書式を使ってください。
typedef struct __attribute__((__packed__)) ad_struct {
uint8_t ad_ID[8];
uint8_t ad_OpCode[2];
uint8_t ad_ProVerHi;
uint8_t ad_ProVerLow;
uint8_t ad_Sequence;
uint8_t ad_Physical;
uint8_t ad_SubUni;
uint8_t ad_Net;
uint8_t ad_LengthHi;
uint8_t ad_Length;
uint8_t ad_Data[512];
};
ad_struct ad_data;
ArtDMXを保存する構造体はこんな感じに書けばよいのでしょう。たぶん。
この型を sizeof で見て530バイトならヨシです。
ついでに共用体の定義(案)です。
// Art-Netの受信値を収める構造体
typedef struct __attribute__((__packed__)) an_struct {
uint8_t resv[530];
};
// ArtDMXを取り出す構造体
typedef struct __attribute__((__packed__)) ad_struct {
uint8_t ID[8];
uint8_t OpCode[2];
uint8_t ProVerHi;
uint8_t ProVerLow;
uint8_t Sequence;
uint8_t Physical;
uint8_t SubUni;
uint8_t Net;
uint8_t LengthHi;
uint8_t Length;
uint8_t Data[512];
};
// Art-Netの受信値を保存する共用体ループバッファ
union an_stack {
an_struct an_resv;
ad_struct ad_data;
} an_loopbuffer[8192];
こういうことでいいのかな?
共用体の書き方はまだよくわかってないのですけど。
共用体の配列を作って Art-Net のポートで受信したパケットを延々と保存します。8191番まで記録したら0に折り返すループバッファです。
8192個あれば44fps、8センダー、各16ユニバースで最短でも1.45秒分の保存が出来るハズです。十進数で8192なのは2進数(16進数)でキリの良い数値のため折り返し評価が少ない処理で出来るからです。十進数8192は16進数0x2000でキリがよく処理しやすいのです。このあたりはアセンブリ言語だけでPICマイコンと会話をしてきた者にとって自然な着想です。10進数は人が日常的に使い慣れているだけで特筆するほど合理的な数体系ではありませんし、今どきのコンピュータ(論理回路)に合わせた方が便利です。
ヘッダーチェックは当該の配列要素(例えば an_loopbuffer[1024] )を示すポインタからmemcmpで12バイトをチェックすれば済みますので共用体には定義しません。
ArtDMX以外のパケットにも使えるチェック方法です。
#C言語
されど、今回のArt-Net系の装置では便利です。Art-Net のポート番号 0x1936(6454) の受信値をとりあえず突っ込むだけで要素毎に取り出すことも出来るからです。例えば ArtDMX は530バイトのパケットですが、受信値を uint8_t[530] (または unsigned char[530]) の配列として保存するだけで ArtDMX の構造体としても扱えます。パディングに注意は必要ですが、便利に使えると思うのです。ID、OpCode、ProVer をまとめて評価するのに先頭12バイトを uint8_t[12] としておいて memcmp で判別することも出来ます。AertDMX と別種の Art-Net パケットもシームレスに扱えそうです。
天才を超越した神たちが何故 union を作ったのかを考えるとワクワクします。
とまぁ、最近C言語の理解が進んで一人笑いが止まらないアホの戯言でした。
オレメモです。
gccで構造体のパディングを回避する書き方。struct に続いて「__attribute__((__packed__))」を入れるそうな。gcc独特の書式らしいので、コンパイラに合わせた書式を使ってください。
typedef struct __attribute__((__packed__)) ad_struct {
uint8_t ad_ID[8];
uint8_t ad_OpCode[2];
uint8_t ad_ProVerHi;
uint8_t ad_ProVerLow;
uint8_t ad_Sequence;
uint8_t ad_Physical;
uint8_t ad_SubUni;
uint8_t ad_Net;
uint8_t ad_LengthHi;
uint8_t ad_Length;
uint8_t ad_Data[512];
};
ad_struct ad_data;
ArtDMXを保存する構造体はこんな感じに書けばよいのでしょう。たぶん。
この型を sizeof で見て530バイトならヨシです。
ついでに共用体の定義(案)です。
// Art-Netの受信値を収める構造体
typedef struct __attribute__((__packed__)) an_struct {
uint8_t resv[530];
};
// ArtDMXを取り出す構造体
typedef struct __attribute__((__packed__)) ad_struct {
uint8_t ID[8];
uint8_t OpCode[2];
uint8_t ProVerHi;
uint8_t ProVerLow;
uint8_t Sequence;
uint8_t Physical;
uint8_t SubUni;
uint8_t Net;
uint8_t LengthHi;
uint8_t Length;
uint8_t Data[512];
};
// Art-Netの受信値を保存する共用体ループバッファ
union an_stack {
an_struct an_resv;
ad_struct ad_data;
} an_loopbuffer[8192];
こういうことでいいのかな?
共用体の書き方はまだよくわかってないのですけど。
共用体の配列を作って Art-Net のポートで受信したパケットを延々と保存します。8191番まで記録したら0に折り返すループバッファです。
8192個あれば44fps、8センダー、各16ユニバースで最短でも1.45秒分の保存が出来るハズです。十進数で8192なのは2進数(16進数)でキリの良い数値のため折り返し評価が少ない処理で出来るからです。十進数8192は16進数0x2000でキリがよく処理しやすいのです。このあたりはアセンブリ言語だけでPICマイコンと会話をしてきた者にとって自然な着想です。10進数は人が日常的に使い慣れているだけで特筆するほど合理的な数体系ではありませんし、今どきのコンピュータ(論理回路)に合わせた方が便利です。
ヘッダーチェックは当該の配列要素(例えば an_loopbuffer[1024] )を示すポインタからmemcmpで12バイトをチェックすれば済みますので共用体には定義しません。
ArtDMX以外のパケットにも使えるチェック方法です。
#C言語
2022年 この範囲を時系列順で読む この範囲をファイルに出力する
オレメモ
● Art-Netの受信の準備でするべきこと。
・受信のタイムアウトを定義し、タイムアウトを例外としてキチンと処理する。
● Art-Netを受信したらするべきこと。
・受信した「Art-Netのバイナリデータ」に「いつ」「どこからか(送信元)」を絡めて受信データとする。
・ユニバースと内部ルートの対照データを基に、データの参照キーを「ユニバース」から「ルート」に変換してキャッシュする。
・「いつ」をキーに送信元からの送信が無くなったと見なせるならキャッシュも含め送信元情報を消去する。
・「いつ」をキーにキャッシュの有効期限が切れたならキャッシュのレベル値をすべてゼロにする。
・送信元ごとのキャッシュをルートで丸めて一意のキャッシュにする。
#[Art-Net]
● Art-Netの受信の準備でするべきこと。
・受信のタイムアウトを定義し、タイムアウトを例外としてキチンと処理する。
● Art-Netを受信したらするべきこと。
・受信した「Art-Netのバイナリデータ」に「いつ」「どこからか(送信元)」を絡めて受信データとする。
・ユニバースと内部ルートの対照データを基に、データの参照キーを「ユニバース」から「ルート」に変換してキャッシュする。
・「いつ」をキーに送信元からの送信が無くなったと見なせるならキャッシュも含め送信元情報を消去する。
・「いつ」をキーにキャッシュの有効期限が切れたならキャッシュのレベル値をすべてゼロにする。
・送信元ごとのキャッシュをルートで丸めて一意のキャッシュにする。
#[Art-Net]
実機を離れて考えを進めると抜けが見えてきます。
一つ前のオレメモはArt-Netを受信していないときの対策です。タイムアウトを設定しませんと延々と待つだけの無限ループになり、適切な終了すら出来なくなります。一定時間受信が無いならそれをユーザーに伝えることも大切な処理です。
その前の送信元が複数になった時の対策もそうです。ミキサー機能が無いと謳っても複数の接続をする人が居ないとも限りませんし、そんな人に限って勝手な想像通りに動かないと作った奴が悪いとかダメな製品だとかレッテルを貼ってくるものです。この件については副産物としてミキサー機能に至れそうな可能性が見えましたので「災い転じて何とやら」ですが、先入観を排除して可能性を熟慮することの大切さを改めて痛感です。
受信処理は試行錯誤しながらディレイを可能にしたことでソースコードが読みにくくなってきましたので、タイムアウトと複数の送信元への対応を加えながら読みやすく書き直しです。
パラメータが増えてくると変数の命名に配慮するだけでも読みやすさが違ってきますので、この辺りも含めてよく考えていきます。
ここまでやってきて、思った以上に受信処理が大切なことに驚いています。
ミキサーしかり、ディレイしかり、思い描いている機能の大半が受信直後の処理にかかっていたとは当初は全く思いもしませんでした。
この辺りは所詮アマチュアの所業でありますが、まだまだ修行です。
#Python #[Art-Net]
一つ前のオレメモはArt-Netを受信していないときの対策です。タイムアウトを設定しませんと延々と待つだけの無限ループになり、適切な終了すら出来なくなります。一定時間受信が無いならそれをユーザーに伝えることも大切な処理です。
その前の送信元が複数になった時の対策もそうです。ミキサー機能が無いと謳っても複数の接続をする人が居ないとも限りませんし、そんな人に限って勝手な想像通りに動かないと作った奴が悪いとかダメな製品だとかレッテルを貼ってくるものです。この件については副産物としてミキサー機能に至れそうな可能性が見えましたので「災い転じて何とやら」ですが、先入観を排除して可能性を熟慮することの大切さを改めて痛感です。
受信処理は試行錯誤しながらディレイを可能にしたことでソースコードが読みにくくなってきましたので、タイムアウトと複数の送信元への対応を加えながら読みやすく書き直しです。
パラメータが増えてくると変数の命名に配慮するだけでも読みやすさが違ってきますので、この辺りも含めてよく考えていきます。
ここまでやってきて、思った以上に受信処理が大切なことに驚いています。
ミキサーしかり、ディレイしかり、思い描いている機能の大半が受信直後の処理にかかっていたとは当初は全く思いもしませんでした。
この辺りは所詮アマチュアの所業でありますが、まだまだ修行です。
#Python #[Art-Net]
オレメモ
Pythonのsocket.recvfromでタイムアウト処理をする。
socketのインスタンスをsockとした場合、sock.recvfromの前に
sock.settimeout(<タイムアウトの秒数>)
とする。
sock.recvfrom(<バッファ数>) を try: で実行し、except socket.timeout: でタイムアウトエラーを拾う。
#Python
Pythonのsocket.recvfromでタイムアウト処理をする。
socketのインスタンスをsockとした場合、sock.recvfromの前に
sock.settimeout(<タイムアウトの秒数>)
とする。
sock.recvfrom(<バッファ数>) を try: で実行し、except socket.timeout: でタイムアウトエラーを拾う。
#Python
本日は久しぶりの現地照明。現場って感じでホッとします。
実機での研究や試験は出来ませんが、アイデアが出てきたら整理しています。今日出てきたアイデアはArt-Netの受信に関するものです。
Art-Netは複数の送信機を同じネットワークに接続することが出来ます。正しくはないけど間違ってもいない使い方ですが、期待してない挙動が起こっても面白くないので対応しといた方が良さそう。
socketによる受信からはデータと送信元アドレスを取り出せますから、送信元アドレスをキーにデータを仕分けます。採用するデータは送信元を一つに限るのが道理な気もしますが、同じユニバース・スロットの最大値を採用したらHTPのミキサーになってしまいます。
ミキサーは欲しい機能ですが、バカよけを施した副産物でミキサーになりそう。
#[Art-Net]
実機での研究や試験は出来ませんが、アイデアが出てきたら整理しています。今日出てきたアイデアはArt-Netの受信に関するものです。
Art-Netは複数の送信機を同じネットワークに接続することが出来ます。正しくはないけど間違ってもいない使い方ですが、期待してない挙動が起こっても面白くないので対応しといた方が良さそう。
socketによる受信からはデータと送信元アドレスを取り出せますから、送信元アドレスをキーにデータを仕分けます。採用するデータは送信元を一つに限るのが道理な気もしますが、同じユニバース・スロットの最大値を採用したらHTPのミキサーになってしまいます。
ミキサーは欲しい機能ですが、バカよけを施した副産物でミキサーになりそう。
#[Art-Net]