ロボ図鑑

FarmBotの状態取得を始める — REST APIとMQTTを分ける

公開: 2026-09-15

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にも現れると説明されている。durationstop_countは観測の境界を作るだけで、接続が生きている証明ではない。受信時刻と接続状態を保存し、何も届かないときは「静止」ではなく「未観測」と扱う。

FarmBotJSでは、公式例のとおりAPI tokenをFarmbotへ渡してconnect()し、onlineofflinestatusなどのイベントを購読できる。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 Genesis v1.8の機械仕様と接続口の全体像はFarmBot Genesis v1.8の標本で確認する。実機未検証のため、標本のverifiedは変更しない。

出典(2026-09-15確認)

他のガイド