デバイスサーバー開発ガイド / gRPC Quick Start / トップ
このページは gRPC Frame を使用したデバイスサーバーの実装方法を扱う。機器操作そのものは DeviceClass に置き、通信上の要求・応答、ストリーミング、イベント配信は Frame とその周辺のクラスで扱う。導入方法はインストールマニュアルに分離する。
create_grpc_server(ctrl_obj=...) は DeviceClass のインスタンスを受け取る。GrpcClient は接続時に Describe を実行し、公開メソッドをクライアントに動的にバインドする。呼び出しは Call を経由する。個々の DeviceClass のために RPC メソッドを .proto に逐一追加する必要はない。
from grpc_frame.grpc_server import create_grpc_server
server = create_grpc_server(ctrl_obj=ctrl, max_workers=10)
公開されるメソッド、戻り値の変換、例外の伝達は Frame のディスパッチ/アダプタに依存する。任意の Python オブジェクトが無条件に透過転送されるわけではない。公開対象とデータ型は動作試験で確認する。
from grpc_frame.grpc_client import GrpcClient
class InstrumentGrpcClient(GrpcClient):
def __init__(self, server_ip: str, server_port: int):
super().__init__(server_ip=server_ip, server_port=server_port)
def read_and_report(self):
return self.read_value() # DeviceClass 側で公開したメソッド
read_and_report はクライアント側の操作をまとめた例であり、Frameが自動生成するRPCではない。専用クライアントの実例は aandd_reader/server_grpc/aandd_reader_grpc_client.py にある。接続終了時は close() を呼ぶ。
aandd_reader は AsyncAanddReaderGrpcClient を提供し、await client.meas() の形で利用する。非同期化の内部方式は、利用するクライアント実装を確認する。同期クライアントと同じ名前のメソッドが存在しても、戻り値や実行方式が同一とは限らない。
import asyncio
from aandd_reader import Config
from aandd_reader.server_grpc import AsyncAanddReaderGrpcClient
async def main():
client = AsyncAanddReaderGrpcClient(config=Config)
try:
print(await client.meas())
finally:
client.close()
asyncio.run(main())
この例は Config がサーバーアドレス・ポートを設定済みであることを前提とする。
StreamCall は通常の単一応答 Call とは別のRPCである。MiniPIXの実装では、サーバー側の _MiniPixStream が取得コールバックをキューへ渡し、ジェネレータで測定フレームを順次返す。制御用の ctrl_obj とストリーム用の stream_obj を分けて扱う実装がある。
# サーバー側:stream_obj を受け取る実装の概念例
server = create_grpc_server(ctrl_obj=ctrl, stream_obj=stream_obj)
stream_obj の具体的なメソッド名・引数とクライアントの stream_call(...) の対応は、MiniPIXの pixet_grpc_server.py と async_pixet_grpc_client.py を参照する。ストリームの中断、キューの滞留、取得側の例外、切断時の後始末を実装・検証する。
gRPC Frameには EventBus を使用するイベント配信経路があり、GrpcClient.subscribe(topic=..., once=...) で受信する。ストリームによる測定データの逐次転送と、条件成立などを通知するイベント購読は別の機能である。
aandd_reader の専用クライアントは、イベント測定の準備操作を prepare_event_measurement() にまとめている。
client.prepare_event_measurement(
topic="weight_threshold",
threshold_g=10.0,
above=True,
once=True,
trigger_mode="raw",
)
event = client.wait_event()
print(event)
client.stream_stop()
このAPIは aandd_reader固有の上位APIであり、GrpcClient 共通メソッドではない。内部では stream_start()、event_set_config()、set_trigger_mode()、event_arm() を呼び、wait_event() は subscribe(topic=..., once=True) を使用する。閾値判定はDeviceClass側の測定機能に属し、購読の通信経路はFrameが扱う。once の意味はイベントのarm側と購読側で区別する。
専用クライアントのメソッドを補完可能にするには、DeviceClassの公開メソッドだけでなく、クライアント側で追加・オーバーライドしたメソッドも型定義に反映する。MiniPIXとaandd_readerの server_grpc/make_pyi.py はその実装例である。DeviceProxy を使用しない直接クライアント接続も可能である。登録・生成の扱いはDeviceProxyとFactoryを参照する。
サーバー起動時は add_insecure_port の戻り値を検査し、start() 後に接続を確認する。aandd_reader_grpc_server.py は channel_ready_future による自己接続確認、停止時の server.stop(...) と ctrl.close() を実装している。insecure_channel は暗号化しないため、配置ネットワークの安全性を別途検討する。大きなデータを扱う場合は grpc_options のメッセージサイズ制限も確認する。
aandd_reader:通常RPC、同期・非同期クライアント、イベント購読。mini_pix:測定データの StreamCall、サーバー側ジェネレータ、クライアントの拡張。cobotta2:gRPCサーバー・クライアントの別実装。詳細な実装断片は既存のgRPC実装例を参照する。