MQTT
MQTT is the most common transport between the shop floor and the corporate world: a broker in the middle, publishers on one side, subscribers on the other. The CMS speaks both roles, and over the same connection it also speaks Sparkplug B — the specification that standardises what MQTT leaves open.
| Collection | Delivery | |
|---|---|---|
| Plain MQTT | MQTT_TOPIC_SUBSCRIBER — subscribes to a topic | MQTT_PUBLISH — publishes to a topic |
| Sparkplug B | SPARKPLUG_SUBSCRIBER — subscribes to a slice of the namespace | SPARKPLUG_CMD — sends NCMD / DCMD |
Connection
Register an MQTT Broker in External Connections:
| Field | Note |
|---|---|
| Protocol | mqtt, mqtts, ws or wss — WebSocket solves a broker behind a corporate proxy |
| Host and port | 1883 by default (or 8883 with TLS) |
| User and password | Optional, as the broker requires |
| TLS | Turns on the encrypted connection |
| Client ID prefix | Goes at the start of each connection’s identifier |
| Sparkplug B | Marks this broker as carrying an spBv1.0 namespace |
Use Test connection before creating the Collection: a broker that refuses the credential fails here, with the broker’s own message, instead of failing silently later.
The Client ID prefix exists for a practical reason: brokers disconnect clients with identical
IDs. The CMS builds the Client ID as {prefix}-{collection id}-{timestamp}, which guarantees
uniqueness even with several Collections on the same broker and repeated reconnections.
Ticking Sparkplug B on the connection is a property of the broker, not of each Collection: once on, the Collection and Delivery screens start offering the Sparkplug types.
Collection — MQTT_TOPIC_SUBSCRIBER
The CMS subscribes to a topic and reacts to every publication. There is no schedule: it is event-driven, like SAP IDoc and the OPC UA trigger.
| Field | Role |
|---|---|
| Topic | The subscription filter. Accepts MQTT wildcards: + (one level) and # (the rest) |
| QoS | 0, 1 or 2, according to the guarantee the broker offers |
Each published message becomes one message in the CMS, with the raw payload, forwarded to the configured target interfaces.
Details that avoid surprises
- The connection is per Collection. Two Collections on the same broker open two connections, with distinct Client IDs. That keeps one independent of the other: reconfiguring one does not drop the other.
- Automatic reconnection every 5 seconds, with a 15-second keepalive. The state (connected / reconnecting / disconnected) shows on the Collection screen.
- Null bytes are stripped from the payload before storing. An MQTT payload is binary, and a
NULbyte in the middle would make the database reject the whole record. - Business Errors are evaluated on receipt, over the clear text, before any payload encryption. An output rule matching here marks the message as a Business Error on arrival.
Configure the Connection Lost alert (CONEXAO_MQTT_PERDIDA) for every MQTT Collection. A dead
subscription is silent: it raises no error, messages simply stop arriving — the hardest failure mode
to notice. See Alerts.
Choosing the topic
Wildcards are tempting and they have a cost. factory/# brings everything, including what you do not
want, and every publication becomes a stored message. Prefer the narrowest slice that solves the case,
and use the Transformer to discard what does not matter only when the topic filter cannot.
When the source publishes several quantities on sibling topics (.../temp, .../pressure), + at
the right level is usually better than #: the source topic reaches the Transformer in
contexto.topico, and that is how the script knows which quantity it is handling.
Delivery — MQTT_PUBLISH
Publishes the payload to a broker topic. Useful to return a result to the shop floor, feed a SCADA system or another consumer in the plant.
| Field | Role |
|---|---|
| Topic | Accepts {{alias}} resolved against the payload — nested paths included ({{equipment.id}}) |
| QoS | 0 (at most once) or 1 (at least once) |
The dynamic topic is what lets a single Delivery publish to sensors/{{sensorId}}/command, with the
destination coming from the message content itself.
Declare the aliases used in the topic as the Delivery’s Input Payload. Marked as required, a
message without the field is refused with a clear message — instead of publishing to a topic with
undefined in the middle.
Testing without a production broker
The repository ships a Mosquitto broker in docker-compose.test.yml, the test environment:
docker compose -f docker-compose.test.yml up -d mosquittoIt serves both plain MQTT and Sparkplug B — which also comes with an edge node simulator.
Sparkplug B
If the other side speaks Sparkplug (Ignition, HiveMQ Edge, Kepware, Cirrus Link, Opto 22), the next page covers the namespace, the BIRTH/DEATH lifecycle, metric discovery and commands.