HSMSの接続が成立しても、装置が返事をするとは限りません。公開ライブラリsecsgem 0.3.0で装置役とホスト役を立て、接続から最初のイベント報告までのメッセージを実際に流しました。接続は「回線がつながる」「会話が始まる」「報告を受け取る準備が整う」の三段階で進み、正常な手順は5回とも同じ順番で通りました。詰まった地点は、どれも「エラーが返らない場所」です。実機ではなく、同じライブラリ同士のループバック試験での結果です。試験の範囲を下の表で示した上で、自社装置との接続試験に持ち込めるチェックリストまで落とし込みます。
この実測が示すもの、示さないもの
| 項目 | 内容 |
|---|---|
| 何をつないだか | secsgem 0.3.0の装置役(PASSIVE)とホスト役(ACTIVE)。同じプロセスの中で、127.0.0.1のループバック経由で会話させた |
| 何ではないか | 実際の装置ではない。ベンダー装置や他のGEM実装との相互接続性は測っていない |
| 環境 | macOS 26.7.1(arm64)、CPython 3.13.5。2026年10月9日、この1環境のみ |
| 回数 | 正常シーケンス5回。失敗ケースは各1回 |
| タイムアウト | 試験用に短縮した値(T3 3秒、T7 2秒、establish_communication_timeout 2秒)。ライブラリの既定値はT3 45秒、T7 8秒 |
| ミリ秒の値 | ログ時刻またはホストのアプリ側計時で、スレッドのキュー待ちを含む。性能値ではない |
| 規格との関係 | 観測はすべて「secsgem 0.3.0の動作」。SEMI E5/E30/E37の規格本文は参照しておらず、規格への適合・違反は判定していない |
「つながりました」の手前に、もう一つ関門がある
HSMSの接続成功で通ったのは、運び方の層だけです。
装置連携の打ち合わせで「HSMSはつながりました」という報告を聞くことがあります。この一言だけでは、上位がデータを受け取れるかどうかは分からない。今回の試験で一番はっきりしたのが、そこでした。
前回の記事では、SECS/GEMを運び方(SEMI E37のHSMS)、中身の書式(SEMI E5のSECS-II)、装置の振る舞い(SEMI E30のGEM)の三層に分け、ラインの装置を三列に棚卸ししました。secsgemの文書は、HSMSを "HSMS defines the communication between host and equipment over the TCP protocol." と説明しています。TCPの上でホストと装置の通信を定める層。接続が成立した時点で確かなのは、この一番下が通ったことだけです。
その上に乗るGEMの役割を、SEMI E30の要旨はこう書いています。
"The GEM Standard defines which SECS-II messages should be used, in what situations, and what the resulting activity should be."(GEM規格は、どのSECS-IIメッセージを、どの場面で使い、その結果どう動くべきかを定める)
SEMI E30-0526, 2.1(SEMI Store 要旨)
どの場面で、どのメッセージを送るか。その順番を外したとき、装置は何を返すのか。要旨から読み取れるのは規格の狙いまでで、手元の実装がどう振る舞うかは別に確かめるしかない。だから流してみました。
接続から最初のイベントまで、実際に流れた順番
正常シーケンスは5回とも成功し、1回あたりホスト18・装置18、計36フレームが行き来しました。
装置役には、状態変数を三つ(10 ChamberTemp、11 WaferCount、12 RecipeName)と、アラームを一つ(ALID 1)定義しています。ホスト役はこの装置に対し、下の順番でメッセージを送りました。右端の列は、そのやり取りを現場の言葉に置き換えたものです。
| 段階 | メッセージ | 実測で返ってきたもの | 現場の言葉で |
|---|---|---|---|
| 回線の確立 | Select.req → Select.rsp | 応答あり | 電話がつながった |
| 会話の開始 | S1F13 → S1F14(装置とホストの双方から送信) | 装置のS1F14は先頭が0x0、続いて "secsgem" "0.3.0" の二つの文字列 | 名乗り合い |
| 生存確認 | S1F1 → S1F2 | "secsgem" "0.3.0" | 「聞こえますか」 |
| 状態の読み出し | S1F3 → S1F4 | 23.5、0、"RCP-A"、制御状態3(secsgemの状態名でHOST_OFFLINE) | 計器を読む |
| 変数名の照会 | S1F11 → S1F12 | 変数の名前と単位 | 計器のラベルを読む |
| オンライン要求 | S1F17 → S1F18 | 0x0。直後の読み出しで制御状態は5(ONLINE_REMOTE) | 遠隔操作を任せてもらう |
| 報告の準備 | S2F33 → S2F35 → S2F37 | 三つとも0x0 | 何を、いつ、送ってよいかを決める |
| 遠隔コマンド | S2F41 "START" → S2F42 | HCACK 0x4 | 指示を出す |
| イベント報告 | S6F11(装置から)→ S6F12 | CEID 20。レポート1000に23.5、1、"RCP-A" | 終わったら知らせてもらう |
| アラーム | S5F3 → S5F4、S5F1 → S5F2 | ALCD 0x82、"Chamber over temperature"。続けてCEID 60のS6F11 | 異常を知らせてもらう |
| 維持と切断 | Linktest → Separate | Linktest.rspあり | 回線の点検と終話 |
実際のログでは、状態の読み出しはこう見えます。並び順はホストが要求したSVIDの順(10、11、12、1002)で、最後の0x3が制御状態です。
S1F4
<L [4]
<F4 23.5 >
<U4 0 >
<A "RCP-A">
<B 0x3>
> .
S1F13は、装置とホストの双方から飛んだ
Selectが済むと、装置役もホスト役もすぐにS1F13を送りました。どちらか一方が会話を始めるのではなく、両方が名乗り、両方が応じる。どちらが先に出るかは回によって前後しましたが、この往復を済ませてから生存確認のS1F1に進む順番は、5回とも同じでした。
オンラインに上げるまで、装置は遠隔操作を任されていない
接続直後の制御状態は3(HOST_OFFLINE)でした。会話は成立しているのに、装置はまだオフライン扱いです。ホストがS1F17でオンラインを要求し、0x0が返った後、同じ変数を読み直すと5(ONLINE_REMOTE)に変わっていた。会話が成立した状態と、遠隔操作を任された状態は別物だと、ログの上で確かめられます。
イベントは、三段の準備を通って初めて届く
装置にイベントを報告させるには、ホストが三つの手順を踏みます。S2F33で「何を報告するか」(レポート1000にSV 10、11、12を束ねる)を定義し、S2F35で「いつ報告するか」(CEID 20と60にレポート1000を結び付ける)をリンクし、S2F37で「送ってよい」と有効化する。三つとも0x0が返ってから、S2F41で "START" を送りました。
装置役のSTART処理はウェーハ数を進めるように組んであり、直後のS6F11ではWaferCountが接続直後の0から1に変わっていました。
S6F11 W
<L [3]
<U1 1 >
<U1 20 >
<L [1]
<L [2]
<U2 1000 >
<L [3]
<F4 23.5 >
<U4 1 >
<A "RCP-A">
>
>
>
> .
S2F41への応答はHCACK 0x4でした。secsgem 0.3.0のソースでは、この値の定数名はACK_FINISH_LATERです。コマンドは受け付け、完了は後で知らせる。実際、完了の知らせはS6F11として別に届いています。
応答と要求をつなぐのは、システムバイト
どの応答がどの要求への返事なのかは、ストリームとファンクションの番号ではなく、ヘッダのシステムバイトで決まっていました。カウンタは送信側ごとに別で、開始値は無作為、送るたびに1ずつ増える。応答は要求の値をそのまま返します。たとえば正常1回目のS1F1は0x03d59e1bで出て、S1F2も0x03d59e1bで戻りました。装置側とホスト側のログを並べて読むときは、この値で行を合わせると迷いません。
ミリ秒の数字は、切り分けの物差しにだけ使う
| やり取り | 計時 | 中央値(最小〜最大) |
|---|---|---|
| Select.req → Select.rsp | ログ時刻 | 1.215ms(0.381〜1.49ms) |
| S1F1 → S1F2 | ログ時刻 | 2.122ms(1.135〜2.657ms) |
| S1F3 → S1F4 | ログ時刻 | 1.721ms(0.842〜2.01ms) |
| S2F41送信 → S6F11(CEID 20)受信 | ホストのアプリ側で計時 | 3.436ms(3.014〜4.0ms) |
正常5回、同じプロセス内の値で、装置の処理時間も工場のネットワークも入っていません。使い道は、実機の試験で何秒も待たされたときに「ライブラリ同士ならミリ秒単位で返るやり取りだった」と切り分けの起点に置くことだけです。
詰まるのは、エラーが返らない場所だった
失敗ケースを各1回流すと、装置役が明示的に断る場面より、黙る場面の方が厄介でした。
S1F13を飛ばしたホストは、黙って無視される
GEMの層を持たず、HSMSだけを話すホストを模しました。Selectは成功します。そこでS1F13を送らずにS1F1を投げると、返事がありません。
装置役はsecsgemの状態名でWAIT_CRAとWAIT_DELAYを行き来したまま(COMMUNICATINGに上がらず)、S1F1もS1F3も応答せずに捨てました。S9系のエラーメッセージも、HSMSのReject.reqも返らない。ホストは約3秒(試験用のT3)で2回ともタイムアウトし、その間も装置役は約5秒おきにS1F13を送り直していました(ホストのアプリ側計時で3,004.174ms/3,005.393ms、再送間隔は5,006.166ms/5,006.655ms。T3 3秒とestablish_communication_timeout 2秒の設定)。ホストがS1F14で応じた途端に装置役はCOMMUNICATINGへ移り、S1F1はすぐに返っています(1.486ms)。
対照的なのが、HSMSの層です。生のソケットからSelect前にS1F1を送ると、装置役はReject.req(stype 7、理由コード4)をはっきり返しました。
層によって、断り方が違う。HSMSは「まだ選択されていない」と返し、GEMは黙る。少なくともsecsgem 0.3.0ではそうでした。現場で「HSMSはつながったのに、タイムアウトばかり出る」と言われたら、最初に見るのはネットワークではありません。ホストがS1F13を送っているか、装置からのS1F13にS1F14で答えているか、です。
存在しないIDを聞くと、エラーではなく空が返る
定義していないSVID 9999を、実在する10と混ぜてS1F3で読みました。返ってきたのは、エラーコードではありません。
S1F4
<L [2]
<F4 23.5 >
<L>
> .
9999の位置に、空のリストが一つ置かれているだけです。S1F11で9999の名前を聞いても、名前と単位が空の文字列で返りました。レポートやコマンドの系統は違い、値で断ってきます。
| 送ったもの | 返った値 | secsgem 0.3.0ソース上の定数名 |
|---|---|---|
| S1F3 未定義SVID 9999 | その位置に空の <L> | (エラーコードなし) |
| S2F33 未定義VID 9999でレポート2000を定義 | DRACK 4 | VID_UNKNOWN |
| S2F35 未定義CEID 777をレポート2000にリンク | LRACK 5 | RPTID_UNKNOWN |
| S2F37 未定義CEID 777を有効化 | ERACK 1 | CEID_UNKNOWN |
| S2F41 未定義コマンド "FOO" | HCACK 1 | INVALID_COMMAND |
| S7F19(装置役に処理を実装していない) | S9F5(本体は元のヘッダ10バイト) |
LRACKは5でした。リンク先のレポート2000は、直前のS2F33で定義を断られていたものです。CEIDの未定義(ソース上は4、CEID_UNKNOWN)より先に、レポートの未定義が判定されたように見えます。間違いが二つ重なっていても、今回返ってきた理由は片方だけでした。ACKの値一つで原因を決め打ちしてはいけない。
厄介なのは、表の一行目です。ACKの値で断る応答は、ホストのログに残ります。空のリストは、何事もなかったように流れていく。SVIDの番号を一つ取り違えたまま本番に入ると、ホスト側が空の項目をどう扱うか次第で、気付くのが帳票の段階まで遅れかねません。
オフラインのまま、遠隔コマンドが通った
装置役をHOST_OFFLINEのままにして、S2F41で "START" を送りました。HCACKは4で、装置役のSTART処理も実際に走っています。規格の定めは別として、secsgem 0.3.0では通りました。オフライン中の遠隔コマンドをどう扱うかは、実装を見るまで分からない。自社の装置で、試験項目に入れておく価値があります。
ホストを再起動したら、イベントが消えた
この試験で、現場への影響が一番大きいと考えるのがこれです。
ホストAで三段の準備(定義・リンク・有効化)を済ませてから切断しました。装置役は、レポート1000とCEID 20のリンクを持ったままです。そこへ、購読の情報を何も持たない新しいホストBが接続し、S2F41で "START" を送りました。装置役は、昔の約束どおりS6F11を送ってきます。ホストBはレポート1000を知らないため、コールバックがKeyError: 1000で止まり、S6F0(中断)を返しました。ホストBのアプリケーションに届いたイベントは0件です。
再接続の場面では、もう一つ動きがありました。TCPが切れた後も、装置役のGEM通信状態はCOMMUNICATINGのまま残り(正常5回とも)、再接続時に装置役は自分からS1F13を送りません。ログには WrongSourceStateError ... 'select': COMMUNICATING が出ていました。
ホストの再起動は、ラインでは珍しくありません。上位の更新、サーバの入れ替え、夜間の保守。secsgem 0.3.0の装置役で観測したように、装置が古い購読を抱えたままになる実装だと、新しいホストは届いたイベントを読めずに捨てる。ホストは起動のたびにレポートを張り直す作りになっているか。接続試験で確かめるべきなのは、むしろここです。
遅れて届いた応答は、捨てられる
装置役がS1F4を5秒遅らせて返すように細工し、ホストのT3を3秒にしました。ホストは3,000.604msでタイムアウトし、結果は空(None)。S9F9は送られず、接続も切れません。5秒後に届いたS1F4は、"unexpected function received s01f04" という警告を残して捨てられました。同じ接続でS1F1を送り直すと、2.314msで返っています。
タイムアウトしたトランザクションの値は、後から来ても使われない。ホストの再要求をどう組むかは、この前提で決めることになります。既定値のT3は45秒ですが、装置が重い処理中に応答が遅れる場合の振る舞いは、実機でしか確かめられません。
試験ホストに使う前に知っておきたい、secsgem 0.3.0の癖
ライブラリは、本番のホストではなく「試験の相手」として使うのが妥当な位置付けです。
READMEには "This module is still work in progress." とあり、最新の公式リリースは0.3.0(2024年9月14日)、ライセンスはLGPL-2.1-or-laterです。今回の作業で、次の癖を踏みました。いずれも0.3.0での観測です。
- READMEのサンプルがそのままでは動かない:サンプルがimportする
communication_log_file_handlerモジュールが配布物に含まれておらず、ModuleNotFoundErrorになった - 型式名と版の指定が効かない:README式に
self.MDLNとSOFTREVを設定しても(今回はMDLNに "PROBE-EQ")、送られたのは "secsgem" と "0.3.0" だった。内部では別の属性が使われていた - T7が効かない:T7を2秒に設定し、Selectなしで5秒置いても接続は切れなかった。相手からのSeparate.reqも無視され、選択状態のまま残った。ソース上で実際に参照されているタイムアウトはt3・t5・t6のみ。Linktestの周期は30秒で固定されている(今回のデータには出ていない)
- S5F1とS5F3がWビットなしで送られる:それでもS5F2とS5F4は返ってきた
- IDが最小の整数型で送られる:SVID 10はU1、1002はU2、RPTID 1000はU2。決まった型を期待する実装が受け付けない可能性はあるが、これは推定で、実機では確かめていない
- macOSで装置役の停止が戻らないことがある:接続のたびに装置側のサーバスレッドで
OSError [Errno 57]が出た。ホスト切断から約0.3秒後にdisable()を呼んだ4ケースは6秒以内に戻らず、約5.5秒後に呼んだ正常5回は戻った。4ケースとも装置側サーバスレッドでUnboundLocalError: select_resultが記録された(正常5回では出ていない)。停止が戻らないこととの因果は推定で、実証はしていない。Linuxとは比べていない
試験の相手にするなら、型式名と版の値、T7、タイムアウトの扱いは、自社装置の仕様と同じだと思い込まないこと。この癖を知ったうえで、相手役として使います。
月曜日に使う、装置とホストの接続試験チェックリスト
本質は「つながるか」ではなく、「何かが返らなかったとき、誰が気付くか」です。
SEMI E37の要旨は、HSMSの目的を、互いの詳しい事情を知らなくても接続して相互運用できる実装を作れるようにすること、と書いています("connected and interoperate without requiring specific knowledge of one another")。一方でSEMI E5の要旨は、装置の機能を使い切るには "equipment-specific host software may be required"(装置ごとのホストソフトウェアが必要になり得る)と見込んでいる。SEMI E30も、追加のGEM機能をどこまで実装するかは "Equipment suppliers should work with their customers to determine"(装置メーカーが顧客と相談して決めるべき)としています。
規格は共通の土台を用意し、残りは装置ごとに決まる。その残りを、規格書ではなく試験で埋めるための一枚です。装置メーカーとの立ち会い試験や、上位システムの更新前に使ってください。右端の列は、今回のsecsgem 0.3.0同士のループバック試験で観測した結果で、実機の正解ではありません。
| 確認項目 | 送るもの・やること | 見るもの | 確認する人 | secsgem 0.3.0同士での観測 |
|---|---|---|---|---|
| 回線の確立 | Select.req | Select.rspが返るか | 自社で試験 | 返った |
| Select前の誤送信 | Select前にデータメッセージを送る | どう断られるか | 自社で試験 | Reject.req(理由コード4) |
| S1F13の扱い | S1F13を省いてS1F1を送る | 無応答か、エラーが返るか。ホストのタイムアウト処理 | メーカー/自社ホスト担当 | 無応答で破棄。T3(試験用3秒)でタイムアウト |
| 名乗りの中身 | S1F1、S1F13 | 型式名と版が仕様書と一致するか | メーカー | 設定に関わらず "secsgem" "0.3.0" |
| 制御状態 | 制御状態の変数をS1F3で読み、S1F17を送る | オフラインからオンラインに移るか | 自社で試験 | 3(HOST_OFFLINE)から5(ONLINE_REMOTE) |
| 未定義ID | 存在しないSVID・VID・CEID・コマンド | エラーコードか、空の応答か | メーカー | SVIDは空のリスト、他は値で拒否 |
| レポート三段 | S2F33 → S2F35 → S2F37 | 各ACKと、その後イベントが届くか | 自社で試験 | 三つとも0x0、S6F11が届いた |
| オフライン中のコマンド | オフラインのままS2F41 | 拒否されるか、実行されるか | メーカー | HCACK 4で受け付け、処理も実行 |
| 遅延応答 | 装置が重い処理中に問い合わせる | タイムアウト後の遅れた応答をどう扱うか | 自社ホスト担当 | 捨てられ、接続は維持 |
| ホスト再起動 | ホストを再起動し、最初のイベントを待つ | イベントが読めるか。ホストが起動時にレポートを張り直すか | 自社ホスト担当 | 装置役が古い購読を保持、S6F0で中断、届いたイベント0件 |
「メーカー」の行は問い合わせで、「自社で試験」の行は立ち会い試験で確かめられます。手間がかかるのは下の二行で、ここはホストの作りと運用手順の話になる。上位システムの担当者と一緒に読む価値があるのは、その二行です。
最初の一手は小さくていい。手持ちのHSMS対応装置1台について、メーカーに「S1F13を送らないホストにどう応答するか」を聞いてください。前回の棚卸し表がある場合は、HSMS対応の列から一台選んでこの表を当ててみてください。空欄が残った行が、次にメーカーへ聞くべき質問になります。データ収集の経路そのものを検討している場合は、EDA(Interface A)の記事も併せてどうぞ。
参考資料
- secsgem 0.3.0(PyPI):2024年9月14日公開、LGPL-2.1-or-later
- secsgem documentation(HSMSの説明、対応範囲)
- bparzella/secsgem(GitHub):README、ソースコード
- SEMI E30-0526:Specification for the Generic Model for Communications and Control of Manufacturing Equipment (GEM)(SEMI Store)
- SEMI E37-0222:Specification for High-Speed SECS Message Services (HSMS) Generic Services(SEMI Store)
- SEMI E5-0725:Specification for SEMI Equipment Communications Standard 2 Message Content (SECS-II)(SEMI Store)
- techandchips 自社実測:secsgem 0.3.0 ループバック試験(2026年10月9日、macOS 26.7.1/CPython 3.13.5、正常5回・失敗ケース各1回)
- SECS/GEM非対応の装置は三列に分けてMESに繋ぐ|HSMS対応・SECS-Iのみ・通信なし(techandchips)
