Sparkplug B (MQTT-based IIoT Standard)
Sparkplug B is an IIoT messaging standard defined by Eclipse Tahu / Cirrus Link. It layers a defined topic structure + Protobuf payload on top of an MQTT broker, allowing equipment from different vendors to read each other's data.
Edge uses this in two directions — the two below are different features, so don't confuse them.
| Direction | What | Where it's documented |
|---|---|---|
| Receive (driver) | Subscribes to Sparkplug topics on a broker, caches metrics, and reads them as tags | Earlier part of this document |
| Export (transmit) | Edge publishes collected values as Sparkplug B | Export below |
Registration form fields
| Field | What to enter | Example |
|---|---|---|
| IP Address | MQTT broker | 192.168.10.50 |
| Port | MQTT broker port | 1883 (plaintext) / 8883 (TLS, planned) |
| Group ID (group-id) | Sparkplug Group — factory/site level | FactoryA, Plant01 |
| Edge Node ID (edge-node-id) | A single node, or + (all nodes) | + (default), edge-01 |
| Keep Alive (keep-alive) | MQTT keep-alive seconds | 60 (default) |
| Connect Timeout (connect-timeout) | MQTT connection timeout, ms | 5000 (default) |
Check which group / edge ID the sending side (Eclipse Tahu / Ignition / Cirrus Link MQTT Engine, etc.) uses to send NBIRTH, and enter the same value. Setting edge-node-id=+ subscribes to all nodes in the group at once.
Tag PLC address notation
The Sparkplug metric identifier uses only the part after the group (group is separated out as a driver option).
| Notation | Meaning |
|---|---|
edge1/Temperature | Node-level metric Temperature of edge node edge1 |
edge1/motor1/RPM | Metric RPM of device motor1 under edge node edge1 |
edge1/dev2/Status | e.g. device status boolean |
On the Sparkplug sending side, metric names and aliases (numeric) are published together during NBIRTH/DBIRTH. Afterward, NDATA/DDATA send only the alias to reduce payload size. Since the PlantPulse driver automatically maintains the alias↔name map, users only ever need to enter the name.
Automatic data type detection
The Sparkplug B Payload specifies a datatype for each metric (Int8/16/32/64, UInt8/16/32/64, Float, Double, Boolean, String, DateTime, Bytes, etc.). The driver converts to the appropriate type based on the wire datatype and caches it as a String, so match the tag's data_type as follows.
| Sparkplug datatype | Recommended data_type |
|---|---|
| Int8 / Int16 / Int32 / UInt8 / UInt16 / UInt32 | Integer |
| Int64 / UInt64 / DateTime | Long |
| Float | Float |
| Double | Double |
| Boolean | Boolean |
| String / Text / UUID | String |
Writing (NCMD / DCMD)
PlantPulse's write automatically branches into NCMD/DCMD.
edge1/SetPoint(segment 2) → NCMD publish (node-level command)edge1/dev1/SetPoint(segment 3+) → DCMD publish (device-level command)
Currently, this phase publishes all command values with String datatype. Since the sending side (Tahu / Ignition) knows the metric's datatype, conversion is usually automatic.
Export — Edge publishing as Sparkplug B
Exports values collected by Edge as standard Sparkplug B (Protobuf). This is the opposite direction of "Receive" described earlier.
The publish target is Edge's own MQTT settings (mqtt.server.host, default 127.0.0.1:1883). This is not a feature that sends to the Platform.
Think of the direction like this — when Edge publishes to the broker on itself, whoever subscribes to that broker (SCADA · MES · upstream IIoT platform) receives it. Values going up to the Platform take a separate path from this.
Topic format
spBv1.0/{groupId}/{type}/{edgeNodeId}[/{deviceId}]
| Position | What goes here |
|---|---|
groupId | sparkplug.group.id — if empty, the site id |
edgeNodeId | sparkplug.edge.node.id — if empty, the edge id |
deviceId | OPC connection id (opc_id) — one connection is one device |
Configuration
| Key | Default | What |
|---|---|---|
sparkplug.enable | true | Turn on publishing |
mqtt.server.host · .port | 127.0.0.1 · 1883 | Target broker for publishing — uses Edge's MQTT settings as-is |
mqtt.server.user · .password | — | Broker credentials |
sparkplug.group.id | Site id | Group in the topic |
sparkplug.edge.node.id | Edge id | Node in the topic |
sparkplug.device.strategy | per-opc | One OPC connection = one device |
sparkplug.qos | 0 | MQTT QoS |
sparkplug.alias.enable | true | Reduce payload with alias |
sparkplug.cmd.enable | false | Receive commands (NCMD/DCMD) |
sparkplug.bdseq.path | /data1/pp-data/sparkplugb/bdseq | File to store bdSeq |
device.strategy is currently just per-opcThe config comment also mentions single, but it is not yet implemented. Currently it only works as per-opc.
The metric name is the tag id
🔴 What goes in the metric name position is the tag_id — not the tag name (tag_name), and not a hierarchy path.
tag_name follows along as a metric's attribute.
| Edge's field | Sparkplug attribute |
|---|---|
| Description | documentation |
| Tag name | displayName — omitted if identical to the tag id |
| Unit | engUnit |
The axis that breaks the consumer side is tag_id. Changing the display name shown on screen is safe, but changing the tag id breaks the mapping on the receiving side.
Lifecycle — connect and disconnect
- When connecting to the broker,
NDEATHis registered as the will — if Edge suddenly dies, the broker notifies on its behalf - Sends
NBIRTH - Sends
DBIRTHfor all devices in sequence - From then on, values flow via
DDATA
Only after NBIRTH and the full DBIRTH have "finished" is the initial BIRTH marked complete — if it fails midway, it remains incomplete.
bdSeq is kept in a file (path in the table above). So when Edge restarts, on the consumer side, the previous session's NDEATH (old bdSeq) goes out first, followed by the new NBIRTH with incremented bdSeq, then all DBIRTH follow. If the file doesn't exist or can't be read, it starts from scratch.
alias — numbers change on reconnect
With alias.enable=true (default), it behaves as standard — BIRTH carries both name and alias together, and afterward DDATA sends only the alias. This makes the payload smaller.
Alias numbers are assigned as 1, 2, 3 … per session. On reconnect, the same tag may get a different number. If you hold onto an old mapping, the value gets attached to the wrong tag — the display looks fine but the value is wrong.
Receiving commands — cmd.enable
Receiving NCMD · DCMD is implemented and off by default (sparkplug.cmd.enable=false). Since this is a feature being rolled out gradually, the default is off.
Opening the command topic means anyone who can connect to the broker can send commands to Edge. Whether that command actually leads to writing to equipment depends on deployment and configuration, so before turning it on, check both broker access control and write permissions.
The "Sparkplug topic" on the Platform screen is different
The UNS screen in the Platform console also shows Sparkplug-style topics. That is a preview showing how names are constructed, and is separate from the export feature described in this document.
Reference links
- Eclipse Tahu —
<https://eclipse.dev/tahu/> - Sparkplug Spec v3.0 —
<https://sparkplug.eclipse.org/specification/> - Cirrus Link MQTT Engine —
<https://www.cirrus-link.com/mqtt-engine/>