FarmBot Genesis v1.8をAIから扱うとき、最初に分けるべきなのは「Webアプリに保存された情報」と「実機へ届くリアルタイム通信」である。本稿はFarmBot公式のv15資料を2026年9月15日に読み直して整理した。機械構成に関する記述(XYZガントリー、散水・工具・撮影、付属部品)は、FarmBot公式のGenesis v1.8商品ページを参照している。実機・給水系・モーターには接続していない。ここで確認する到達点は、認証を保護したまま状態を読める構成を作ることだ。
0. 先に安全境界を固定する
FarmBotは屋外でXYZガントリーを動かし、散水や工具を扱う機械である。初回は実機を動かさず、公式資料の範囲とアカウント情報の扱いを確認する。実機を使う段階でも、人や動物が運転域へ入らない区画、物理的な電源・給水遮断、手元の緊急停止手段をソフトウェアより先に用意する。APIトークンを記事、シェル履歴、ログ、LLMへの無加工の入力へ置かない。
1. RESTとMessage Brokerの役割
FarmBot Web AppのREST APIは、HTTPのリクエストとレスポンスでJSONリソースを読む・書く入口である。栽培レイアウト、植物、シーケンス、Farm Event、写真、ログ、設定など、アカウント側のデータを扱う。公式資料は、リソースごとにURLがあり、HTTP verbでサーバーの処理が決まると説明している。
一方、Message Brokerはリアルタイム同期とRPCのための通信路だ。公式資料はMQTT、WebSockets、AMQPを挙げ、ブラウザならWebSockets、ブラウザ外のアプリならMQTTを推奨している。実機への即時命令や状態変化の購読はこの経路に属する。AMQPはFarmBot OSを直接変更する場合以外は推奨されていない。
したがって「REST APIがある」ことだけから「HTTP POSTでモーターが動く」と読まない。RESTはアカウントのリソース操作、Message Brokerは認証済みクライアントと実機・サーバー間の同期およびRPC、という別の口で設計する。
2. トークンを発行し、保存場所を分ける
FarmBot公式REST資料のトークン例は、Web Appの/api/tokensへ認証情報を送ってトークンを得る流れを示している。レスポンスには人が読むunencoded情報と、Authorizationヘッダーで使うencoded情報が含まれる。既存トークンを使う場合も、必要なプロセスだけが読めるファイルや秘密ストアへ保存し、ソースコードへ埋め込まない。
RESTの最小読取例は次の形になる。FARMBOT_TOKENはシェルへ直接書かず、秘密ストアからそのプロセスへ渡す。レスポンスが返ることと、実機が動いたことは別の判定である。
curl --fail --silent --show-error \
-H "Authorization: Bearer ${FARMBOT_TOKEN}" \
-H "Content-Type: application/json" \
"https://my.farm.bot/api/webcam_feeds"
3. RESTは読み取りから始める
まずGETだけで、アカウントに保存されたリソースを読めるか確認する。公式資料の例にはwebcam_feedsがあり、ページング可能なリソースでは?page=3&per=10のように分割する。AIへ渡す前に、HTTP status、レスポンスのJSON、取得時刻を一緒に記録する。空配列を「機器が停止した」と解釈せず、認証先、対象アカウント、リソース名、権限を切り分ける。
公式farmbot-pyのWeb App API例は、トークンをFarmbotへ設定し、api_get("webcam_feeds")を呼ぶ形である。状態取得用の小さな読み取り関数へ閉じるなら、最初は次のように対象を限定する。
import json
from farmbot import Farmbot
with open("farmbot_authorization_token.json", encoding="utf-8") as file:
token = json.load(file)
fb = Farmbot()
fb.set_token(token)
webcam_feeds = fb.api_get("webcam_feeds")
print(webcam_feeds)
このコードは公式のAPI呼び出し形を示すための最小例で、手元のアカウントや実機への接続結果を保証するものではない。farmbot-pyの設定にはtimeoutやcacheの項目もあるため、実装時は既定値を鵜呑みにせず、通信断をエラーとして扱える設定にする。
4. MQTTで状態変化を受け取る
RESTを一定間隔で叩き続けると、通信断と「状態に変化がない」を区別しにくい。公式Python資料には、listen_for_status_changes()でstatusチャンネルを購読し、一定時間または指定件数で止める例がある。位置だけを見る場合も、最初の状態との差分か、location_data.positionのように対象パスを明示する。
from farmbot import Farmbot
# TOKENは秘密ストアから読み込む。ここへ実値を置かない。
fb = Farmbot()
fb.set_token(TOKEN)
# 5秒間、または最初のstatus変化まで観測する
fb.listen_for_status_changes(duration=5)
# 必要な場合だけ、10回の変化から位置の差分を読む
fb.listen_for_status_changes(
stop_count=10,
diff_only=False,
path="location_data.position",
)
公式資料では、出力は機器のstate treeであり、同じ状態木はFarmBotJSにも現れると説明されている。durationやstop_countは観測の境界を作るだけで、接続が生きている証明ではない。受信時刻と接続状態を保存し、何も届かないときは「静止」ではなく「未観測」と扱う。
FarmBotJSでは、公式例のとおりAPI tokenをFarmbotへ渡してconnect()し、online、offline、statusなどのイベントを購読できる。statusはリモート機器の状態変化、offlineは接続断の信号で、公式資料は自動再接続も説明している。なお、FarmBotはNode.js環境を自社の本番環境ではテストしていないと明記しているため、サーバーで使う場合はNodeで動くことを実機・対象版ごとに別途検証する。
import { Farmbot } from "farmbot";
const bot = new Farmbot({ token: process.env.FARMBOT_TOKEN });
bot.on("online", () => console.log("connected"));
bot.on("offline", () => console.log("disconnected"));
bot.on("status", (state) => console.log("state changed", state));
bot.connect();
ここでもconnect()成功は接続確立のイベントであり、移動・散水・工具操作を許可する判定ではない。状態を読み、期限、位置、緊急停止、運転域の安全条件を固定ルールで検査してから、別の狭い制御関数へ進める。
5. RESTの設定変更とRPCを同じ権限にしない
栽培レイアウトやFarm EventをRESTで登録・更新することと、Message BrokerへRPCを送ることは別の操作である。REST側のPOST/PATCHはWeb Appに保存するデータを変える。Message Broker側のRPCは接続中のクライアント・実機へ命令を届ける。前者の成功レスポンスを後者の実機動作と読み替えない。
AIに渡すツールは、最初はread_webapp_resource()とread_status()のような読み取り専用の面だけにする。RPCを開く場合でも、速度・移動範囲・給水量・実行時間・再接続後の再送条件を固定ルールで制限し、タイムアウトやofflineの後に命令を自動再送しない。緊急停止はAIと同じソフトウェア層に置かず、人が物理的に使える経路を残す。
完了判定
- FarmBot公式REST資料を読み、JWTのAuthorizationとJSONリソースの関係を説明できる
- RESTの読み取りとMessage BrokerのMQTT/WebSocket通信を別の経路として扱える
farmbot-pyのapi_getとlisten_for_status_changes、FarmBotJSのstatus/offlineの役割を区別できる- timeout、接続断、空レスポンスを「実機停止」と断定しない
- 実機操作・散水・モーターRPCを行わず、AIへ渡す権限を読み取りから始められる
FarmBot Genesis v1.8の機械仕様と接続口の全体像はFarmBot Genesis v1.8の標本で確認する。実機未検証のため、標本のverifiedは変更しない。