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}
SegmentDescriptionExamples
rosfitFixed namespace prefix for all RosFit traffic
{device_id}The unique identifier of the devicebot-01, dev_abc123
{category}Logical grouping of the message typetelemetry, cmd, shadow, ota, ros, blob
{action}Specific operation within the categorystatus, 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.

TopicQoSDescription
rosfit/{device_id}/telemetry/status1Periodic device status (CPU, memory, battery, position)
rosfit/{device_id}/telemetry/diagnostics1ROS 2 diagnostic messages and error reports
rosfit/{device_id}/telemetry/custom/{name}0User-defined telemetry streams (e.g. battery, temperature)
rosfit/{device_id}/ros/{topic_name}0Raw ROS 2 topic data bridged to MQTT
rosfit/{device_id}/blob/image1Compressed camera frames (JPEG/PNG, base64 or binary)
rosfit/{device_id}/blob/pointcloud1Point cloud snapshots (compressed PCD)
rosfit/{device_id}/cmd/response1Command acknowledgement with result and correlation_id
rosfit/{device_id}/shadow/reported1Device-reported shadow state
rosfit/{device_id}/ota/progress1OTA update download/install progress
rosfit/{device_id}/ota/result1Final OTA update success or failure

Cloud to robot topics

These topics are published by cloud services and consumed by the device (bridge).

TopicQoSDescription
rosfit/{device_id}/cmd/request1Command sent to the device (navigation goal, velocity, parameter)
rosfit/{device_id}/cmd/cancel1Cancel a previously issued command by correlation_id
rosfit/{device_id}/shadow/desired1Full desired shadow state from the cloud
rosfit/{device_id}/shadow/delta1Diff between desired and reported state
rosfit/{device_id}/ota/trigger1Instruct the device to download and apply a firmware update
rosfit/{device_id}/ota/rollback1Instruct the device to roll back to the previous firmware
rosfit/{device_id}/ros/inject/{topic_name}0Inject 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.

TopicScopeDescription
rosfit/$broadcast/cmd/requestAll devicesSend a command to every connected device
rosfit/$group/{group_name}/cmd/requestGroupSend a command to all devices in a group
rosfit/$broadcast/shadow/desiredAll devicesPush a desired shadow state to all devices
rosfit/$group/{group_name}/shadow/desiredGroupPush a desired shadow to a specific group
rosfit/$broadcast/ota/triggerAll devicesTrigger OTA for the entire fleet
rosfit/$group/{group_name}/ota/triggerGroupTrigger 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": {
    ...
  }
}
FieldTypeDescription
msg_idstring (UUID v4)Unique identifier for the message. Used for deduplication and tracing.
device_idstringThe device that originated (or is targeted by) this message.
timestampstring (ISO 8601)When the message was created, in UTC.
versionstringEnvelope schema version. Currently "1.0".
typestringDot-delimited message type matching the topic category and action.
payloadobjectThe 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.