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.

TypeDescriptionTypical hardware
ros2_robotA robot running a full ROS 2 stack with the RosFit BridgeTurtleBot, custom AMR, robotic arm
micro_ros_mcuA microcontroller running micro-ROS over XRCE-DDSESP32, STM32, Arduino Portenta
mqtt_deviceA generic MQTT device not running ROS 2Environmental sensor, smart relay, PLC
gatewayAn aggregation point that proxies multiple sub-devicesRaspberry Pi hub, edge server
simulatorA simulated device for development and CI testingGazebo, 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.

StateDescriptionTransitions to
provisioningDevice has been registered but has not connected yetonline, decommissioned
onlineDevice is connected to the MQTT broker and sending heartbeatsoffline, error, maintenance
offlineDevice has not sent a heartbeat within the configured timeout (default 60 s)online, maintenance, decommissioned
errorDevice reported a critical fault via telemetry/diagnosticsonline, maintenance, decommissioned
maintenanceDevice has been manually placed in maintenance mode (commands are paused)online, decommissioned
decommissionedDevice 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 a dev_ 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" }'