Topics & Messages
All communication between devices and the cloud passes through MQTT topics with a consistent naming convention and a standard message envelope. Understanding the topic hierarchy and message format is essential for building integrations, debugging, and extending the platform.
Topic structure
Every MQTT topic in RosFit follows a four-segment pattern:
rosfit/{device_id}/{category}/{action}
| Segment | Description | Examples |
|---|---|---|
rosfit | Fixed namespace prefix for all RosFit traffic | — |
{device_id} | The unique identifier of the device | bot-01, dev_abc123 |
{category} | Logical grouping of the message type | telemetry, cmd, shadow, ota, ros, blob |
{action} | Specific operation within the category | status, request, reported, trigger |
Some topics extend beyond four segments when additional specificity is needed (e.g. rosfit/bot-01/telemetry/custom/battery or rosfit/bot-01/ros/inject/cmd_vel).
Robot to cloud topics
These topics are published by the device (bridge) and consumed by cloud services.
| Topic | QoS | Description |
|---|---|---|
rosfit/{device_id}/telemetry/status | 1 | Periodic device status (CPU, memory, battery, position) |
rosfit/{device_id}/telemetry/diagnostics | 1 | ROS 2 diagnostic messages and error reports |
rosfit/{device_id}/telemetry/custom/{name} | 0 | User-defined telemetry streams (e.g. battery, temperature) |
rosfit/{device_id}/ros/{topic_name} | 0 | Raw ROS 2 topic data bridged to MQTT |
rosfit/{device_id}/blob/image | 1 | Compressed camera frames (JPEG/PNG, base64 or binary) |
rosfit/{device_id}/blob/pointcloud | 1 | Point cloud snapshots (compressed PCD) |
rosfit/{device_id}/cmd/response | 1 | Command acknowledgement with result and correlation_id |
rosfit/{device_id}/shadow/reported | 1 | Device-reported shadow state |
rosfit/{device_id}/ota/progress | 1 | OTA update download/install progress |
rosfit/{device_id}/ota/result | 1 | Final OTA update success or failure |
Cloud to robot topics
These topics are published by cloud services and consumed by the device (bridge).
| Topic | QoS | Description |
|---|---|---|
rosfit/{device_id}/cmd/request | 1 | Command sent to the device (navigation goal, velocity, parameter) |
rosfit/{device_id}/cmd/cancel | 1 | Cancel a previously issued command by correlation_id |
rosfit/{device_id}/shadow/desired | 1 | Full desired shadow state from the cloud |
rosfit/{device_id}/shadow/delta | 1 | Diff between desired and reported state |
rosfit/{device_id}/ota/trigger | 1 | Instruct the device to download and apply a firmware update |
rosfit/{device_id}/ota/rollback | 1 | Instruct the device to roll back to the previous firmware |
rosfit/{device_id}/ros/inject/{topic_name} | 0 | Inject a message directly into the ROS 2 graph |
Broadcast and group topics
RosFit supports sending a single message to multiple devices using broadcast and group topics.
| Topic | Scope | Description |
|---|---|---|
rosfit/$broadcast/cmd/request | All devices | Send a command to every connected device |
rosfit/$group/{group_name}/cmd/request | Group | Send a command to all devices in a group |
rosfit/$broadcast/shadow/desired | All devices | Push a desired shadow state to all devices |
rosfit/$group/{group_name}/shadow/desired | Group | Push a desired shadow to a specific group |
rosfit/$broadcast/ota/trigger | All devices | Trigger OTA for the entire fleet |
rosfit/$group/{group_name}/ota/trigger | Group | Trigger OTA for a device group |
The EMQX broker expands broadcast and group topics to the individual device topics using shared subscriptions and topic rewrite rules.
Message envelope
Every message published through RosFit — regardless of direction — is wrapped in a standard JSON envelope.
{
"msg_id": "550e8400-e29b-41d4-a716-446655440000",
"device_id": "bot-01",
"timestamp": "2026-03-30T14:23:01.042Z",
"version": "1.0",
"type": "telemetry.status",
"payload": {
...
}
}
| Field | Type | Description |
|---|---|---|
msg_id | string (UUID v4) | Unique identifier for the message. Used for deduplication and tracing. |
device_id | string | The device that originated (or is targeted by) this message. |
timestamp | string (ISO 8601) | When the message was created, in UTC. |
version | string | Envelope schema version. Currently "1.0". |
type | string | Dot-delimited message type matching the topic category and action. |
payload | object | The actual message data. Schema depends on type. |
Example payloads
Telemetry status
Published by the bridge every 5 seconds (configurable) on rosfit/{device_id}/telemetry/status.
{
"msg_id": "a1b2c3d4-0001-4000-8000-000000000001",
"device_id": "bot-01",
"timestamp": "2026-03-30T14:23:01.042Z",
"version": "1.0",
"type": "telemetry.status",
"payload": {
"state": "online",
"uptime_seconds": 84320,
"cpu_percent": 42.5,
"memory_percent": 68.1,
"battery": {
"voltage": 24.1,
"percentage": 73,
"charging": false
},
"position": {
"x": 12.4,
"y": -3.7,
"z": 0.0,
"heading": 1.57
},
"ros_nodes_active": 14
}
}
Command request
Published by the cloud on rosfit/{device_id}/cmd/request.
{
"msg_id": "b2c3d4e5-0002-4000-8000-000000000002",
"device_id": "bot-01",
"timestamp": "2026-03-30T14:25:00.000Z",
"version": "1.0",
"type": "cmd.request",
"payload": {
"correlation_id": "cmd-7890",
"command": "navigate_to",
"data": {
"x": 5.0,
"y": 10.0,
"theta": 0.0
},
"timeout_seconds": 120
}
}
Command response
Published by the device on rosfit/{device_id}/cmd/response.
{
"msg_id": "c3d4e5f6-0003-4000-8000-000000000003",
"device_id": "bot-01",
"timestamp": "2026-03-30T14:25:02.100Z",
"version": "1.0",
"type": "cmd.response",
"payload": {
"correlation_id": "cmd-7890",
"status": "accepted",
"message": "Navigation goal accepted, executing."
}
}
Shadow desired / reported
The cloud publishes a desired state on rosfit/{device_id}/shadow/desired:
{
"msg_id": "d4e5f6a7-0004-4000-8000-000000000004",
"device_id": "bot-01",
"timestamp": "2026-03-30T14:30:00.000Z",
"version": "1.0",
"type": "shadow.desired",
"payload": {
"max_speed": 1.5,
"navigation_mode": "autonomous",
"geofence_enabled": true
}
}
The device confirms by publishing its reported state on rosfit/{device_id}/shadow/reported:
{
"msg_id": "e5f6a7b8-0005-4000-8000-000000000005",
"device_id": "bot-01",
"timestamp": "2026-03-30T14:30:01.200Z",
"version": "1.0",
"type": "shadow.reported",
"payload": {
"max_speed": 1.5,
"navigation_mode": "autonomous",
"geofence_enabled": true,
"firmware_version": "1.4.0"
}
}
If there is a mismatch between desired and reported, the cloud publishes a delta on rosfit/{device_id}/shadow/delta containing only the differing keys.