Gonio Meter Control Protocol (GMCP) 仕様書 Ver. 001 2000/07/22 作成 2001/01/26 改定 GMCPはTCP/IPを用いてゴニオメータの制御、モニターをリモートで 行なう為のプロトコール。モータコントローラが存在するマシンで サーバが動作し、他のマシンで動作するクライアントからのリクエスト に従ってゴニオメータの制御を行なう。このプロトコールの目的は ゴニオメータ制御に特化することによってクライアントプログラムを シンプルで小型にすることである。例えば引数によって制御できる コマンドプログラムを作ることにより、スクリプトによるバッチ処理、 外部コマンドを実行することができるソフトウェアとの連係が可能と なる。HTTP+CGI|Java+Web+Browser による制御と相補的な形でシステム を構成するとより効果的であると思われる。 通信手順は基本的にクライアントが出した要求に対しサーバが応答する、 という流れである。 0. 接続 接続はサーバが用意したストリーム型socketにクライアントが接続する 形態を想定している。 サーバに特定のポートを割り当て、lisen状態でクライアントの接続 要求を待つ。 ポート番号はdefaultで31310とする。 サーバにはアクセスを受け入れるクライアントのアドレスを限定する 機能が実装されるのが好ましい。 サーバは接続要求の日時、クライアントのアドレスなどの情報を ログファイルに記録するのが望ましい。 1. 認証 接続が確立した後、クライアントが接続リクエストを送信することによって 認証作業が始まる。認証ではTEXT文字列が用いられる。大文字と小文字は 区別される。 行末コードとして"\n"を採用する。 1.1 接続リクエスト クライアントが最初に送信する接続リクエストは "GMCP/001" である。001はバージョンを示し、002,003,...のように増加していく。 サーバは256Byteのバッファを用意し接続リクエストを受け取る。 送信バッファは送る文字列のサイズに合わせて動的にサイズを取得した ほうが好ましい。また、256byteを越えないようにする。 受け取った文字列が "GMCP/001" と一致した場合、 "GMCP/ACCEPT" をクライアントに返答し、接続が許可される。そして、サーバは またレシーブ状態になって次に期待される権限リクエストを待つ。 不一致の場合には "GMCP/REJECT" を返して、socketを閉じて接続を切断する。 1.2 権限リクエスト 接続が受け入れられると、クライアントは権限リクエストをサーバ に送信する。権限リクエストには「モニター」「ユーザー」「特権」の 3種類の権限がある。ユーザーとモニターのリクエストは "GMCP/USER" "GMCP/MNTR" で行なわれる。権限の許可はクライアントのIPアドレスで判断して行な われる。GMCPはLAN内で使用されることを前提にし、「モニター」権限 に関してはdefaultでは制限しない。「ユーザー」はゴニオ軸を占有する 可能性があるので、リクエスト可能なマシンを制限する。サーバはこの セッションの権限を「モニター」あるいは「ユーザー」にすると、 "GMCP/%s"(%s=ctime(&nowtime))とサーバ時刻を返す。 特権リクエストは "GMCP/ROOT" で行なわれ、サーバは "GMCP/PASS?" とパスワードを要求する。クライアントはA-z,0-9の8文字で構成 されるパスワードを答える。 "********" それがサーバ側のパスワードと一致すれば、このセッションの権限 を「特権」に設定し "GMCP/%s"(%s=ctime(&nowtime))とサーバ時刻を返す。 パスワードが一致しない場合、 "GMCP/REFUSE" を返し、接続を閉じる。 権限リクエストの書式が不整合の場合も "GMCP/REJECT" を返して接続を閉じる。 権限リクエストの手続きが完了すると、サーバは制御コマンドを 受け取る準備をする。 2. 権限とプロセス制御 権限には「モニター」「ユーザー」「特権」の3種類ある。 「モニター」は制御コマンドのうちのモニターコマンドのみリクエスト 可能である。「ユーザー」では通常の制御コマンドは全てリクエスト できる。 サーバは複数のアクセスを受け入れることが望まれる。現在座標値取得 などのモニターコマンドは複数のマシンからの要求に答えるべきである。 「ユーザー」の場合、既に他の「ユーザー」が接続し、ゴニオ軸を占有 している場合にはそのセッションが終了しない限り、排他的制御コマンド のリクエストはできない。サーバは2番め以降の「ユーザー」の排他的制御 コマンドのリクエストを拒絶する。 「特権」の場合、他の「ユーザー」の接続状況に関わらず全ての制御 コマンドおよび特権コマンドのリクエストが可能である。 特権コマンドはサーバが管理する全てのデバイスの緊急停止、他の 「ユーザー」の接続の切断などの機能を持つものである。 「特権」での接続は1つのみ受け入れられ、2番目以降は拒絶される。 実装の例としてfork()によるマルチプロセス化、セマフォを用いた 排他制御が考えられる。クライアントとの応答は子プロセスに渡す ほうが安全と思われる。 3. 制御コマンド 制御コマンドは1byte(8bit)文字3個で構成され、最初の2つは ASCII TEXT として認識される。先頭の文字がコマンドの種類を、2番目の文字が コマンドの内容を表す。3番目はchar型で表した軸番号である。 "#**": 排他的制御コマンド "&**": モニターコマンド "$**": 特権コマンド 制御コマンドのデリミタは"\n"である。 軸番号は、0:全軸であり、以後は順番に (16進)1,2,3,....,9,a,b,c... と続く。 サーバはリクエストに指定された軸が使用可能であるなら、 "OK" を返す。軸が他のユーザに占有されている、制御コマンドが不正、 そのコマンドの権限がない、といった場合には "NG" を返し、継続パラメータを待つ。 クライアントは"OK"を受け取ると、コマンド固有のパラメータ (バイナリを8byte文字列に変換したもの。下位ビットが先頭)か、 継続パラメータを返す。サーバもコマンドによって期待される返答を 受け取る準備をする。 サーバは受け取ったパラメータに問題がなければ "OK" を返し、不正であれば "NG" を返し、継続パラメータを待つ。 サーバからの返り値はバイナリデータをchar型(8byte)の文字列に変換した ものであり、データサイズは各コマンドごとに決められている。 文字列は下位ビットが先頭になるように変換されている。 例:long型(4byte) (long) a = (long)buf[0] +(long)buf[1]<<8 +(long)buf[2]<<16 +(long)buf[3]<<24 3.1 排他的制御コマンド 排他的制御コマンドはその軸を占有し、その占有状態が解除される まで、その軸の操作を他の「ユーザー」が行なうことはできない。 "#H*": 原点復帰 なし char 0:正常 -1:エラー 1:動作中 指定した軸を原点に復帰する。動作中ならばなにもせずに返す。 "#L*": CW方向リミットへ なし char 0:正常 -1:エラー 1:動作中 指定した軸をCW方向リミットへ移動する。 動作中ならばなにもせずに返す。 "#R*": CCW方向リミットへ なし char 0:正常 -1:エラー 1:動作中 指定した軸をCCW方向リミットへ移動する。 動作中ならばなにもせずに返す。 "#S*": 通常停止 なし char 0:正常 -1:エラー 指定した軸を通常停止する。停止した状態で発行した場合でも 正常と扱う。 "#T*": 即時停止 なし char 0:正常 -1:エラー 指定した軸を直ちに停止する。停止した状態で発行した場合でも 正常と扱う。 "#U*": 励磁ON なし char 0:正常 -1:エラー 1:動作中 指定した軸を励磁する。動作中ならばなにもせずに返す。 "#D*": 励磁OFF なし char 0:正常 -1:エラー 1:動作中 指定した軸の励磁を解除する。動作中ならばなにもせずに返す。 通常停止してからOFFするべき。 "#V*": 速度設定 short 速度設定 char 0:正常 -1:エラー 1:動作中 指定した軸の速度を設定する。 速度は、0:低速(default)、1:中速、2:高速があり、 具体的な値の設定は実行プログラムに実装される。 動作中ならばなにもせずに返す。 "#P*": 相対ステップ移動 long 相対移動パルス数 char 0:正常 -1:エラー 1:動作中 指定した軸を相対移動パルス数だけ移動する。パルス数は 符合つきで、+がCW方向、-がCCW方向である。 動作中ならばなにもせずに返す。 "#A*": 絶対位置移動 long 絶対パルス数座標 char 0:正常 -1:エラー 1:動作中 指定した軸を指定された絶対パルス数座標へ移動する。 動作中ならばなにもせずに返す。 "#J*": ジョグ移動 char 0:CW方向 1:CCW方向 char 0:正常 -1:エラー 指定した軸を指定した方向へのジョグ移動モードにする。 その前に速度設定コマンドで設定された速度で移動し、停止コマンドや 反対方向のジョグ移動あるいはリミットに達するまで動き続ける。 ジョグ移動コマンドは他のコマンドとは異なり、動作中の場合は停止 させてジョグ移動モードに切替える。 1セッションで排他的制御コマンドを連続して継続している間、 そのセッションが排他的制御を占有した状態となる。 「ユーザー」では排他的制御コマンドは連続して10回までしか継続 できない。10回に達するとサーバはクライアントの意志に関わらず 強制的にセッションを終了する。10回に達する前にモニターコマンド か他の軸の制御コマンドのリクエストを発行することにより、 占有状態が解除され、カウントが初期化される。位置確認を考慮 すると、排他的制御コマンドとモニターコマンドを交互に使用する ほうが実用的である。 3.2 モニターコマンド モニターコマンドは現在位置やデバイスの状態を取得するための コマンドで、複数の「ユーザー」からのリクエストに答えることが できる。モニターコマンドは通常パラメータを持たない。 "&p*": 位置パルス座標値 上位1byte char 状態フラグ + 下位4byte long パルス座標値 指定された軸の現在の位置をパルス座標値で取得する 状態フラグの仕様は下位ビットから 2^0: モータの動作 0=idle, 1=busy 2^1: 原点センサー 0=off, 1=on 2^2: CW方向リミットセンサー 0=off, 1=on 2^3: CCW方向リミットセンサー 0=off, 1=on 2^4: 励磁状態 0=off, 1=on 2^5: 停止フラグ 0=off, 1=on 2^6: インターロック 0=off, 1=on 2^7: エラー状態 0=normal, 1=error ※捕捉 1〜31はその軸のカウンタA(出力パルス座標)の値、 32+〜63はその軸のカウンタB(エンコーダ座標)、 64〜75はその軸のポテンショ(via ADC)の値を取得する。 ただしADCがない場合にはエンコーダを読む "&s*": 速度設定値 char 指定された軸の速度設定を取得する 0:低速、1:中速、2:高速 "&l*": センサー状態 char 指定された軸のリミットセンサーなどの状態を取得する。 0:すべてOFF, 1:CW方向リミットON, 2:CCWリミット方向ON, 3:原点センサーON, 4:それ以外の状態 "&g*": 動作状態 char 指定された軸のモータの動作状態を取得する 0:停止(励磁OFF), 1:動作中(励磁ON), -1:励磁OFFで動作中, 2:励磁ONで停止 "&e*": エラー状態 char 指定された軸のエラー状態を取得する 0:正常, 1:エラー "&q*": セッション終了 なし 軸番号はダミー。 セッションを終了して接続を閉じることを通知する。 3.3 特権コマンド 特権コマンドはプロセスの管理に用いる。「特権」モードの セッションでしか使用できない。「ユーザー」がリクエスト しても不正なデータとして判断される。 "$E*":全軸緊急停止 なし 全ての軸を緊急停止させる。 軸番号ははダミー。通常は0。 "$X*":接続切断 なし 他の「ユーザ」の接続を強制的に切断する。 軸番号はダミー。通常は0。 "$R*":接続拒否 なし 他の「ユーザ」の新たな接続を拒絶する。 軸番号はダミー。通常は0。 "$Q*":サーバの終了 なし サーバを終了させる。 軸番号はダミー。通常は0。 コマンドは種類によって引数をもつものがある。引数はバイナリを 1byte文字列に変換した形で送信され、そのデータサイズは各コマンド ごとに決められている。 3.4 継続パラメータ 継続パラメータは1文字の ASCII TEXT であり、 A:終了, B:継続, C:キャッチボール の3種類ある。継続パラメータの送信はコマンド実効のゴーサイン を兼ねている。サーバは継続パラメータを受け取ることにより それまでに設定されたコマンドを実際に実行する。 "A"はコマンドリクエストをサーバが1回だけ実行し、クライアント に返り値を返すと直ちにセッションを終了する。 "B"はコマンド実行後、サーバは次のコマンドリクエストを待つ。 排他的制御コマンドを発行した場合、この状態では駆動した軸の 占有を保持したままである。続いてリクエストされるコマンドが モニターコマンドであった場合も占有は継続される。したがって、 同じ軸の排他的制御コマンドと継続パラメータ"B"、モニター コマンドの組合せでその軸を占有し続けることができる。 占有はセッションの終了あるいは他の軸への移行によって解除される。 また、権限が「モニター」の場合は継続パラメータ"B"は無効である。 "C"はモニターコマンドでのみ有効で、キャッチボールモードになる。 サーバはコマンドで要求される返答をクライアントに返すと、 キャッチボール返球待ちの状態になる。クライアントからの返球は TEXT1文字である。"c"はキャッチボール継続で同じコマンドを実行 して値を返す。"b"はキャッチボールを終了し、次のコマンド リクエストを待つ。"a"はキャッチボールを終了し、セッションも 終了する。返り値はない。それ以外の文字は"a"として扱う。 各コマンドをサーバマシンで実行するプログラム、スクリプトは 上記の仕様を満たすように作られなければならない。 デバイスと各サーバの軸との関係は、クライアント側でテーブル を用意して参照するのがよい。サーバ側ではデバイスをなるべく 抽象的に扱うべきである。 また、デバイスの初期化等はGMCPで行なうべきことではない。これ はサーバ側でデバイスの構成に合わせてサーバプログラムに、 あるいは別プログラムとして実装するべきである。 3.5 用例 ・相対ステップ移動のあと継続して励磁OFFし、終了  サーバ側   "GMCP/001"   クライアント側      <-------------------         "GMCP/ACCEPT"      ------------------->         "GMCP/USER"      <-------------------    "GMCP/Sat Jul 22 16:00:05 2000"      ------------------->          "#P1"      <-------------------          "OK"      ------------------->          12000      <-------------------          "OK"      ------------------->          "B"      <-------------------           0      ------------------->          "#D1"      <-------------------          "OK"      ------------------->          "A"      <------------------- ---------------- close -------------------- ・位置パルス座標値取得  サーバ側   "GMCP/001"   クライアント側      <-------------------         "GMCP/ACCEPT"      ------------------->         "GMCP/MNTR"      <-------------------    "GMCP/Sat Jul 22 16:00:05 2000"      ------------------->          "&p*"      <-------------------          "OK"      ------------------->          "C"      <-------------------          1000      ------------------->          "c"      <-------------------          1200      ------------------->          "a"      <------------------- ---------------- close -------------------- 4. 例外処理 GMCPではTCPでデータをやり取りされることを前提としているので パケットのロストに対する例外処理は用意されない。 必要とされる例外処理はタイムアウト処理とSIGPIPEシグナル処理 である。実装はサーバに関しては必須である。クライアントも実装 するほうが好ましい。 4.1 タイムアウト処理 GMCPはLAN内での使用を前提としているため、タイムアウトは短く 設定される。 サーバ側のタイムアウト 認証手続きにおいて、接続リクエストを受け入れて"GMCP/ACCEPT" を返し、権限リクエストを待つ間 -> 5sec 特権リクエストによって"GMCP/PASS?"を返し、パスワードを待つ間 -> 8sec 認証手続き完了後コマンドのリクエストを待つ間 -> 60sec セッション継続によって次の制御コマンドのリクエストを待つ間 -> 600sec 制御コマンドが引数を持つ場合、コマンドリクエスト受け取り後 引数パラメータを待つ間 -> 3sec 座標取得で用いられるキャッチボールモードの場合、返球をまつ間 -> 2sec 以上をdefault値とする。 クライアント側のタイムアウトは特に規定せず、各々の実装に任せる。 4.2 SIGPIPE(パイプが壊れちゃったのよシグナル)処理 GMCPはストリーム型socketを用いた通信を前提としているため、 クライアントプログラムのトラブルにより仮想パイプの破壊という 事態が起こり得る。サーバはSIGPIPEが発生してもメインプロセスが 終了することなく、サービスを継続できるように実装されなければ ならない。 クライアントに関しては各々の実装に任せる。 ハード的な制約によるクライアントの待ち時間はコマンドによって 異なると思われる。 5. 終了処理 サーバはセッションの終了時刻を記録するのが望ましい。 サーバ自体の終了に関して、その終了のクライアントへの通知は socketのクローズをもって代える。