MQTT topics & ACL
Console ACLs use a flat topic prefix. The SDK builds topics to match.
Prefix
{workspace_slug}/{device_key}/…
| Segment | Source |
|---|---|
workspace_slug | Provision JSON → NVS. Kconfig override optional. |
device_key | Provision JSON → NVS. Usually equals mqtt_username. |
Publish (device → cloud)
| Topic | QoS | Retain | Purpose |
|---|---|---|---|
…/telemetry | 0 | No | Sensor readings |
…/state | 1 | Yes | Actuator state |
…/event | 1 | No | Live alarms / discrete events (not history; see Event logging) |
…/presence | 1 | Yes | Online/offline JSON |
…/config/get | 1 | No | Config pull request |
…/config/status | 1 | No | Config apply ack |
…/cmd/ack/{ch} | 1 | No | Command ack (e.g. OTA queued / starting) |
Subscribe (cloud → device)
| Topic | QoS | Purpose |
|---|---|---|
…/cmd | 1 | Commands (iotmer_subscribe_commands) |
…/cmd/# | 1 | Optional: cmd/device and nested command topics |
…/config/# | 1 | Config protocol |
OTA command ("cmd":"ota") and history ("cmd":"event.get") are application handlers on cmd / cmd/device. See OTA and Event logging.
Device → cloud command acks (products that implement them): {prefix}/cmd/ack/{ch} (e.g. cmd/ack/device), QoS 1, retain 0.
Payload routing
Route by JSON fields type and ch, not by topic depth:
{"type":"cmd","ch":"relay_1","cmd":"set","state":true}
{"type":"telemetry","ch":"ch_1","voltage":22050,"ts":1748000000}
Same schema over MQTT and BLE. See operational protocol.
Presence (LWT)
Topic: {workspace_slug}/{device_key}/presence
On connect (retained):
{"status":"online","ts":1748000000}
On unexpected disconnect (broker LWT, retained):
{"status":"offline","ts":0}
Enable with presence_lwt_enable in iotmer_config_t.
Config protocol
Subscription …/config/# covers:
| Topic | Direction |
|---|---|
…/config/meta | Cloud → device (retained) |
…/config/get | Device → cloud |
…/config/resp | Cloud → device (chunked) |
…/config/status | Device → cloud |
Details: MQTT Config Protocol.
Platform MQTT rules: docs.iotmer.com