Appearance
MQTT Sparkplug B
Last updated
License feature: MQTT Sparkplug BScada.Ink can act as a Sparkplug B edge node: it connects to an MQTT broker and publishes the live values of the devices you choose, with birth and death certificates so a Sparkplug host (Ignition MQTT Engine, HiveMQ, a unified-namespace consumer) discovers the tags on its own.
It publishes, and — only for device mappings you opt in — accepts writes from the host (DCMD). Scada.Ink does not act as a Sparkplug host and does not subscribe to other edge nodes. To read data from an MQTT broker into Scada.Ink, add an MQTT device instead — see Open Standards.
Where and who
System → Sparkplug (/sparkplug, title MQTT Sparkplug B). Needs the mqtt_sparkplug licensed feature. Anyone with the feature can view connections and status; creating, editing, connecting, disconnecting and mapping devices needs admin. The page has three tabs: Connections, Device Map and Status.
Set up publishing
- On Connections, click New Connection.
- Enter Name, Broker URL (for example
tcp://10.20.0.5:1883), Group ID (for examplePlantA) and Node ID (for exampleLine3-Edge). Add Username and Password if the broker needs them. - For TLS, tick Use TLS and paste the certificates (below).
- Click Create Connection.
- Click the power icon (Connect) on the connection's row. This also marks it to reconnect automatically when the API restarts.
- Open Device Map, pick the connection, click Add Device.
- Choose the Local Device, type a Sparkplug Device ID (for example
Press4), set Publish Interval (ms) and optionally a Tag Filter, then Add. - Watch the Status tab: the connection should show
connected. On the broker, subscribe tospBv1.0/PlantA/#to see the NBIRTH, DBIRTH and DDATA messages.
Connection fields
| Field | What it does | Default | Notes |
|---|---|---|---|
| Name | Label in the list and the Status tab | — | Required |
| Broker URL | Broker address as tcp://host:port or mqtts://host:port | tcp://localhost:1883 | Required; not validated — a typo shows up as a connection error |
| Group ID | Sparkplug group — first level after spBv1.0/ | ScadaINK | Required. Avoid /, + and #; they are not rejected but break the topic |
| Node ID | Sparkplug edge node id | Edge1 | Required; must be unique on the broker within the group |
| Username / Password | Broker credentials | empty | The password is stored encrypted on the appliance and reads back as •••••••• |
| Keep Alive (s) | MQTT keep-alive | 60 | Form minimum 10 |
| Use TLS | Connect with TLS | off | See TLS below |
| Enabled | Connect automatically when the API starts | off | Ticking it does not connect now — use Connect |
| CA Certificate, Client Certificate, Client Key | PEM text, shown when Use TLS is ticked | empty | Paste the whole -----BEGIN …----- block |
When you edit a connection, the Password shows as •••••••• and the certificate fields are empty, because the appliance never sends them back to the browser. Leave them as they are to keep what's stored; type or paste a new value to replace it.
The Password can be a reference to the Secrets store, written ${secret:BROKER_PW}. A reference is a name rather than a credential, so the field shows it as you typed it; the appliance looks the value up each time it connects to the broker. A name that matches no secret leaves the connection in error with Secret "BROKER_PW" is not in the Secrets store, and nothing is sent to the broker.
Edits are not applied to a live connection: click Disconnect, then Connect, after saving.
Device mapping fields
| Field | What it does | Default | Notes |
|---|---|---|---|
| Local Device | The Scada.Ink device whose tags are published | — | Required; any device, including Local Tags. One mapping per device per connection; cannot be changed when editing |
| Sparkplug Device ID | Last topic level, for example spBv1.0/PlantA/DDATA/Line3-Edge/Press4 | — | Required |
| Publish Interval (ms) | How often changed values are sent | 1000 | Form minimum 100 |
| Tag Filter (glob, empty = all) | Which tag paths to publish | empty (all) | Matched against the whole tag path; * matches within one path level (Spindle/*), ** matches across levels (Spindle/**) |
| Enabled | Include this mapping | on | |
| Accept commands (DCMD) | Let the host write to this device's tags | off | See Commands from the host below |
What is published
| Message | Topic | When | Content |
|---|---|---|---|
| NBIRTH | spBv1.0/<group>/NBIRTH/<node> | On every connect and reconnect, and on Rebirth | bdSeq and Node Control/Rebirth (Boolean, false) |
| DBIRTH | spBv1.0/<group>/DBIRTH/<node>/<device> | After NBIRTH for each enabled mapping; when a device reconnects; when mappings change | Every tag the device currently has a value for, filtered by Tag Filter |
| DDATA | spBv1.0/<group>/DDATA/<node>/<device> | Every Publish Interval if anything changed | Only the tags that changed since the last send |
| DDEATH | spBv1.0/<group>/DDEATH/<node>/<device> | When the device's status becomes disconnected | No metrics |
| NDEATH | spBv1.0/<group>/NDEATH/<node> | Sent by the broker as the last will when the connection drops, including Disconnect | bdSeq |
- Metric names are the Scada.Ink tag paths (
Spindle/Speed). No aliases, units or properties are sent. - Types: integer tags → Int32, float/double tags → Float (32-bit), boolean → Boolean, everything else → String.
- Report by exception. Only changed values are sent, after each tag's own deadband. Nothing is sent for a device whose values did not change. The timestamp on each metric is the time the change reached the Sparkplug service.
- Tags without a value yet are left out of the DBIRTH; if they report later they arrive in DDATA without having been born, which strict hosts may reject — send a Rebirth once everything is connected.
- Device diagnostics such as
_STATUS/Connectedare part of the device's values and are published unless your filter excludes them. - Expression tags cannot be published — they do not belong to a device you can map. Copy them into local tags with a script or workflow if a host needs them.
- Quality. A tag with bad quality (for example, its device lost communication) is published as a null value of its own type, with a
Qualityproperty of 0; an uncertain value keeps its value and carriesQuality64. When the tag reads good again, its next value carriesQuality192. Good values otherwise carry no properties. - Sequence numbers.
seqruns 0–255 across all messages of the connection;bdSeqis a random value chosen at each Connect and repeated in NBIRTH and the last will. - QoS. Births and DDEATH use QoS 1; DDATA uses QoS 0; nothing is retained.
Commands from the host
Scada.Ink subscribes to spBv1.0/<group>/NCMD/<node> and spBv1.0/<group>/DCMD/<node>/+. There is no primary-host (STATE) awareness.
- NCMD: only
Node Control/Rebirth= true is acted on; it republishes NBIRTH and every DBIRTH. Other NCMD metrics are ignored. - DCMD writes each metric's value to the tag of the same path on the mapped device. A DCMD writes to real equipment, so it's refused unless all of these are true:
- The device mapping has Accept commands (DCMD) ticked. It's off for every mapping until you turn it on.
- The metric name is a tag path inside the mapping's Tag Filter, and is a configured tag on that device.
- The device has Allow Tag Writes on. Tags on the Local Tags device are the exception, as for REST and OPC-UA writes.
- The tag has no write security level. A Sparkplug host has no user who could hold one, so such tags can't be written over Sparkplug.
Sparkplug has no reply to a command. A refused or failed command is logged in the API log with the reason (Sparkplug DCMD … refused: …); an applied one is recorded in the Audit Log as sparkplug_write. Null metrics are ignored.
TLS
- Tick Use TLS and put the broker's TLS port in the URL, usually
tcp://broker.plant.local:8883. With Use TLS ticked the connection uses TLS whatever scheme you typed —tcp://host:1883would attempt TLS on port 1883. - Paste the CA Certificate when the broker's certificate is not signed by a public authority (typical on a plant network, and on an air-gapped appliance always).
- Paste Client Certificate and Client Key only if the broker requires client-certificate authentication.
- The broker certificate is always verified, and its name must match the host in the URL. There is no option to skip verification.
- Writing
mqtts://in the URL without ticking Use TLS also connects with TLS, but ignores the pasted certificates.
Restarts and outages
- Connections that are Enabled (set by Connect) reconnect when the API starts; a new
bdSeqis chosen. - If the broker drops, the client retries every second. On reconnect it publishes NBIRTH and all DBIRTHs again.
- Values that change while the broker is unreachable are not buffered — only the latest value per tag is sent after the reconnect. Sparkplug store-and-forward (historical flag) is not implemented.
- Removing a mapping does not send DDEATH for it; the host keeps the device until the node rebirths.
Status and monitoring
The Status tab refreshes every 5 seconds and shows each connection's status (connected, disconnected or error), Broker, Group, Node, TLS and the last error. For a dashboard, add the Sparkplug Status widget and set its Connection ID (the number in /api/sparkplug/connections).
A failing connection shows disconnected between retries, with the last error kept until a connection succeeds. If it never reaches connected and the last error doesn't say why, contact Scada.Ink support for deeper log analysis.
API
| Method | Path | Role | Purpose |
|---|---|---|---|
| GET | /api/sparkplug/connections | viewer | List connections (password masked as ••••••••, or shown as its ${secret:NAME} reference; no certificates) |
| POST | /api/sparkplug/connections | admin | Create |
| PUT | /api/sparkplug/connections/:id | admin | Update (fields you omit are kept; for the password and certificates, an empty string or •••••••• also keeps the stored value) |
| DELETE | /api/sparkplug/connections/:id | admin | Disconnect and delete, with its mappings |
| POST | /api/sparkplug/connections/:id/connect | admin | Connect and enable auto-connect |
| POST | /api/sparkplug/connections/:id/disconnect | admin | Disconnect and disable auto-connect |
| GET | /api/sparkplug/connections/:id/devices | viewer | Device mappings |
| POST | /api/sparkplug/connections/:id/devices | admin | Add a mapping |
| PUT | /api/sparkplug/device-map/:id | admin | Update a mapping |
| DELETE | /api/sparkplug/device-map/:id | admin | Remove a mapping |
A script can GET a connection, change a field, and PUT the whole object back; the masked password keeps the stored one. Mappings take acceptCommands (boolean, default false).
Sparkplug connections and their mappings can be copied between appliances in a configuration bundle (entity type sparkplug); the password and certificates are blanked unless sensitive data is included. See Bundles.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Status stays disconnected | Broker unreachable, wrong port, or credentials refused | Read the last error; test the broker with an MQTT client from the same network |
| The stored broker password could not be decrypted | The appliance's JWT secret changed after the password was saved | Edit the connection and type the password again |
| Host writes don't reach the device | Accept commands off, tag outside the filter, Allow Tag Writes off, or a write security level on the tag | Check the API log for Sparkplug DCMD … refused and the reason |
TLS error such as self-signed certificate or unable to verify the first certificate | CA not pasted, or wrong CA | Paste the CA that signed the broker certificate |
Hostname/IP does not match certificate's altnames | URL uses an IP or name not in the certificate | Use the name the certificate was issued for |
| TLS handshake fails on port 1883 | Use TLS ticked with the plain port | Use the broker's TLS port (usually 8883) |
| Host sees the node but no devices | No enabled mapping, or the device has no values yet | Add a mapping; check the device is connected; send Rebirth |
| Some tags missing | Tag Filter too narrow, or tags had no value at birth | Clear the filter to test; send Rebirth |
403 Feature "mqtt_sparkplug" is not enabled… | Not in the license | Contact your supplier |
MQTT Sparkplug B is not enabled on this license. | License lapsed or changed | Same |
| Changes on the connection do nothing | Edits are not applied to a live connection | Disconnect, then Connect |