Device Model
Every robot, microcontroller, gateway, or simulator connected to RosFit is represented as a device. The device model defines the schema, lifecycle, and organizational structure that the rest of the platform builds on.
What is a device
A device is the atomic unit of management in RosFit. It represents a single endpoint that can publish telemetry, receive commands, maintain a shadow state, and accept OTA updates. Each device has a unique device_id, a set of credentials for MQTT access, and a metadata document that describes its capabilities and configuration.
Devices are not limited to physical robots. A device can be:
- A full ROS 2 robot running the RosFit Bridge
- An ESP32 running micro-ROS
- A standalone MQTT sensor or actuator
- A gateway aggregating multiple sub-devices
- A simulated robot for testing
Device types
RosFit uses a type enum to classify devices. The type determines default topic mappings, dashboard rendering, and available features.
| Type | Description | Typical hardware |
|---|---|---|
ros2_robot | A robot running a full ROS 2 stack with the RosFit Bridge | TurtleBot, custom AMR, robotic arm |
micro_ros_mcu | A microcontroller running micro-ROS over XRCE-DDS | ESP32, STM32, Arduino Portenta |
mqtt_device | A generic MQTT device not running ROS 2 | Environmental sensor, smart relay, PLC |
gateway | An aggregation point that proxies multiple sub-devices | Raspberry Pi hub, edge server |
simulator | A simulated device for development and CI testing | Gazebo, Isaac Sim, custom sim |
You set the type during registration and it cannot be changed afterwards. If a device's role changes, decommission it and register a new one.
Device states
A device transitions through a set of well-defined states throughout its lifecycle.
| State | Description | Transitions to |
|---|---|---|
provisioning | Device has been registered but has not connected yet | online, decommissioned |
online | Device is connected to the MQTT broker and sending heartbeats | offline, error, maintenance |
offline | Device has not sent a heartbeat within the configured timeout (default 60 s) | online, maintenance, decommissioned |
error | Device reported a critical fault via telemetry/diagnostics | online, maintenance, decommissioned |
maintenance | Device has been manually placed in maintenance mode (commands are paused) | online, decommissioned |
decommissioned | Device has been permanently retired. Credentials are revoked. | — (terminal) |
State transitions happen automatically (heartbeat timeout, diagnostic errors) or manually through the API (PATCH /api/v1/devices/{device_id}).
Device metadata schema
When you register a device, you send a JSON payload describing it. Below is the full schema accepted by the registration endpoint.
{
"device_id": "bot-01",
"name": "Warehouse AMR #1",
"type": "ros2_robot",
"group": "warehouse-east",
"tags": ["amr", "navigation", "floor-2"],
"metadata": {
"ros_distro": "humble",
"firmware_version": "1.4.0",
"hardware": {
"model": "custom-amr-v2",
"serial_number": "SN-2026-00412",
"cpu": "Jetson Orin Nano",
"sensors": ["lidar", "imu", "camera_rgb", "encoder"]
},
"network": {
"mac_address": "AA:BB:CC:DD:EE:01",
"ip_address": "10.0.1.42"
},
"location": {
"site": "warehouse-east",
"building": "B",
"floor": 2
}
}
}
device_id— A globally unique identifier. If omitted, the server generates one with adev_prefix.name— A human-readable display name.type— One of the device type enums listed above.group— Optional group for fleet organization.tags— Arbitrary string tags for filtering and search.metadata— A free-form JSON object for hardware details, firmware info, or any custom fields your team needs.
Registering a device
Send a POST request to the devices endpoint with the JSON body described above.
curl -X POST http://localhost:8000/api/v1/devices \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-api-token>" \
-d '{
"device_id": "bot-01",
"name": "Warehouse AMR #1",
"type": "ros2_robot",
"group": "warehouse-east",
"tags": ["amr", "navigation", "floor-2"],
"metadata": {
"ros_distro": "humble",
"firmware_version": "1.4.0",
"hardware": {
"model": "custom-amr-v2",
"serial_number": "SN-2026-00412"
}
}
}'
The API responds with the created device, MQTT credentials, and topic namespace:
{
"device_id": "bot-01",
"name": "Warehouse AMR #1",
"type": "ros2_robot",
"status": "provisioning",
"access_token": "mqtt_tok_a1b2c3d4e5f6",
"mqtt_endpoint": "mqtt://emqx.rosfit.local:8883",
"mqtt_topics": {
"publish": "rosfit/bot-01/#",
"subscribe": "rosfit/bot-01/#"
},
"created_at": "2026-03-30T10:00:00Z"
}
Pass the access_token to the RosFit Bridge configuration on the robot. The bridge uses it to authenticate with the EMQX broker and begin publishing telemetry.
Groups and fleet hierarchies
Devices can be organized into groups for bulk operations and logical segmentation. Groups are flat strings by default, but you can model a hierarchy using slash-delimited names.
warehouse-east
warehouse-east/floor-1
warehouse-east/floor-2
warehouse-west
lab/simulation
Groups enable:
- Broadcast commands — Send a single command to every device in a group via the topic
rosfit/$group/{group_name}/cmd/request. - Filtered dashboards — The dashboard's fleet view can filter by group to show only relevant devices.
- Bulk OTA — Target an entire group for a firmware rollout.
- Access control — Operators can be scoped to specific groups via RBAC policies.
You assign a group during registration or update it later with PATCH /api/v1/devices/{device_id}. A device belongs to exactly one group at a time.
curl -X PATCH http://localhost:8000/api/v1/devices/bot-01 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-api-token>" \
-d '{ "group": "warehouse-east/floor-2" }'