puda-edge について
puda-edgeは、機器ハードウェアをラップし、型付きコマンドをNATS経由で公開するPUDAエッジサービス構築用のPythonスキルです。SDK/APIとGUIの実装、設定、安全情報、検証手順を扱います。
主な機能
- 01SDK/APIとGUIエッジのガイド
- 02型付き機械コマンドとドキュメント
- 03コマンドの安全情報メタデータ
- 04設定とテレメトリーの指針
- 05オフラインおよび実機での検証手順
活用シーン
- 01計測機器SDK用Pythonラッパーの構築
- 02NATS経由でのGUI操作ワークフロー公開
- 03エージェント向け機械操作の安全情報記述
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ pudap/ skills --skill puda-edgeインストール後、Claude Code で/puda-edgeを入力して読み込まれたか確認します。
同梱ファイルreferences/gui-edge.md
詳細
Puda Edge
NATS に接続し、装置のコマンドを公開する薄いハードウェアラッパーである Python エッジサービスの作成を支援します。
エッジの構築
適切な場合は、既存の装置 SDK/API を使用してください。デスクトップソフトウェアを介して操作する機器には、GUI エッジを構築します。AI はマニュアルまたはスクリーンショットとタスクの指示を使って、装置固有の Python ワークフローを作成し、PUDA がそれを NATS 経由で公開します。
GUI で作業する場合は、references/gui-edge.md をお読みください。GitHub から PUDAP/edge-python-gui-template をひな形としてクローンし、実例として PUDAP/opentrons-gui-edge を使用してください。このガイドでは、タスクの指示を決定論的な GUI コマンドに変換し、検証する方法を説明しています。入手できる場合は、ベンダーの PDF マニュアルを使用してください。マニュアルがない場合は、クリックする場所、入力する内容、期待される結果を示すスクリーンショットも、アトミックコマンドの有効なコンテキストになります。どちらの情報源にも、利用できる場合は実際の操作画面のキャプチャを補足してください。
SDK/API エッジと GUI エッジでは、次の点に注意してください。
- ひな形から作成を始める前に、選択したひな形の依存関係と SDK の仕様を確認してください。GUI の例では
from puda import EdgeNatsClient, EdgeRunner, commandを使用しています。 - 装置コマンドは型付きで JSON 互換にし、パラメーター、単位、デフォルト値、前提条件、返される証拠、失敗について記述してください。意図したワークフローを
@commandで公開してください。GUI エッジでは、低レベルのリモートコマンドはcapture_screenshotのみとし、継承された GUI ヘルパーを内部で使用して高レベルのワークフローを実装してください。 - 装置の ID、NATS サーバー、接続やウィンドウの詳細は、設定と
.env.exampleで指定してください。ひな形のライフサイクル管理とクリーンアップを維持してください。別の装置の認証情報や動作中の.envをコピーしないでください。 - デスクトップまたはハードウェアで検証する前に、オフラインでコマンドを確認してください。実装した内容、フィクスチャでテストした内容、デスクトップ上で確認した内容、ハードウェアで実行した内容を分けて報告してください。
リポジトリの構成、main.py の設定、テレメトリー、複数装置を接続する PC については、新しい装置の統合 に従ってください。SDK/API エッジは edge-python-template をひな形として作成し、GUI エッジには上記の GUI ひな形を使用してください。リポジトリ名は puda-<machine_id>-edge にしてください。
Python のみを使用してください。ホスト/NATS/ハードウェアの導入と設定には puda-deployment を使用してください。コマンドが動作したら、puda で CLI をインストールしてください。
ひな形の作成
- ひな形からリポジトリを作成します。すべての
TODOを解決してください。 .envに、一意の小文字とハイフンで構成されたMACHINE_IDとNATS_SERVERSを設定します。driver.pyを実装してから、設定とドライバーをmain.pyに接続します。- ヘルパーは非公開(
_name)のままにします。公開されるのは@commandメソッドのみです。
エッジの接続後、puda machine commands <machine_id> で確認してください。
1 台の PC にある複数の機器は、1 つの uv ワークスペースを共有できます。各サブディレクトリには、それぞれ独自の MACHINE_ID、driver.py、main.py を用意します。ドキュメントと PUDAP/ViPSA を参照してください。
ドライバー
driver.py はハードウェア API を薄くラップします。メソッド名、docstring、パラメーター、戻り値の注釈が、エージェントに見えるコマンドインターフェイスになります。Driver クラスの docstring に1文で概要を記載してください。EdgeRunner は puda machine list と puda machine ping で最初の段落を表示するため、エージェントはマシンについて知るためだけに puda machine commands を実行する必要がありません。
- リモートから呼び出せるメソッドすべてに
@commandを付けてください。デコレーターのないパブリックメソッドは、NATS 経由で表示も呼び出しもできません。@commandメソッドがないドライバーは、起動時に失敗します。 - コマンドはアトミックにしてください。1つのメソッドにつきハードウェア操作は1つです。
- パラメーターにはプリミティブ(
str、int、float、bool)またはプリミティブの単純なリスト/辞書を使用してください。 - パブリックな docstring にはすべて、引数、戻り値、発生するエラーを記載してください。これらはエージェントにコンテキストを提供します。
- 失敗時には、コマンド、対象、ハードウェアの応答を含めて例外を発生させてください。
Falseを返しても PUDA への応答は成功として扱われます({"result": false})。 shutdown、home、resetは任意です。エッジの停止前にshutdownが実行されます。homeはpuda machine homeによって呼び出されます。puda machine resetは必ずアクティブなrun_idをクリアしてから、resetがあれば呼び出します。
from puda import command, safety
class Driver:
"""Software-only PUDA test machine. Commands are simulated in memory; no hardware is required."""
@command
def shutdown(self) -> bool:
"""Release hardware resources. If defined, called before the edge stops."""
...
@command
def home(self) -> bool:
"""Home the machine. If defined, triggered by `puda machine home <machine_id>`."""
...
@command
def reset(self) -> bool:
"""Software reset. Optional. `puda machine reset` clears the run first, then calls this if present."""
...
@command
def move_to(self, x_mm: float, y_mm: float, z_mm: float) -> bool:
"""
Move the machine head to an absolute position.
Args:
x_mm: Target X position in millimeters.
y_mm: Target Y position in millimeters.
z_mm: Target Z position in millimeters.
Raises:
RuntimeError: If the hardware rejects the move.
"""
result = self._hardware.move_to(x_mm=x_mm, y_mm=y_mm, z_mm=z_mm)
if not result.ok:
raise RuntimeError(
"Failed to move machine head "
f"to x={x_mm}, y={y_mm}, z={z_mm}: {result.error}"
)
return True
@safety
@command メソッドに @safety を付けると、コマンドカタログに参考情報を公開できます。エッジでのディスパッチはブロックしません。@command のない @safety は無視されます。
5つのフィールドはすべてキーワード専用です。他のフィールドは追加しないでください。
| フィールド | 必須 | 役割 |
|---|---|---|
summary | はい | リスクの概要 |
hazards | いいえ | collision、thermal などの短いタグ |
requires | いいえ | 前提条件。エージェントは先行する手順を挿入するか、まず確認します |
forbidden_when | いいえ | コマンドを使用してはならない状況 |
confirm | いいえ | オペレーターによる yes の確認ゲート。既定値は false です。有効にするには true を設定します |
同じ文を複数のフィールドで繰り返さないでください。summary はリスク、requires は前提条件、forbidden_when は禁止条件、confirm=True は確認プロンプトを示します。summary に「confirm…」を記載しないでください。
@command
@safety(
summary="Collision risk from unhomed motion or an occupied workspace.",
hazards=["collision"],
requires="Machine must just have been homed.",
forbidden_when="Do not move if the workspace is occupied or human movement is detected.",
confirm=True,
)
def move_to(self, x: float, y: float, z: float) -> dict:
...
読み取り専用または無害なコマンド(get_position、echo)には @safety を付けないでください。動作、化学物質の混合、加熱、加圧、その他の不可逆なハードウェア操作には confirm=True を使用してください。
設定
.env に MACHINE_ID と NATS_SERVERS を記載してください。main.py の Config に型付きハードウェアフィールドを追加し、値が不足している場合は起動時に失敗するようにしてください。これらのフィールドを Driver(...) に渡します。
テレメトリーは JSON にシリアライズ可能でなければなりません。ハートビートと、マシンが実際に持つ位置、ヘルス、状態を公開してください。フィールド名には、直交座標のテンプレートではなく、ハードウェアに合った名前(joints、plunger、focus)を使用してください。
リモート更新
puda machine update
使用する前に puda machine update --help を確認し、インストール済み CLI の対象指定と更新オプションを確認してください。