MQTT Guide
Subscribe to topics, publish data, and run an embedded broker.
Overview
ControlBird's MQTT integration runs in two modes. In client mode it connects to an external MQTT broker, subscribes to topics, and maps incoming payloads directly into entity fields, it can also publish field values back out to topics. In broker mode it hosts an embedded MQTT broker so devices and other systems can publish and subscribe against ControlBird itself. Both modes are configured entirely through the Device Manager app, no configuration files are required.
The integration supports MQTT 3.1.1 and 5.0, topic wildcards, QoS levels 0/1/2, retained messages, Last Will Testament, TLS, and three payload formats (String, JSON, and Binary). Inbound JSON payloads can be reduced to a single value with a JSONPath expression and coerced to the target field's type.
New to device configuration?
If this is your first integration, start with walkthrough step 7: Connect a Device for a hands-on introduction to controllers and mappers, then return here for MQTT specifics.
Architecture
MQTT follows ControlBird's standard controller/mapper pattern. A controller owns the connection (or the listener, in broker mode) and is configured through an endpoint that holds the connection settings. In client mode you attach mappers to the controller, and each mapper binds one topic to one entity field.
Both modes appear in the Device Manager under the name MQTT, and you choose the Client or Server role when you create the controller. In a multi-node deployment the controllers coordinate so that only one node runs the active connection or broker at a time, which means traffic is never doubled up and failover is automatic.
The broker does not use mappers
In broker mode ControlBird is a pure message broker. Clients connect to it over standard MQTT and publish/subscribe directly, there is no entity bridging on the broker side. Add mappers to a client-mode controller when you want topics mapped to entity fields.
Client mode: connecting to a broker
- Open the Device Manager app in the ControlBird control plane.
- Create a new protocol controller and select MQTT in the Client role.
- Configure the endpoint with the broker
HostandPort(default1883for plain,8883for TLS). - Optionally set
UsernameandPasswordfor authentication. - Set client behavior:
ClientId,CleanSession(defaulttrue), andKeepAliveSeconds(default60). - Add one or more mappers, one per topic pattern.
Client endpoint fields
| Field | Description | Default |
|---|---|---|
Host | Broker hostname or IP address. | none |
Port | Broker TCP port. | 1883 / 8883 (TLS) |
ClientId | MQTT client identifier (a per-controller/node suffix is appended automatically). | auto |
Username / Password | Optional credentials. | none |
CleanSession | Start a fresh session on each connect. | true |
KeepAliveSeconds | Heartbeat interval. | 60 |
TlsEnabled | Enable MQTTS/TLS. | false |
Certificate | Certificate entity supplying CA (and optional client cert/key). | none |
Logging | Enable TX/RX packet logging. | off |
MaxLogFiles / MaxLogSizeMb | Log rotation limits. | n/a |
MinRetryBackoffMs / MaxRetryBackoffMs | Reconnect backoff bounds. | 1000 / 60000 |
ClientId is unique per node
ControlBird derives a distinct effective client identifier for each node, so leaving ClientId empty (or setting one) still produces a unique value per node. This prevents the broker from evicting and re-admitting connections in a reconnection storm when multiple ControlBird nodes share a configuration.
Mappers: binding topics to fields
Each mapper connects a single MQTT topic to one entity field. The SourcePath is the topic pattern, TargetEntity and TargetField identify where values are read or written, and the remaining fields control direction, payload handling, and MQTT publish options.
| Field | Values | Purpose |
|---|---|---|
SourcePath | topic string | MQTT topic pattern (supports + and # wildcards). |
TargetEntity / TargetField | entity / field | The Store field that receives values (inbound) or supplies them (outbound). |
Direction | Read, Write, ReadWrite | Inbound only, outbound only, or bidirectional. |
ReadMode | Subscribe, Poll | Subscribe (event-driven, default) or Poll on an interval. |
QoS | AtMostOnce, AtLeastOnce, ExactlyOnce | Quality of service (default AtLeastOnce). |
Retain | bool | Publish as a retained message (default false). |
PayloadFormat | String, Json, Binary | How payload bytes are interpreted. |
JsonPath | JSONPath string | Extract a single value from a JSON payload (e.g. $.brightness). |
ByteOrder | BigEndian, LittleEndian | Byte order for Binary payloads. |
PollIntervalMs | milliseconds | Interval used when ReadMode=Poll. |
Disabled | bool | Disable the mapper without deleting it. |
Topic wildcards
MQTT topics are hierarchical, separated by /. Two wildcards are supported in subscription patterns:
+matches exactly one topic level, e.g.sensors/+/value.#matches the remaining levels and must be the last character, e.g.house/#.
Payload formats
| Format | Behavior |
|---|---|
String | Raw text. The payload is stored as-is. |
Json | Parsed as a JSON object. An optional JsonPath extracts one value; without it the whole object is used. |
Binary | Raw bytes parsed using the selected ByteOrder (BigEndian or LittleEndian). |
Type coercion
Extracted JSON values are automatically converted to the target field's type, Bool, Int, Float, String, or Choice. A JSON boolean mapped onto a Choice field becomes 0/1, and a JSON string mapped onto a Choice field is treated as a numeric index when it parses as a number, otherwise it is preserved as a String so the choice label can be resolved (for example "ON" / "OFF").
Examples
Subscribe to a plain-text temperature topic:
SourcePath: sensors/temperature
PayloadFormat: String
Direction: ReadExtract a single value from a JSON payload via JSONPath:
SourcePath: zigbee/light/brightness
PayloadFormat: Json
JsonPath: $.brightness
Direction: ReadPublish a setpoint as a retained message at QoS 1:
SourcePath: control/setpoint
Direction: Write
QoS: AtLeastOnce
Retain: trueSubscribe with wildcards across many sensors or an entire subtree:
SourcePath: sensors/+/value PayloadFormat: String Direction: Read
SourcePath: house/# PayloadFormat: Json Direction: ReadBidirectional state mirroring (subscribe and publish on one topic):
SourcePath: devices/light/state
Direction: ReadWrite
PayloadFormat: StringParse a binary payload with an explicit byte order:
SourcePath: modbus/holding/registers
PayloadFormat: Binary
ByteOrder: BigEndian
Direction: ReadResolve a Choice field from a JSON string (e.g. "ON" / "OFF"):
SourcePath: switch/status
PayloadFormat: Json
JsonPath: $.state
Direction: ReadSecurity and reliability
TLS / MQTTS
Set TlsEnabled on the endpoint and attach a Certificate entity. The CA certificate is required to validate the broker; a client certificate and key are optional and enable mutual TLS. TLS connections typically use port 8883. See the certificates guide for managing certificate material.
Quality of service
| QoS | Name | Guarantee |
|---|---|---|
| 0 | AtMostOnce | Fire and forget, no delivery guarantee. |
| 1 | AtLeastOnce | Delivered at least once (default), duplicates possible. |
| 2 | ExactlyOnce | Delivered exactly once via a four-way handshake. |
Retained messages and Last Will
Publishing with Retain=true stores the last message on the broker so new subscribers receive it immediately on subscription. Per the MQTT 3.1.1 specification, retained messages are still delivered on reconnect even when CleanSession=true. The client also supports a Last Will Testament: a will message the broker publishes automatically if the client disconnects ungracefully.
Reconnect behavior
On connection failure the client retries with exponential backoff bounded by MinRetryBackoffMs (default 1000) and MaxRetryBackoffMs (default 60000). The keep-alive heartbeat (default 60 seconds) lets the broker detect a dead client.
Broker mode: hosting an embedded broker
Create a controller in the Server role and configure its endpoint. Bind to 0.0.0.0 to accept connections on all interfaces, choose a listen Port (default 1883), and set resource limits. Enable TLS by setting TlsEnabled and attaching a Certificate.
| Field | Description | Default |
|---|---|---|
Host | Bind address (e.g. 0.0.0.0). | none |
Port | Listen port. | 1883 |
MaxConnections | Maximum concurrent client connections. | 100 |
MaxQueuedMessages | Maximum queued messages per client. | 256 |
KeepAliveSeconds | Keep-alive interval for connected clients. | 60 |
TlsEnabled / Certificate | Enable TLS and supply certificate material. | false |
Logging / MaxLogFiles / MaxLogSizeMb | Packet logging and rotation. | None |
MinRetryBackoffMs / MaxRetryBackoffMs | Backoff bounds. | 1000 / 60000 |
Host: 0.0.0.0
Port: 1883
MaxConnections: 1000
MaxQueuedMessages: 512Limitations
- The embedded broker does not bridge entities, it is a pure pub/sub broker with no mappers.
- Publishing to topics beginning with
$(reserved system topics) is not allowed; system topics can still be subscribed to and read. - Topic length is capped at 65535 bytes (the MQTT specification limit).
- Wildcard subscriptions apply to client read operations; the broker does not subscribe to external clients on your behalf.
- JSONPath extraction returns only the first match.
- Binary payloads require
PayloadFormat=Binaryexplicitly, format is never auto-detected because binary and text are ambiguous.
Observability
Set Logging=Enabled on either endpoint to record all MQTT TX/RX packets, with rotation governed by MaxLogFiles and MaxLogSizeMb. In a multi-node deployment, only one node holds the active connection or broker at a time, and the role moves automatically if that node becomes unavailable. For broader device setup, return to step 7: Connect a Device.