# サーバーとクライアントの実装仕様 この章は、`src/dobot/server_fastapi/` の提供された実装に基づき、**MG400向け `DobotCtrl` を共通制御I/Fとして公開する**構成を説明します。ロボット固有の制御APIを `ese774_frame` が定義するわけではありません。 ## 制御経路 - ローカル:アプリケーション → `DobotCtrl` → `DobotTcp` → MG400 - リモート:アプリケーション → `SyncDobotClient` / `AsyncDobotClient` / `DeviceProxy` → `ese774_frame` → サーバー上の `DobotCtrl` → `DobotTcp` → MG400 サーバー側の `FastApiServer` は `device_cls=DobotCtrl`、`router_cls=None`、`api_spec=None`、`object_name="dobot"` を指定します。独自RouterやAPI定義を追加することが必須ではない、自動ディスパッチ構成です。 ## サーバーの起動 既存の `dobot.server_fastapi.server` モジュールは、`Config` のクラス属性を読み込んでサーバーを構築します。初期値は `SERVER_IP="127.0.0.1"`、`SERVER_PORT=8000`、`DOBOT_IP="192.168.1.6"` です。 ```bash python -m dobot.server_fastapi.server ``` **注意:** この起動モジュールは、読み込み時に `FastApiServer` インスタンスを生成します。外部のPythonプロセスで `Config.load_yaml()` を実行しても、その変更が別プロセスのサーバーに伝わるわけではありません。設定値を変更するには、サーバー生成前に同一プロセスで `Config` のクラス属性を設定する起動スクリプトを用意してください。既存モジュールにYAMLの自動読込処理があるとは説明しません。 以下は、**設定を読み込んでからサーバーを生成する独立した起動スクリプト**です。`Config.load_yaml()` は、相対パスを呼び出し元ファイルの位置から解決するため、ここでは絶対パスを使います。 ```python from pathlib import Path from dobot.config import Config from dobot.dobot_ctrl import DobotCtrl from ese774_frame import FastApiServer from x_logger import XLogger Config.load_yaml(Path(__file__).resolve().parent / "config_dobot_server.yaml") logger = XLogger(log_level=Config.LOGGER_LEVEL, logger_name=Config.SERVER_LOGGER_NAME) server = FastApiServer( device_cls=DobotCtrl, router_cls=None, config=Config, api_spec=None, object_name="dobot", device_kwargs={"dobot_ip": Config.DOBOT_IP, "instance_name": Config.INSTANCE_NAME}, logger=logger, logger_name=Config.SERVER_LOGGER_NAME, lifespan_msg_prefix="DOBOT", ) server.run(host=Config.SERVER_IP, port=Config.SERVER_PORT) ``` ```yaml SERVER_IP: "127.0.0.1" SERVER_PORT: 8000 DOBOT_IP: "192.168.1.6" INSTANCE_NAME: "Ctrl" LOGGER_LEVEL: "INFO" ``` `SERVER_IP` はHTTPサーバーの待受アドレス、`DOBOT_IP` はMG400本体のアドレスであり、同じ役割ではありません。外部からのアクセスを許す場合は、認証・ネットワーク分離などを別途検討してください。HTTP経由の操作は実機を動かし得ます。 ## 同期・非同期クライアント `SyncDobotClient` は `SyncDeviceClient`、`AsyncDobotClient` は `AsyncDeviceClient` を継承します。どちらも `object_name="dobot"`、`api_spec=None` を親クラスに渡します。明示的な接続先を指定する例: ```python from dobot.server_fastapi.client_sync import SyncDobotClient client = SyncDobotClient(server_ip="127.0.0.1", server_port=8000) ``` ```python from dobot.server_fastapi.client_async import AsyncDobotClient client = AsyncDobotClient(server_ip="127.0.0.1", server_port=8000) ``` **重要:** 両クライアントのコンストラクタ引数 `server_ip` と `server_port` の既定値は `None` です。`config` も渡さない場合、ソースコード上では `http://None:None` が組み立てられます。接続先を明示するか、`Config` インスタンスを渡してください。`config` が指定されると、その `SERVER_IP` と `SERVER_PORT` が個別の引数より優先されます。 `DeviceProxy` は `server_fastapi/__init__.py` で `DobotCtrl` と別名 `dobot` に登録されています。既定の `default_async_mode=True` は、**ロボットの動作完了を待つ指定ではありません**。クライアントの通信形態と、ロボット動作の完了待ちは区別してください。 ## 仕様の境界 本章のコードは提供されたPython実装とクラスの初期化引数を示すものです。通信先のMG400、サーバーの起動環境、`ese774_frame` のインストール版、実機動作の検証は別途必要です。安全停止を通常のHTTPメソッドの応答だけに依存させないでください。