Skip to content

MQTT Access

MQTT Access turns an existing device into a real device that a Device Agent can control and query. The device does not need to use the Device Agent SDK or rewrite existing drivers. Add an MQTT adapter that subscribes to commands, calls the existing device capability, returns execution results, and reports state and events according to the DeviceSpec.

Get Connection Details

In the Device Agent workspace, click Connect device, then choose Existing device. The console shows the details required for integration:

  • productId: the current Device Agent identifier.
  • namespace: the current runtime namespace. The default is default.
  • deviceId: the unique identifier of this real device under the current Device Agent.
  • MQTT broker URL, username, and password status.
  • Command, response, telemetry, event, and time synchronization topics.
  • Payload examples for commands, responses, online status, state telemetry, and device events.
  • Commands, telemetry, and events from the current DeviceSpec.

If MQTT topic templates have been changed in configuration, use the topics shown in the console.

Existing device MQTT connection details

Choose the Adapter Location

Place the adapter where it can read state and execute actions most reliably:

  • Device firmware: the firmware already supports MQTT, so it subscribes to commands and reports state directly.
  • Edge gateway: the gateway talks to the real device through Modbus, BLE, serial, or a private protocol, then converts it to MQTT.
  • Backend service: an existing cloud or local service can already control the device, so an MQTT adapter process translates commands into existing API calls.

Regardless of where the adapter runs, the Device Agent uses the same MQTT contract.

Adaptation Steps

First align the DeviceSpec with existing device capabilities:

DeviceSpecExisting device mappingMQTT action
CommandsDriver calls, HTTP APIs, serial instructions, or business functionsSubscribe to commands and publish responses
TelemetryCurrent state, sensor readings, operating modePublish online status and state telemetry
EventsAlerts, failures, task completion, button callbacksPublish event messages

The minimal adapter loop is:

text
Startup:
  Connect to MQTT
  Subscribe to the command topic
  Publish online status and the current state snapshot

On command:
  Call the existing device capability with cmd and params
  Publish a command response with the same requestId
  If state changed, publish the latest state snapshot

On device state change:
  Publish state telemetry

On alert, failure, or task completion:
  Publish an event

Device Agent resolves productId and deviceId from the topic path. Keep metadata.productId in reports as well; it helps auto-registration, debugging, and custom topic template setups. If MQTT Client ID must be bound to the device ID, enforce that in broker authentication or ACL rules.

Topics

Default topics are listed below. Copy the topics from the console when integrating.

DirectionPurposeDefault topic
Device subscribesReceive commandsdevice-agent/{productId}/device/{deviceId}/commands
Device publishesReturn command responsesdevice-agent/{productId}/device/{deviceId}/responses
Device publishesReport online status and telemetryv1/{productId}/{deviceId}/telemetry
Device publishesReport device eventsv1/{productId}/{deviceId}/event
Device publishesRequest time synchronizationdevice-agent/{productId}/device/{deviceId}/ntp/request
Device subscribesReceive time synchronization responsesdevice-agent/{productId}/device/{deviceId}/ntp/response

Use QoS 1 and retain: false unless the broker deployment requires otherwise. This avoids replaying stale status or event messages.

Payload Rules

All payloads are UTF-8 JSON objects. Do not use the legacy single-topic envelope, and do not invent custom shadow topics.

FieldDescription
tsOptional Unix timestamp in milliseconds, useful for debugging and ordering.
metadataOptional object. Include at least productId, for example { "productId": "thermostat", "source": "existing-device" }.
dataReported data object. Status and telemetry fields must come from the current DeviceSpec.

The DeviceSpec is the runtime validation source:

  • Command names and parameters must match command definitions.
  • status.data.state and state telemetry must use telemetry fields from the DeviceSpec.
  • Event names and event fields must match event definitions.
  • Unknown fields, invalid types, or unknown event names produce validation errors and are not written into current device state.

Online Status

After the device connects to MQTT, publish online status to the telemetry topic. After the first accepted report, the device appears in the device list.

json
{
  "type": "status",
  "data": {
    "status": "online",
    "state": {
      "current_temperature": 26.5,
      "target_temperature": 24,
      "humidity": 61,
      "mode": "auto"
    }
  },
  "ts": 1710000000000,
  "metadata": {
    "productId": "thermostat",
    "source": "existing-device"
  }
}

Use online, offline, or error for status. Include a full state snapshot when possible. Before shutdown, publish offline; if the device supports MQTT Will Message, use the offline status payload as the will payload.

State Telemetry

Publish state changes to the telemetry topic. The usual type is state. Put only telemetry fields defined in the DeviceSpec into data.

json
{
  "type": "state",
  "data": {
    "current_temperature": 27.1,
    "target_temperature": 24,
    "humidity": 60,
    "mode": "auto"
  },
  "ts": 1710000005000,
  "metadata": {
    "productId": "thermostat",
    "source": "existing-device"
  }
}

Report a full snapshot after startup, after command execution, and after important state changes. If a device reports only partial fields, the console can only update those fields.

Command Responses

When a user controls a device through conversation, the Device Agent publishes a command to the command topic.

json
{
  "cmd": "set_target_temperature",
  "params": {
    "target_temperature": 24
  },
  "requestId": "req-001",
  "ts": 1710000010000
}
FieldTypeRequiredDescription
cmdstringYesCommand name defined in the DeviceSpec.
paramsobjectNoCommand parameters. They must match the command parameter definition. Use {} or omit it when the command has no parameters.
requestIdstringYesRequest ID for this command.
tsnumberNoUnix timestamp in milliseconds.

After execution, publish the result to the response topic. requestId must match the received command.

json
{
  "code": 0,
  "msg": "ok",
  "requestId": "req-001",
  "data": {
    "target_temperature": 24,
    "mode": "auto"
  },
  "ts": 1710000011000,
  "metadata": {
    "productId": "thermostat",
    "source": "existing-device"
  }
}
FieldTypeRequiredDescription
codenumberYes0 means success. Non-zero values mean failure.
msgstringYesExecution result message.
requestIdstringYesMust equal the command requestId.
dataanyNoExecution result returned to the Device Agent.
tsnumberNoUnix timestamp in milliseconds.

If a command changes device state, publish the latest status or state immediately after the response so the status panel reflects the result.

Device Events

Events are one-time device-originated changes, such as alerts, failures, threshold triggers, task completion, or button presses. Publish type: "event" to the event topic.

json
{
  "type": "event",
  "data": {
    "event": "temperature_alert",
    "current_temperature": 38.5,
    "level": "warning"
  },
  "ts": 1710000020000,
  "metadata": {
    "productId": "thermostat",
    "source": "existing-device"
  }
}

data.event must be an event name defined in the DeviceSpec. Other fields must be output fields defined by that event. Events do not automatically update current data, but they appear in recent events. For threshold events, use edge triggering or a cooldown to avoid duplicate reports.

Test with MQTTX

Before adapting a real device, you can use MQTTX CLI to simulate one device. The examples below assume:

  • MQTT broker: 127.0.0.1:1883
  • productId: thermostat
  • deviceId: thermostat-001

If the MQTT broker does not require username and password, remove -u and -P.

First, open one terminal and subscribe to the command topic. This lets you see commands sent by the Device Agent:

bash
mqttx sub \
  -h 127.0.0.1 \
  -p 1883 \
  -u your-username \
  -P 'your-password' \
  -q 1 \
  -t 'device-agent/thermostat/device/thermostat-001/commands'

Then use another terminal to simulate the device coming online:

bash
mqttx pub \
  -h 127.0.0.1 \
  -p 1883 \
  -u your-username \
  -P 'your-password' \
  -q 1 \
  -t 'v1/thermostat/thermostat-001/telemetry' \
  -m '{"type":"status","data":{"status":"online","state":{"current_temperature":26.5,"target_temperature":24,"humidity":61,"mode":"auto"}},"metadata":{"productId":"thermostat","source":"mqttx"}}'

After thermostat-001 appears in the device list, simulate a state update:

bash
mqttx pub \
  -h 127.0.0.1 \
  -p 1883 \
  -u your-username \
  -P 'your-password' \
  -q 1 \
  -t 'v1/thermostat/thermostat-001/telemetry' \
  -m '{"type":"state","data":{"current_temperature":27.1,"target_temperature":24,"humidity":60,"mode":"auto"},"metadata":{"productId":"thermostat","source":"mqttx"}}'

You can also simulate a device-originated event:

bash
mqttx pub \
  -h 127.0.0.1 \
  -p 1883 \
  -u your-username \
  -P 'your-password' \
  -q 1 \
  -t 'v1/thermostat/thermostat-001/event' \
  -m '{"type":"event","data":{"event":"temperature_alert","current_temperature":38.5,"level":"warning"},"metadata":{"productId":"thermostat","source":"mqttx"}}'

Finally, ask the Device Agent to control this device in the conversation. The subscription terminal receives a command with requestId. Copy that requestId into the response payload:

bash
mqttx pub \
  -h 127.0.0.1 \
  -p 1883 \
  -u your-username \
  -P 'your-password' \
  -q 1 \
  -t 'device-agent/thermostat/device/thermostat-001/responses' \
  -m '{"code":0,"msg":"ok","requestId":"replace-with-received-requestId","data":{"target_temperature":24,"mode":"auto"},"metadata":{"productId":"thermostat","source":"mqttx"}}'

These commands validate the full path: device online status, telemetry reporting, event reporting, command reception, and command response. For a real device, replace the MQTTX commands with MQTT publish and subscribe logic in firmware, a gateway, or a backend service.

Time Synchronization

If the device needs to estimate local clock drift from Agent Gateway, use the time synchronization topics.

Publish this payload to the request topic:

json
{
  "deviceSendTime": 1710000030000
}

Receive this payload from the response topic:

json
{
  "deviceSendTime": 1710000030000,
  "serverRecvTime": 1710000030120,
  "serverSendTime": 1710000030122
}

deviceSendTime is the device's local Unix timestamp in milliseconds when it sends the request. serverRecvTime and serverSendTime are Agent Gateway timestamps for receiving the request and sending the response.

Verify Access

After adapting the device side, check the workspace in this order:

  1. The device is connected to MQTT and has subscribed to the command topic.
  2. After the telemetry topic receives the first status or state report, the device appears in the device list.
  3. Current state shows telemetry fields defined in the DeviceSpec.
  4. A conversation control request reaches the device, and the device publishes a response with the same requestId.
  5. After a command changes state, the device publishes the latest status or telemetry.
  6. Device-originated events appear in recent events.

If the device does not appear, check the MQTT broker and credentials first, then verify productId, deviceId, topic paths, and metadata.productId. If the device appears but current state does not update, check whether telemetry field names and types match the DeviceSpec. See Configuration for runtime settings.

Next Steps

  • Read SDK Access to connect real hardware with a generated device-side project.
  • Read Device Simulator to validate the DeviceSpec without real hardware.
  • Read Use a Device Agent to select devices and control them through conversation.