既存の実験装置をSiLA 2へ接続するとき、装置の通信処理をSiLA Serverへ直接書き込むと、保守しにくい「巨大なドライバー」になりがちです。実務では、SiLA Feature、装置に依存しない共通ドライバー、SCPI・シリアル通信・メーカーSDKを扱うアダプターの3層に分けると、装置交換と試験が容易になります。
この記事では、温度調節装置を例に、既存装置をSiLA 2の共通インターフェースへ変換するラッパー設計を解説します。SCPI、行指向シリアル、メーカーSDKを同じ操作で扱うPythonコードも用意し、実機を使わず正常系と代表的な異常系を検証しました。
この記事で学べること
- 「SiLA 2対応」と「既存通信をSiLA 2で包むこと」の違い
- SiLA Feature、共通ドライバー、装置アダプターの責任分担
- SCPI、シリアル通信、メーカーSDKを選ぶ判断基準
- タイムアウト、不正応答、装置エラーを共通エラーへ変換する方法
- 実機導入前に模擬装置で検証すべき項目
仕様・SDKの確認日:2026年10月13日。本文では、SiLA 2の規格上の考え方、各ライブラリ固有の動作、R&D Compass編集部の設計推奨を区別して記載します。
結論:装置固有通信はSiLA Featureから隔離する
SiLA 2は、装置が提供する能力をFeatureとして公開し、ClientがCommandやPropertyを介して利用する仕組みです。Featureは「温度を設定する」「現在温度を読む」といった意味を表し、装置が内部でSCPIを使うか、RS-232の独自文字列を使うか、DLL形式のSDKを使うかまでClientへ見せる必要はありません。SiLA公式も、ServerがFeatureを実装し、ClientはFeatureを通じてServerの能力を利用する構造を説明しています[1]。
推奨する構造は次の4段です。
| 層 | 役割 | 装置交換時の変更 |
|---|---|---|
| ワークフロー/SiLA Client | 実験条件を指定し結果を受け取る | 原則なし |
| SiLA Feature実装 | Command・Property・SiLAエラーを提供する | 意味が同じなら原則なし |
| 共通ドライバー | set_target、read_statusなど装置非依存の契約を定義する | 原則なし |
| 装置アダプター | SCPI、シリアル、SDKを実際に呼び出す | ここを差し替える |
この分離はSiLA 2の必須実装方式ではなく、編集部の推奨設計です。しかし、Featureの意味と装置通信を分けることで、同じSiLA Serverを複数メーカーの装置へ展開しやすくなります。
SCPI・シリアル・メーカーSDKは何が違うのか
SCPI:計測器で広く使われる共通のコマンド言語
SCPIは、コンピューターと試験・計測器の間で使う共通コマンド言語です。IEEE 488.2を基礎とするソフトウェア規格で、ASCII文字列としてGPIB、RS-232、LANなど複数の通信経路で利用できます[2]。つまり、SCPIはケーブル規格ではありません。
一般に、値を設定するCommandと、末尾に「?」を付けて値を取得するQueryを使います。例えば、仮想的な温度装置なら、SOUR:TEMP 40で設定し、MEAS:TEMP?で温度を問い合わせます。SCPIのコマンドは木構造を持ち、*IDN?などの共通コマンドと、コロンで階層を表すサブシステムコマンドがあります[3]。
向いている場合:装置マニュアルにリモートコマンド一覧があり、コマンド体系が比較的安定している場合です。PythonではPyVISAを使うと、GPIB、RS-232、USB、Ethernetなどの違いをある程度吸収できます[4]。
行指向シリアル:単純だが、細部を自分で決める必要がある
RS-232やUSB仮想COMポートでは、装置独自の文字列を送受信する場合があります。例えばSET T=40.00\r\nを送り、OK\r\nを受け取る方式です。仕組みは単純ですが、ボーレート、データ長、パリティ、ストップビット、フロー制御、文字コード、終端文字、読取タイムアウトを一致させる必要があります。pySerialのAPIも、これらを個別パラメーターとして扱います[5]。
向いている場合:通信仕様が公開され、応答形式が明確で、メーカーSDKへ依存したくない場合です。ただし「改行を待ち続けて停止する」「途中まで届いた文字列を正常応答と誤認する」といった事故を避ける実装が必要です。
メーカーSDK:高機能だが、配布条件と保守性を確認する
メーカーSDKは、複雑な装置機能を高水準のメソッドとして提供します。バイナリデータ、校正、装置状態、特殊な同期処理を扱いやすい一方、特定OS、特定Python・.NET版、USBドライバー、ライセンス、GUIセッションに依存する場合があります。
向いている場合:公開プロトコルだけでは必要機能へ到達できない場合、SDKが公式に保守されている場合、SDKの戻り値と例外をテストできる場合です。「SDKがあるから最も安全」とは限りません。更新方針、対応OS、再配布条件、ヘッドレス運転可否を調達時に確認します。
ラッパー設計の中心は「共通契約」である
最初にSCPI文字列を書くのではなく、SiLA Featureが必要とする装置能力をPythonのProtocolとして定義します。次の例では、装置種別にかかわらず、識別、目標温度設定、状態取得という3操作だけを公開します。
class TemperatureDevice(Protocol):
def identify(self) -> str: ...
def set_target_c(self, value: float) -> None: ...
def read_status(self) -> DeviceStatus: ...
SiLA側のサービスはこの共通契約だけを参照します。
class TemperatureFeatureService:
def __init__(self, device: TemperatureDevice) -> None:
self._device = device
def set_target_temperature(self, value: float) -> None:
self._device.set_target_c(value)
def get_current_temperature(self) -> float:
return self._device.read_status().temperature_c
公式SDKで生成したFeature Baseクラスでは、Command実装からこのサービスを呼び出します。SDKのメソッド名やデコレーターは実装ごとに異なるため、規格そのものと混同しないことが重要です。SiLA Featureの分け方やデータ型の決め方は、別記事「SiLA 2のFeature設計」で詳しく扱います(公開後に内部リンクを追加予定)。
3種類のアダプターをどう実装するか
SCPIアダプター:writeとqueryを区別し、エラーキューを確認する
設定コマンドは送信に成功しても、装置内部で拒否されることがあります。そのため、通信成功と処理成功を分けて判定します。実装例では設定後にSYST:ERR?を問い合わせ、0,No error以外を装置実行エラーへ変換します。
def set_target_c(self, value: float) -> None:
validate_target(value)
self._io.write(f"SOUR:TEMP {value:.2f}")
error = self._query("SYST:ERR?")
if not error.startswith("0,"):
raise DeviceExecutionError(f"SCPI error queue: {error}")
実機では、装置マニュアルが定めるエラー取得方法、コマンド完了待ち、ステータスレジスターを優先してください。全装置がこの仮想コマンドを実装するわけではありません。
シリアルアダプター:終端文字と部分書込みを確認する
シリアル通信では、送信したバイト数、受信終端、文字コードを明示的に確認します。空応答はタイムアウト、終端なしはプロトコル違反として分けます。
payload = command.encode("ascii") + b"\r\n"
if port.write(payload) != len(payload):
raise DeviceProtocolError("serial partial write")
raw = port.read_until(b"\r\n")
if not raw:
raise DeviceTimeout("serial timeout")
if not raw.endswith(b"\r\n"):
raise DeviceProtocolError("terminator was not received")
pySerialではtimeoutとwrite_timeoutを設定できます[5]。無期限待機を本番のServerスレッドに持ち込まないことが重要です。
SDKアダプター:メーカー例外を外へ漏らさない
メーカーSDKの例外クラスや数値エラーコードを、そのままSiLA Clientへ公開すると、装置交換でClientまで変更が必要になります。アダプター内で、入力不正、タイムアウト、応答形式不正、装置実行失敗などの共通分類へ変換します。ただし、保守ログには元の例外、エラーコード、SDK版、装置シリアル番号を残します。
SiLAエラーへどう対応付けるか
| 共通ドライバーの結果 | SiLA側の扱い | 再試行の考え方 |
|---|---|---|
| 入力範囲外 | Validation Error | 同じ入力では再試行しない |
| 装置が条件を拒否 | Defined Execution Error | 原因を解消後に判断 |
| 応答形式不正 | DefinedまたはUndefined Execution Error | 自動再試行前に状態確認 |
| 通信タイムアウト | 実行状態に応じてDefined/接続エラー | 二重実行を防ぐ |
| 予期しないSDK例外 | Undefined Execution Error | ログと装置状態を調査 |
タイムアウトしたからといって、処理が実行されていないとは限りません。応答だけ失われ、装置は設定を変更済みかもしれません。書込み系Commandを無条件に再送すると二重注入、二重測定、二重搬送につながります。再試行前に現在値、装置状態、実行IDを確認できる設計にします。
導入手順:1台を小さく包み、境界を試験する
- 操作一覧を作る:設定、読取、開始、停止、校正、結果取得を列挙する。
- 危険操作を分ける:衝突、過熱、加圧、薬品移送などは装置内安全機能と責任分界を決める。
- 最小Featureを決める:最初は識別、状態取得、安全な1操作に絞る。
- 共通契約を定義する:単位、範囲、状態、例外を装置非依存で記述する。
- アダプターを実装する:SCPI、シリアル、SDK固有処理を閉じ込める。
- 模擬装置で試験する:正常応答だけでなく、無応答、遅延、途中応答、不正値、SDK例外を発生させる。
- 実機PoCを行う:電源再投入、ケーブル抜去、装置ローカル操作との競合、長時間運転を確認する。
- SiLA Serverへ統合する:Feature Command・Propertyと共通サービスを結び付ける。
- 運用情報を固定する:装置ファーム、SDK、ドライバー、VISA、設定ファイルの版を記録する。
実験装置とLIMS・データベースを結ぶ全体像は、実験装置・LIMS・データベースを連携する設計も参考になります。規格の役割分担は、実験自動化の通信・制御・標準を整理するで整理しています。
実行できるPython例と検証結果
サンプルコードは標準ライブラリだけで動きます。SCPI、シリアル、SDKの模擬バックエンドを同じTemperatureDevice契約へ接続し、Featureサービスから40℃を設定して状態を読みます。実機へ置き換える際は、FakeScpiTransportをPyVISA Resource、FakeSerialPortをserial.Serial、FakeVendorSdkをメーカーSDKオブジェクトへ差し替えます。
python3 device_adapter_demo.py
python3 -m unittest -v test_device_adapter_demo.py
検証環境では9件の自動試験がすべて成功しました。
| 試験 | 期待結果 | 結果 |
|---|---|---|
| SCPI・シリアル・SDKの共通操作 | 40℃設定とREADY取得 | 成功 |
| 設定範囲外 | 装置へ送る前に拒否 | 成功 |
| SCPIタイムアウト | DeviceTimeoutへ変換 | 成功 |
| SCPIエラーキュー | DeviceExecutionErrorへ変換 | 成功 |
| SCPI数値不正 | DeviceProtocolErrorへ変換 | 成功 |
| シリアル無応答・終端欠落・形式不正 | 異常を区別して検出 | 成功 |
| メーカーSDK例外 | 共通実行エラーへ変換 | 成功 |
この試験は設計例のロジックを検証したもので、特定メーカー装置との相互接続試験ではありません。PyVISAの利用にはVISAバックエンド、シリアル実機には正しい電気仕様とポート設定が別途必要です。
よくある失敗
失敗1:Feature実装へSCPI文字列を直接散らす
コマンド変更が複数箇所へ波及し、模擬試験もしにくくなります。アダプターへ集約し、SiLA側は共通契約だけを見るようにします。
失敗2:応答が返れば成功と判断する
装置がエラー文字列を返している、値が適用範囲へ丸められた、処理がまだ完了していない可能性があります。エラーキュー、状態、実際の設定値を確認します。
失敗3:タイムアウト後に同じCommandを即時再送する
装置側で処理済みなら二重実行になります。読取可能な現在状態と、処理を一意に識別する情報を設計します。
失敗4:SDKの型と例外をFeatureへ漏らす
Clientがメーカー固有実装へ依存します。アダプターで共通データ型とエラーへ変換し、詳細はログへ残します。
失敗5:SiLA Serverを安全制御装置として扱う
ネットワーク越しのServerは、非常停止、インターロック、過温・過圧保護の代替ではありません。安全機能は装置、PLC、安全リレーなど適切な層で実装し、SiLAは上位の操作と状態取得を担います。
限界・不確かさ・責任範囲
ラッパーは異なる通信方式を同じ意味へそろえますが、装置能力そのものを同一にするわけではありません。温度精度、設定分解能、更新周期、校正状態、処理完了条件が異なるなら、共通インターフェースでもその差を明示する必要があります。
また、SiLA 2接続が成立しても、危険な操作が安全になるわけではありません。装置メーカーは装置内部の安全仕様、システム統合者はインターフェースとワークフロー、利用組織はリスク評価・権限・手順・教育に責任を持ちます。自動運転へ進む前に、実験自動化の導入手順と、自律実験の仕組みと導入手順も確認してください。
導入前チェックリスト
- 通信方式、コマンド仕様、SDK版、対応OSが文書化されている
- 読取タイムアウトと書込タイムアウトを設定した
- 終端文字、文字コード、単位、小数点、ロケールを固定した
- 装置エラーと通信エラーを区別できる
- タイムアウト後に処理済みか確認できる
- 同じ操作の二重実行を防止できる
- 装置交換時にアダプターだけを差し替えられる
- 模擬装置で無応答、不正応答、SDK例外を試験した
- 実機で電源断、再接続、ローカル操作との競合を試験した
- 非常停止とインターロックがネットワークから独立している
FAQ
Q1. SCPI対応なら、そのままSiLA 2対応ですか?
いいえ。SCPIは装置コマンド言語、SiLA 2はFeatureを公開するClient/Server標準です。SCPIコマンドを呼ぶSiLA Serverを作ることで両者を接続できます。
Q2. PyVISAとpySerialはどちらを使うべきですか?
装置がVISA Resourceとして扱え、SCPIなどのコマンド仕様があるならPyVISAが便利です。独自の行プロトコルを仮想COMポートで扱うならpySerialが直接的です。装置マニュアルとサポート範囲を優先してください。
Q3. メーカーSDKがある場合も共通ドライバーは必要ですか?
長期運用や装置交換を考えるなら有効です。SDKのメソッド、型、例外をアダプター内に閉じ込めることで、SiLA Featureを安定させられます。
Q4. 1台の装置を複数Clientから操作できますか?
技術的に接続できても、同時操作が安全とは限りません。排他制御、所有権、予約、状態遷移、タイムアウト後の解放を設計してください。
Q5. 既存装置を包めば、メーカー保証は維持されますか?
保証条件は製品ごとに異なります。公開API・SDKの使用条件、サポート対象のドライバー、遠隔操作の制限をメーカーへ確認してください。
まとめ
既存装置をSiLA 2へ接続する要点は、装置通信をSiLA Featureへ直書きせず、共通ドライバーと装置アダプターへ分離することです。SCPIは共通コマンド言語、シリアル通信は低レベルの送受信、メーカーSDKは製品固有APIであり、それぞれのエラーや戻り値を共通の意味へ変換します。
最初のPoCでは、1台・1Feature・1つの安全な操作から始め、正常系より先に無応答、不正応答、装置拒否、二重実行の危険を試験してください。そうすることで、装置を交換しても上位ワークフローを変えにくいSiLA 2接続へ近づけます。
参考文献
- SiLA Association, “Standards – High Level Overview,” SiLA 2 Core, Mapping and Features. https://sila-standard.com/standards/(2026年10月13日確認)
- IVI Foundation, “The SCPI Standard.” https://www.ivifoundation.org/About-IVI/scpi.html(2026年10月13日確認)
- Keysight Technologies, “SCPI Basics,” instrument help documentation. https://helpfiles.keysight.com/csg/n5106a/scpi_basics.htm(2026年10月13日確認)
- PyVISA Project, “PyVISA 1.16.1 documentation.” https://pyvisa.readthedocs.io/en/1.16.1/(2026年10月13日確認)
- Chris Liechti et al., “pySerial API,” pySerial 3.5 documentation. https://pyserial.readthedocs.io/en/latest/pyserial_api.html(2026年10月13日確認)


