MQTT#
Talk to the swarm from any language that speaks MQTT - no Python, no SDK. This is the low-magic integration path: subscribe to bot state, publish commands, on standard topics. For Python, the REST API is usually simpler.
How it works#
The MQTT surface is provided by the qrkey bridge, a small process that runs next to the controller and mirrors its state onto an MQTT broker:
dotbot run controller # one terminal - drives the gateway
dotbot run demo qr -w # another terminal - the qrkey MQTT bridge
The bridge connects to a broker (a public HiveMQ instance by default) and:
publishes notifications (state changes, position updates) for consumers to read;
subscribes to command topics, forwarding what it receives to the controller.
So an external consumer subscribes to notifications and publishes commands - it never talks to the controller directly.
Topic vocabulary#
Every topic is rooted at /pydotbot/<secret-topic>, where <secret-topic> is a
base64 string derived from the current PIN code (see Secured brokers).
Topic (under |
Direction |
Purpose |
|---|---|---|
|
you publish |
drive a bot ( |
|
you subscribe |
controller state changes + position updates |
|
request/reply |
one-shot queries (e.g. list of bots, map size) |
Command-topic fields:
<swarm-id>- 4-hex swarm identifier (bots behind one gateway), e.g.0000.<address>- 16-hex DotBot address, e.g.9903ef26257feb31.<app>- application type:0= DotBot,1= SailBot.<cmd>- the command name (last segment).
Get a bot’s address and the swarm id from the controller’s
REST API (GET /controller/dotbots).
Send commands#
Payloads are JSON. Drive a bot forward and turn its LED red:
# move_raw - left_y / right_y drive the wheels, values in [-100, 100]
mosquitto_pub -h <broker> \
-t '/pydotbot/<secret-topic>/command/0000/9903ef26257feb31/0/move_raw' \
-m '{"left_x": 0, "left_y": 80, "right_x": 0, "right_y": 80}'
# rgb_led - 0..255 per channel
mosquitto_pub -h <broker> \
-t '/pydotbot/<secret-topic>/command/0000/9903ef26257feb31/0/rgb_led' \
-m '{"red": 255, "green": 0, "blue": 0}'
Read state#
mosquitto_sub -h <broker> -t '/pydotbot/<secret-topic>/notify' | jq
Notifications carry a cmd field: RELOAD (refetch all bots), UPDATE
(per-bot state delta, incl. LH2 position), PIN_CODE_UPDATE (the secret topic
and key are about to rotate - see below).
Secured brokers#
Topics and payloads are not in the clear. The secret topic and a symmetric
AES-GCM key are both derived from a rotating 8-digit PIN code; the PIN refreshes
periodically (with a grace window), so the topic and key change over time, and
all payloads are encrypted. A consumer therefore needs to derive the topic/key
from the current PIN and decrypt - the bare mosquitto_pub/sub calls above are
the shape of the integration, not a drop-in for a live secured broker.
The PIN and the full key-derivation + encryption scheme are
qrkey’s job. Use it (or a port of its
derivation) rather than reimplementing the crypto. A complete working consumer -
deriving the topic/key, encrypting commands, decrypting notifications, and
rotating on PIN_CODE_UPDATE - ships as the qrkey_demo example
(dotbot run demo qr); read its source as the reference implementation.
For a fully language-neutral bridge that publishes plain dotbot-semantic topics
(pydotbot/<addr>/position, .../cmd/move_raw) with no per-message crypto, see
the Python SDK roadmap - that bridge is planned, not yet shipped.
See also#
REST API - the controller surface the bridge mirrors.
dotbot run-run controllerandrun demo qr.Controller guide - what the controller does.