sparkplug-specification-3.0.0
sparkplug-specification-3.0.0
0
Sparkplug Specification
Eclipse Sparkplug Contributors
Sparkplug®, Sparkplug Compatible, and the Sparkplug Logo are trademarks of the Eclipse Foundation.
1
Chapter 1. Introduction
1.1. Rationale and Use Case
Eclipse Sparkplug provides an open and freely available specification for how Edge of Network
Gateways (Sparkplug Edge Nodes) or native MQTT enabled end devices and Sparkplug Host
Applications communicate bi-directionally within an MQTT Infrastructure. This document details the
structure and implementation requirements for Sparkplug compliant MQTT Client implementations on
both Edge Nodes and Host Applications.
It is recognized that MQTT is used across a wide spectrum of application solution use-cases, and an
almost indefinable variation of network topologies. To that end the Sparkplug Specification strives to
accomplish the three following goals.
As noted many times in this document one of the many attractive features of MQTT is that it does not
specify any required MQTT Topic Namespace within its implementation. This fact has meant that
MQTT has taken a dominant position across a wide spectrum of IoT solutions. The intent of the
Sparkplug Specification is to identify and document a Topic Namespace that is well thought out and
optimized for the SCADA/IIoT solution sector. In addition, Sparkplug defines a Topic Namespace in
such a way that it provides semantics which allow for automatic discovery and bi-directional
communication between MQTT clients in a system.
One of the unique aspects of MQTT is that it was originally designed for real time SCADA systems to
help reduce data latency over bandwidth limited and outage prone network infrastructures. These can
include cellular, satellite, and other radio based networks. In many implementations the full benefit of
this “Continuous Session Awareness” is not well understood, or not even implemented. The intent of
the Sparkplug Specification is to take full advantage of MQTT’s native Continuous Session Awareness
capability as it applies to real time SCADA/IIoT solutions.
It is important to note that reducing bandwidth usage and being resilient to network drops is
advantageous on more reliable and high bandwidth networks as well. By reducing the bandwidth
usage, Sparkplug is able to move more data through the network because of its efficiency. This in turn
can reduce network costs.
Just as the MQTT Specification does not dictate any particular Topic Namespace, it also does not dictate
any particular payload data encoding. The intent of the Sparkplug Specification is to define payload
encoding mechanisms that remain true to the original, lightweight, bandwidth efficient, low latency
features of MQTT while adding modern encoding schemes targeting the SCADA/IIoT solution space.
2
Sparkplug has defined an approach where the Topic Namespace can aid in the determination of the
encoding scheme of any particular payload. Historically there have been two Sparkplug defined
encoding schemes. The first one was the Sparkplug A and the second is Sparkplug B. Each of these uses
a first topic token identifier so Sparkplug Edge Nodes can declare the payload encoding scheme they are
using. These first topic tokens are:
spAv1.0
spBv1.0
• Sparkplug Identifier
◦ Always sp
◦ Currently v1.0 but denoted in the event that future versions are released
The original Sparkplug A encoding scheme was based on the Eclipse Kura™ open source Google
Protocol Buffer definition. Sparkplug B was released shortly after the release of Sparkplug A and
addressed a number of issues that were present in the A version of the payload encoding scheme. Due
to lack of adoption and the fact that Sparkplug B was made available shortly after the release of A, the
Sparkplug A definition has been omitted from this document and is no longer supported.
The Sparkplug B encoding scheme was created with a richer data model developed with the feedback
of many system integrators and end user customers using MQTT. These additions included metric
timestamp support, complex datatype support, metadata, and other improvements.
1.1.4. Background
MQTT was originally designed as a message transport for real-time SCADA systems. The MQTT
Specification does not specify the Topic Namespace nor does it define the Payload representation of the
data being published and/or subscribed to. In addition to this, since the original use-case for MQTT was
targeting real-time SCADA, there are mechanisms defined to provide the state of an MQTT session such
that SCADA/Control Human-Machine Interface (HMI) application can monitor the current state of any
MQTT enabled device in the infrastructure. As with the Topic Namespace and Payload the way state
information is implemented and managed within the MQTT infrastructure is not defined. All of this
was intentional within the original MQTT Specification to provide maximum flexibility across any
solution sector that might choose to use MQTT infrastructures.
But at some point, for MQTT based solutions to be interoperable within a given market sector, the
Topic Namespace, Payload representation, and session state must be defined. The intent and purpose
of the Sparkplug Specification is to define an MQTT Topic Namespace, payload, and session state
3
management that can be applied generically to the overall IIoT market sector, but specifically meets
the requirements of real-time SCADA/Control HMI solutions. Meeting the operational requirements for
these systems will enable MQTT based infrastructures to provide more valuable real-time information
to Line of Business and MES solution requirements as well.
The purpose of the Sparkplug Specification is to remain true to the original notion of keeping the Topic
Namespace and message sizes to a minimum while still making the overall message transactions and
session state management between MQTT enabled devices and MQTT SCADA/IIoT applications simple,
efficient, easy to understand, and implement.
By using and/or copying this document, or the Eclipse Foundation document from which this statement
is linked, you (the licensee) agree that you have read, understood, and will comply with the following
terms and conditions:
Permission to copy, and distribute the contents of this document, or the Eclipse Foundation document
from which this statement is linked, in any medium for any purpose and without fee or royalty is
hereby granted, provided that you include the following on ALL copies of the document, or portions
thereof, that you use:
• All existing copyright notices, or if one does not exist, a notice (hypertext is preferred, but a textual
representation is permitted) of the form: "Copyright © [$date-of-document] "Eclipse Foundation,
Inc. <<url to this license>> "
Inclusion of the full text of this NOTICE must be provided. We request that authorship attribution be
provided in any software, documents, or other items or products that you create pursuant to the
implementation of the contents of this document, or any portion thereof.
"Copyright (c) 2016-2022 Eclipse Foundation. This software or document includes material copied from
or derived from the Sparkplug Specification: https://www.eclipse.org/tahu/spec/sparkplug_spec.pdf
4
1.2.2. Disclaimers
THIS DOCUMENT IS PROVIDED "AS IS," AND THE COPYRIGHT HOLDERS AND THE ECLIPSE
FOUNDATION MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING,
BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE DOCUMENT ARE SUITABLE FOR ANY
PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD
PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
THE COPYRIGHT HOLDERS AND THE ECLIPSE FOUNDATION WILL NOT BE LIABLE FOR ANY DIRECT,
INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE DOCUMENT OR
THE PERFORMANCE OR IMPLEMENTATION OF THE CONTENTS THEREOF.
The name and trademarks of the copyright holders or the Eclipse Foundation may NOT be used in
advertising or publicity pertaining to this document or its contents without specific, written prior
permission. Title to copyright in this document will at all times remain with copyright holders.
• Chapter 1 - Introduction
• Chapter 2 - Principles
• Chapter 6 - Payloads
• Chapter 7 - Security
• Chapter 9 - Acknowledgements
• Chapter 10 - Conformance
1.4. Terminology
1.4.1. Infrastructure Components
5
Security
Digital Output
Digital Input
4-20ma Input
Primary Application
Analytics
(Sparkplug)
(Sparkplug) Edge Node Device
(Sparkplug)
Historian
(Sparkplug)
MQTT Server
Device
Edge Node
(Sparkplug)
Sensor
Device
IT OT
MQTT Server(s)
Program or device that acts as an intermediary between Clients which publish Application Messages
and Clients which have made Subscriptions[MQTTV5-1.2]. MQTT enabled infrastructure requires that
one or more MQTT Servers are present in the infrastructure. An MQTT Server must be compatible with
the requirements outlined in the Conformance Section. In addition, it must be sized to properly
manage all MQTT message traffic.
One can implement the use (if required) of multiple MQTT servers for redundancy, high availability,
and scalability within any given infrastructure.
Sparkplug Group
Logical or physical group of Edge Nodes that makes sense in the context of a distributed Sparkplug
application. Groups can represent physical groups of Edge Nodes. For example, a Sparkplug Group
6
could represent a set of Edge Nodes at a particular location, facility, or along a specific oil pipeline.
Alternatively, a Sparkplug Group could represent group of similar types of Edge Nodes. For example, it
could represent a particular set of like make and models of embedded gateways. The groups are meant
to be defined by the system architects as appropriate for their particular application.
Any v3.1.1 or v5.0 compliant MQTT Client application that manages an MQTT Session and provides the
physical and/or logical gateway functions required to participate in the Topic Namespace and Payload
definitions described in this document. The Edge Node is responsible for any local protocol interface to
existing devices (PLCs, RTUs, Flow Computers, Sensors, etc.) and/or any local discrete I/O, and/or any
logical internal process variables (PVs).
Sparkplug Device
Physical or logical device that makes sense in the context of a distributed Sparkplug application. Often
times a Sparkplug Device will be a physical PLC, RTU, Flow Computer, Sensor, etc. However, a
Sparkplug device could also represent a logical grouping of data points as makes sense for the specific
Sparkplug Application being developed. For example, it could represent a set of data points across
multiple PLCs that make up a logical device that makes sense within the context of that application.
Any device, sensor, or hardware that directly connects to MQTT infrastructure using a compliant
MQTT v3.1.1 or v5.0 connection with the payload and topic notation as outlined in this Sparkplug
Specification. With MQTT/Sparkplug enabled directly in the device this could bypass the use of a
Sparkplug Edge Node in the infrastructure. In this case, the physical device or sensor is the Edge Node.
It is up to the developer of the application to decide if the concept of a Sparkplug Device is to be used
within their application.
Host Applications
Application that consumes data from Sparkplug Edge Nodes. Depending on the nature of the Host
Application it may consume Edge Node data and display it in a dashboard, it may historize the data in
a database, or it may analyze the data in some way. SCADA/IIoT Hosts, MES, Historians, and Analytics
applications are all examples of potential Sparkplug Host Applications. A Host Application may
perform many different functions in handling the data. In addition, Host Applications may also send
Sparkplug NCMD or DCMD messages to Edge Nodes.
A Sparkplug Edge Node may specify one Host Application as its Primary Host Application. This is
handled by the Edge Node waiting to publish its NBIRTH and DBIRTH messages until the Host
Application that the Edge Node has designated as its Primary Host application has come online.
Sparkplug does not support the notion of multiple Primary Host Applications. This does not preclude
any number of additional Host Applications participating in the infrastructure that are in either a pure
monitoring mode, or in the role of a hot standby should the Edge Node’s Primary Host Application go
offline or become unavailable within the infrastructure.
7
[tck-id-intro-sparkplug-host-state] Sparkplug Host Applications MUST publish STATE messages
denoting their online and offline status.
Most important consumer of Sparkplug Edge Node data. The Primary Host Application must be online
to keep operations running.
A Primary Host Application may be defined by an Edge Node. The Edge Node’s behavior may change
based on the status of its configured Primary Host. It is not required that an Edge Node must have a
Primary Host configured but it may be useful in certain applications. This allows Edge Nodes to make
decisions based on whether or not the Primary Host Application is online or not. For example, an Edge
Node may store data at the edge until a Primary Host Application comes back online. When the
Primary Host Application publishes a new STATE message denoting it is online, the Edge Node can
resume publishing data and also flush any historical data that it may have stored while offline.
In a traditional SCADA system the SCADA Host would be the Primary Host Application. With this same
concept in mind, there can only be one Primary Host Application configured in an Edge Node as a
result.
Sparkplug Identifiers
Sparkplug defines identifiers or IDs for different physical or logical components within the
infrastructure. There are three primary IDs and one that is a composite ID. These are defined as the
following.
• Group ID
◦ [tck-id-intro-group-id-string] The Group ID MUST be a UTF-8 string and used as part of the
Sparkplug topics as defined in the Topics Section.
◦ [tck-id-intro-group-id-chars] Because the Group ID is used in MQTT topic strings the Group
ID MUST only contain characters allowed for MQTT topics per the MQTT Specification.
▪ Non-normative comment: The Group ID represents a general grouping of Edge Nodes that
makes sense within the context of the Sparkplug application and use-case.
• Edge Node ID
▪ Non-normative comment: The Edge Node ID represents a unique identifier for an Edge
Node within the context of the Group ID under which it exists.
• Device ID
8
◦ [tck-id-intro-device-id-string] The Device ID MUST be a UTF-8 string and used as part of the
Sparkplug topics as defined in the Topics Section.
▪ Non-normative comment: The Device ID represents a unique identifier for a Device within
the context of the Edge Node ID under which it exists.
◦ The Edge Node Descriptor is the combination of the Group ID and Edge Node ID.
▪ In other words, no two Edge Nodes within a Sparkplug environment can have the same
Group ID and same Edge Node ID.
▪ Non-normative comment: The Device ID represents a unique identifier for a Device within
the context of the Edge Node ID under which it exists.
Sparkplug Metric
Identifies a single tag change event in the Sparkplug Payload. It represents an event that occurred at
the Edge Node or Device such as a value or quality of a data point changing. For example, it could
represent the value of an analog or boolean changing at a Sparkplug Device. A Sparkplug Metric
typically includes a name, value, and timestamp. Sparkplug Metrics are also used in NCMD and DCMD
messages to send messages to Edge Nodes and Devices to change values at the Edge.
Data Types
There are different uses of the term datatype in the specification. Sparkplug encodes the payloads
using Google Protocol Buffers. Google Protocol Buffers has its own scalar value types here:
https://developers.google.com/protocol-buffers/docs/proto#scalar
The Google Protocol Buffer datatypes define what actually travels over the TCP/IP socket in the MQTT
payload. For ease of programming, Google Protobuf includes a compiler tool that generates code in
multiple different languages. These Protobuf datatypes are then represented by their proper native
programming language datatypes. This is done on a per language basis after the Google Protobuf file is
used to generate the code for each specific language.
In addition to Protobuf datatypes and native programming language datatypes there are also
Sparkplug datatypes. These are defined in the Sparkplug Protobuf Schema. These datatypes are those
that are used for Sparkplug Metrics. Every Metric must include a Sparkplug Datatype in the NBIRTH or
DBIRTH message depending on whether the Metric is a Node level or Device level metric. Each of the
Sparkplug Datatypes is then represented by a Google Protobuf datatype.
9
1.5. Normative References
• [BCP14] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119,
March 1997. Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC
8174, May 2017.
• [MQTTV50] MQTT Version 5.0. Edited by Andrew Banks, Ed Briggs, Ken Borgendale, and Rahul
Gupta. 07 March 2019. OASIS Standard. https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-
os.html. Latest version: https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html.
• [MQTTV311] MQTT Version 3.1.1 Plus Errata 01. Edited by Andrew Banks and Rahul Gupta. 10
December 2015. OASIS Standard Incorporating Approved Errata 01. http://docs.oasis-open.org/mqtt/
mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html. Latest version: http://docs.oasis-
open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html.
1.7. Security
Security is not directly addressed in the Sparkplug Specification with normative statements. However,
security should be addressed appropriately in every Sparkplug system. MQTT clients, servers,
authentication, authorization, network access, physical access, and all other aspects of security should
be addressed based on how the system will be deployed and used. Because Sparkplug utilizes MQTT
and TCP/IP, the security features and best practices of those protocols also applies to Sparkplug. The
security practices related to TCP/IP and MQTT have changed throughout the years and likely will
continue to do so. As a result, the Sparkplug Specification will defer to the underlying protocols and
industry standards for best practices. However, some non-normative statements are included with
regard to security in the Sparkplug Specification.
1.7.1. Authentication
There are several levels of security and access control configured within an MQTT infrastructure. From
a pure MQTT client perspective, the client must provide a unique MQTT Client ID, and an optional
MQTT username and password.
1.7.2. Authorization
Although access control is not mandated in the MQTT Specification for use in MQTT Server
implementations, Access Control List (ACL) functionality is available in many MQTT Server
implementations. The ACL of an MQTT Server implementation is used to specify which Topic
10
Namespace any MQTT Client can subscribe to and publish on. For example, it may make sense to have
an Edge Node’s MQTT client only able to publish on topics associated with it’s Group and Edge Node ID.
This would make it difficult for an MQTT client to spoof another Edge Node whether it be malicious or
a configuration setup error.
1.7.3. Encryption
The MQTT Specification does not specify any TCP/IP security scheme as it was envisaged during
development of the MQTT Specification that TCP/IP security would (and did) change over time.
Although this document will not specify any TCP/IP security schema it will provide examples on how to
secure an MQTT infrastructure using TLS security.
All normative statements in this document are highlighted in yellow text as shown here.
11
Chapter 2. Principles
2.1. Pub/Sub
This section discusses the simple topology shown in "Figure 2 – Simple MQTT Infrastructure"
identifying how each of the components of the infrastructure interacts.
At the simplest level, there are only two components required as shown below. An MQTT client and an
MQTT server are the primary two components. With proper credentials, any MQTT client can connect
to the MQTT server without any notion of other MQTT client applications that are connected. The client
can issue subscriptions to any MQTT messages that it might be interested in as well as start publishing
any message containing data that it has. This is one of the principal notions of IIoT, that is the
decoupling of devices from any direct connection to any one consumer application.
MQTT Client
Sparkplug does not require that RBE be used in all cases. This is to account for special circumstances
that may require periodic reporting. However, as a general rule periodic publishing should not be
used.
12
2.3. Continuous Session Awareness
In any network architecture, network connection "State" is important. In SCADA/IIoT, connection State
is extremely important. State is the session awareness of the MQTT Edge Node and the MQTT Server.
Note the uses of the term session here should not be confused with MQTT’s clean session concept/flags.
That is covered later in this specification. The very reason that most SCADA Host systems in this
market sector are still using legacy poll/response protocols to maintain a notion of the State of the
connection between the SCADA application and the connected devices. “I poll, I get a response, I know
the State of all the I/O points, but now I must poll again because that State may have changed.”
Many implementations of solutions using MQTT treat it as a simple, stateless, pub/sub state machine.
This is quite viable for IoT and some IIoT applications, however it is not taking advantage of the full
capability of MQTT based infrastructures.
One of the primary applications for MQTT as it was originally designed was to provide reliable SCADA
communications over VSAT networks. Due to propagation delay and cost, it was not feasible to use a
poll/response protocol. Instead of a poll/response protocol where all the data was sent in response to
every poll, MQTT was used to publish information from remote sites only when the data changed. This
technique is sometimes called Report by Exception or RBE. But for RBE to work properly in real-time
SCADA, the “state” of the end device needs to be always known. In other words, SCADA/IIoT host could
only rely on RBE data arriving reliably if it could be assured of the state of the MQTT session.
The Eclipse Sparkplug specification defines the use of the MQTT “Will Message” feature [MQTTV5-
3.1.2.5] to provide MQTT session state information to any other interested MQTT client in the
infrastructure. The session state awareness is implemented around a set of defined BIRTH and DEATH
topic namespace and payload definitions in conjunction with the MQTT connection “Keep Alive” timer.
Birth Certificates denote to any subscribing MQTT clients that the Edge Node or Host Application is
now online. For Edge Nodes, the Birth Certificate uses the NBIRTH Sparkplug verb in the topic. For Host
Applications, the spBv1.0/STATE/sparkplug_host_id topic is used. More details and requirements on
Birth certificates can be found in Edge Node Birth Certificates and Host Application Birth Certificates
13
2.5. Persistent vs Non-Persistent Connections for Edge
Nodes
Persistent connections are intended to remain connected to the MQTT infrastructure at all times. They
never send an MQTT DISCONNECT control packet [MQTTV5-3.14] during normal operation. This fact
lets the Host Applications provide the real-time state of every persistent node in the infrastructure
within the configured MQTT Keep Alive period using the BIRTH/DEATH mechanisms defined above.
But in some use cases, such as sending GPS coordinates for asset tracking or other IOT applications
with periodic data from sensors, MQTT enabled devices do not need to remain connected to the MQTT
infrastructure. In these use cases, all the Device needs to do is to issue an MQTT DISCONNECT control
packet prior to going offline to leave the MQTT infrastructure “gracefully”. In this case an MQTT device
or associated DEATH certificate will not be sent to Sparkplug Host Applications. System designers just
need to be aware that the metric in the Host Application will represent “Last Known Good” values with
a timestamp of this data where the current state of the of the MQTT Device is not a real-time indication.
The Host Application metric timestamp values can be used to determine when the values from this
Edge Node were last updated.
Non-persistent MQTT Enabled Devices should still register a proper DEATH Certificate upon the
establishment of an MQTT session. In this manner, the Host Application can still have a good
representation of last known good process variable versus the fact that the MQTT session was
terminated prior to the Edge Node being able to complete its transaction.
14
Chapter 3. Sparkplug Architecture and
Infrastructure Components
This section details the infrastructure components implemented.
Security
Digital Output
Digital Input
4-20ma Input
Primary Application
Analytics
(Sparkplug)
(Sparkplug) Edge Node Device
(Sparkplug)
Historian
(Sparkplug)
MQTT Server
Device
Edge Node
(Sparkplug)
Sensor
Device
IT OT
15
One can implement the use (if required) of multiple MQTT servers for redundancy, high availability,
and scalability within any given infrastructure.
3.3. Device/Sensor
The Device/Sensor represents any physical or logical device connected to the MQTT Edge Node
providing any data, process variables or metrics.
The Primary Host Application is often also referred to as the SCADA Host or IIoT Host. In typical
SCADA/IIoT infrastructure implementations, there will be only one Primary Host Application
responsible for the monitoring and control of a given MQTT Edge Node. Sparkplug does support the
notion of multiple Primary Host Applications for any one Edge Node. This does not preclude any
number of additional Sparkplug Host Applications from participating in the infrastructure that are in
either a pure monitoring mode, or in the role of a hot standby should the Primary Host Application go
offline. In addition, there could be multiple Host Applications which are each the Primary Host
Application for some subset of Edge Nodes connected to the MQTT infrastructure.
16
[tck-id-components-ph-state] A Sparkplug Host Application MUST utilize the STATE messages to
denote whether it is online or offline at any given point in time.
17
Chapter 4. Topics and Messages
To get a working Message Oriented Middleware based SCADA system using MQTT, the first thing that
must be defined is a topic namespace to work within. The beauty of MQTT is the fact that you can just
come up with an arbitrary topic like “Portland/Temperature”, connect to an MQTT Server, and start
publishing the temperature value. For this data to be useful to other MQTT Client applications that
want to consume the temperature values, the Topic Namespace needs to be understood by everyone
participating in the data exchange.
Every MQTT message published typically consists of a topic and payload components. These
components are the overhead of an MQTT message as measured in bytes on the wire. The Eclipse
Sparkplug Specification is designed to keep these components meaningful and easy to understand, but
not to get so verbose as to negatively impact bandwidth/time sensitive data exchange.
namespace/group_id/message_type/edge_node_id/[device_id]
The namespace element of the topic namespace is the root element that will define both the structure
of the remaining namespace elements as well as the encoding used for the associated payload data.
The Sparkplug specification defines two (2) namespaces. One is for Sparkplug payload definition A
(now deprecated), and the second is for the Sparkplug payload definition B.
spBv1.0
Note that for the remainder of this document, the version of the Sparkplug Payload definition does not
affect the topic namespace or session state management as they will remain the same. There are
separate definitions in this document for the encoding used for both the A and B versions of Sparkplug
MQTT message payloads.
The Group ID element of the topic namespace provides for a logical grouping of Sparkplug Edge Nodes
into the MQTT Server and back out to the consuming Sparkplug Host Applications.
18
[tck-id-topic-structure-namespace-valid-group-id] The format of the Group ID MUST be a valid
UTF-8 string with the exception of the reserved characters of + (plus), / (forward slash), and #
(number sign).
In most use cases to minimize bandwidth, the Group ID should be descriptive but as small as possible.
Examples of where the [group_id] might be used include Oil/Gas applications where Sparkplug Edge
Nodes on a physical pipeline segment all have the same [group_id]. Plant floor applications may group
Sparkplug Edge Nodes based on logical cell or manufacturing line requirements.
The message_type element of the topic namespace provides an indication as to how to handle the
MQTT payload of the message. Note that the actual encoding of the payload will vary depending on the
version of the Sparkplug implementation as indicated by the namespace element.
The following message_type elements are defined for the Sparkplug topic namespace:
The specification for each of these message_type elements are detailed later in this document.
The edge_node_id element of the Sparkplug topic namespace uniquely identifies the Sparkplug Edge
Node within the infrastructure.
The topic element edge_node_id travels with every message published and should be as short as
19
possible.
The device_id element of the Sparkplug topic namespace identifies a device attached (physically or
logically) to the Sparkplug Edge Node. Note that the device_id is an optional element within the topic
namespace as some messages will be either originating or destined to the edge_node_id and the
device_id would not be required.
20
Using these defined messages Host Applications can:
• Discover all metadata and monitor state of all Edge Nodes and Devices connected to the MQTT
infrastructure.
• Discover all metrics which include all diagnostics, properties, metadata, and current state values.
This section defines the payload contents and how each of the associated message types can be used.
Topic (NBIRTH)
• [tck-id-topics-nbirth-topic] The Birth Certificate topic for a Sparkplug Edge Node MUST be of
the form namespace/group_id/NBIRTH/edge_node_id where the namespace is replaced with
the specific namespace for this version of Sparkplug and the group_id and edge_node_id are
replaced with the Group and Edge Node ID for this specific Edge Node.
Payload (NBIRTH)
The Sparkplug Edge Node Birth Certificate payload contains everything required to build out a data
structure for all metrics for this Edge Node. At the time any Host Application receives an NBIRTH, the
online state of this Edge Node should be set to true along with the associated online date and time
parameter. Note that the Edge Node Birth Certificate ONLY indicates the Edge Node itself is online and
in an MQTT Session, but any devices that have previously published a DBIRTH will still have STALE
metric quality until the Host Application receives the new DBIRTH messages associated with the new
Sparkplug session..
• [tck-id-topics-nbirth-metric-reqs] The NBIRTH MUST include every metric the Edge Node will
ever report on.
21
• [tck-id-topics-nbirth-bdseq-included] A bdSeq number as a metric MUST be included in the
payload.
◦ The Node Control/Rebirth metric is used by Host Application(s) to request a new NBIRTH and
DBIRTH(s) from an Edge Node.
The NBIRTH message can also include additional Node Control payload components. These are used by
a Sparkplug Host Application to control aspects of the Edge Node. The following are examples of Node
Control metrics.
◦ Used by Host Application(s) to request an Edge Node to walk to the next MQTT Server in its list
in multi-MQTT Server environments.
The NBIRTH message can also include optional ‘Properties’ of an Edge Node. The following are
examples of Property metrics.
Once an Sparkplug Edge Node is online with a proper NBIRTH it is in a mode of quiescent Report by
22
Exception (RBE) or time based reporting of metric information that changes. This enables the
advantages of the native Continuous Session Awareness of MQTT to monitor the state of all connected
Sparkplug Edge Nodes and to rely on Report by Exception (RBE) messages for metric state changes over
the MQTT session connection. Time based reporting is not explicitly disallowed by the Sparkplug
Specification but it is discouraged. Due to the session awareness provided by MQTT and Sparkplug it is
not necessary to send the same data again on a periodic basis.
Topic (NDATA)
• [tck-id-topics-ndata-topic] The Edge Node data topic for a Sparkplug Edge Node MUST be of
the form namespace/group_id/NDATA/edge_node_id where the namespace is replaced with
the specific namespace for this version of Sparkplug and the group_id and edge_node_id are
replaced with the Group and Edge Node ID for this specific Edge Node.
The payload of NDATA messages will contain any RBE or time based metric Edge Node values that need
to be reported to any subscribing MQTT clients.
Payload (NDATA)
• [tck-id-topics-ndata-mqtt] NDATA messages MUST be published with MQTT QoS equal to 0 and
retain equal to false.
• [tck-id-topics-ndata-timestamp] The NDATA MUST include a timestamp denoting the date and
time the message was sent from the Edge Node.
• [tck-id-topics-ndata-payload] The NDATA MUST include the Edge Node’s metrics that have
changed since the last NBIRTH or NDATA message.
The Death Certificate topic and payload described here are not “published” as an MQTT message by a
client, but provided as parameters within the MQTT CONNECT control packet when this Sparkplug
Edge Node first establishes the MQTT Client session.
Immediately upon reception of an Edge Node Death Certificate (NDEATH message) with a bdSeq
number that matches the preceding bdSeq number in the NBIRTH, any Host Application subscribed to
this Edge Node should set the data quality of all metrics to STALE and should note the timestamp when
the NDEATH message was received.
Topic (NDEATH)
• [tck-id-topics-ndeath-topic] The Edge Node Death Certificate topic for a Sparkplug Edge Node
23
MUST be of the form namespace/group_id/NDEATH/edge_node_id where the namespace is
replaced with the specific namespace for this version of Sparkplug and the group_id and
edge_node_id are replaced with the Group and Edge Node ID for this specific Edge Node.
Payload (NDEATH)
The MQTT payload typically associated with this topic can include a Birth/Death sequence number
used to track and synchronize Birth and Death sequences across the MQTT infrastructure. Since this
payload will be defined in advance, and held in the MQTT server and only delivered on the
termination of an MQTT session, not a lot of additional diagnostic information can be pre-populated
into the payload.
Command (NCMD)
Topic (NCMD)
The NCMD command topic provides the topic namespace used to send commands to any connected
Edge Nodes. This means sending an updated metric value to an associated metric included in the
NBIRTH metric list.
• [tck-id-topics-ncmd-topic] The Edge Node command topic for a Sparkplug Edge Node MUST be
of the form namespace/group_id/NCMD/edge_node_id where the namespace is replaced with
the specific namespace for this version of Sparkplug and the group_id and edge_node_id are
replaced with the Group and Edge Node ID for this specific Edge Node.
Payload (NCMD)
• [tck-id-topics-ncmd-mqtt] NCMD messages MUST be published with MQTT QoS equal to 0 and
retain equal to false.
• [tck-id-topics-ncmd-timestamp] The NCMD MUST include a timestamp denoting the date and
time the message was sent from the Host Application’s MQTT client.
• [tck-id-topics-ncmd-payload] The NCMD MUST include the metrics that need to be written to
on the Edge Node.
4.2.2. Device/Sensor
24
Birth Message (DBIRTH)
The Sparkplug Edge Node is responsible for the management of all attached physical and/or logical
devices. Once the Edge Node has published its NBIRTH, any Sparkplug Host Application ensures that
the metric structure has the Edge Node in an online state. But each physical and/or logical device
connected to this node will still need to provide this DBIRTH before Host Applications create/update
the metric structure (if this is the first time this device has been seen) and set any associated metrics in
the application to a “GOOD” state.
The DBIRTH payload contains everything required to build out a data structure for all metrics for this
device. The online state of this device should be set to TRUE along with the associated online date and
time this message was received.
Topic (DBIRTH)
• [tck-id-topics-dbirth-topic] The Device Birth topic for a Sparkplug Device MUST be of the form
namespace/group_id/DBIRTH/edge_node_id/device_id where the namespace is replaced with
the specific namespace for this version of Sparkplug and the group_id, edge_node_id, and
device_id are replaced with the Group, Edge Node, and Device ID for this specific Device.
Payload (DBIRTH)
• [tck-id-topics-dbirth-seq] The DBIRTH MUST include a sequence number in the payload and it
MUST have a value of one greater than the previous MQTT message from the Edge Node
contained unless the previous MQTT message contained a value of 255. In this case the
sequence number MUST be 0.
• [tck-id-topics-dbirth-metric-reqs] The DBIRTH MUST include every metric the Edge Node will
ever report on.
The DBIRTH message can also include optional ‘Device Control’ payload components. These are used
by a Host Application to control aspects of a device. The following are examples of Device Control
metrics.
25
◦ Used by Host Application(s) to request a new DBIRTH from a device.
The DBIRTH message can also include optional ‘Properties’ of a device. The following are examples of
Property metrics.
Once a Sparkplug Edge Node and associated Devices are all online with proper Birth Certificates it is in
a mode of quiescent Report by Exception (RBE) reporting of any metric that changes. This takes
advantage of the native Continuous Session Awareness of MQTT to monitor the state of all connected
devices and can rely on Report by Exception (RBE) messages for any metric value change over the
MQTT session connection. Again, time based reporting can be used instead of RBE but is discouraged
and typically unnecessary.
Topic (DDATA)
• [tck-id-topics-ddata-topic] The Device command topic for a Sparkplug Device MUST be of the
form namespace/group_id/DDATA/edge_node_id/device_id where the namespace is replaced
with the specific namespace for this version of Sparkplug and the group_id, edge_node_id,
and device_id are replaced with the Group, Edge Node, and Device ID for this specific Device.
The payload of DDATA messages can contain one or more metric values that need to be reported.
Payload (DDATA)
• [tck-id-topics-ddata-mqtt] DDATA messages MUST be published with MQTT QoS equal to 0 and
retain equal to false.
• [tck-id-topics-ddata-timestamp] The DDATA MUST include a timestamp denoting the date and
26
time the message was sent from the Edge Node.
• [tck-id-topics-ddata-payload] The DDATA MUST include the Device’s metrics that have
changed since the last DBIRTH or DDATA message.
It is the responsibility of the Sparkplug Edge Node to indicate the real-time state of either physical
legacy device using poll/response protocols and/or local logical devices. If the device becomes
unavailable for any reason (no response, CRC error, etc.) it is the responsibility of the Edge Node to
publish a DDEATH on behalf of the end device.
Immediately upon reception of a DDEATH, any Host Application subscribed to this device should set
the data quality of all metrics for the Device to STALE and should note the timestamp when the
DDEATH message was received.
Topic (DDEATH)
• [tck-id-topics-ddeath-topic] The Device Death Certificate topic for a Sparkplug Device MUST
be of the form namespace/group_id/DDEATH/edge_node_id/device_id where the namespace is
replaced with the specific namespace for this version of Sparkplug and the group_id,
edge_node_id, and device_id are replaced with the Group, Edge Node, and Device ID for this
specific Device.
Payload (DDEATH)
Command (DCMD)
The DCMD topic provides the topic namespace used to publish metrics to any connected device. This
means sending a new metric value to an associated metric included in the DBIRTH metric list.
Topic DCMD)
• [tck-id-topics-dcmd-topic] The Device command topic for a Sparkplug Device MUST be of the
form namespace/group_id/DCMD/edge_node_id/device_id where the namespace is replaced
with the specific namespace for this version of Sparkplug and the group_id, edge_node_id,
and device_id are replaced with the Group, Edge Node, and Device ID for this specific Device.
27
Payload (DCMD)
• [tck-id-topics-dcmd-mqtt] DCMD messages MUST be published with MQTT QoS equal to 0 and
retain equal to false.
• [tck-id-topics-dcmd-timestamp] The DCMD MUST include a timestamp denoting the date and
time the message was sent from the Host Application’s MQTT client.
• [tck-id-topics-dcmd-payload] The DCMD MUST include the metrics that need to be written to
on the Device.
The Birth Certificate that is defined here is an MQTT application level message published by the
Sparkplug Host Application MQTT Client application.
• [tck-id-host-topic-phid-birth-retain] The MQTT retain flag for the Birth Certificate MUST be
set to TRUE
The topic used for the Host Birth Certificate is identical to the topic used for the Death Certificate. [tck-
id-host-topic-phid-birth-topic] The Sparkplug Host Application Birth topic MUST be of the form
spBv1.0/STATE/sparkplug_host_id where the sparkplug_host_id must be replaced with the specific
Spakrplug Host ID of this Sparkplug Host Application.
◦ An appropriate spBv1.0 topic could simply be spBv1.0/. However, it may also make sense for a
Host Application to subscribe only to a specific Sparkplug Group. For example subscribing to
spBv1.0/Group1/ is also valid. A Host Application could even issue a subscription to subscribe to
only a single Sparkplug Edge Node using this: spBv1.0/Group1/+/EdgeNode1/#. A Sparkplug Host
Application could subscribe to a combination of specific Sparkplug Groups and/or Edge Nodes
as well.
28
successfully subscribing its own spBv1.0/STATE/sparkplug_host_id topic.
Sparkplug B payloads are not used for encoding in this payload. This allows Host Applications to work
across Sparkplug payload types.
When the Sparkplug Host Application MQTT client establishes an MQTT session to the MQTT Server(s),
the Death Certificate will be part of the Will Topic and Will Payload registered in the MQTT CONNECT
packet.
• [tck-id-host-topic-phid-death-retain] The MQTT retain flag for the Birth Certificate MUST be
set to TRUE
29
cleanly using MQTT DISCONNECT packet, the Host Application MUST publish a Death
Certificate payload before sending the MQTT DISCONNECT packet with the timestamp set to
the current UTC time the disconnect is occurring.
• [tck-id-host-topic-phid-death-payload-disconnect-with-no-disconnect-packet] If a Host
Application is disconnecting and not using an MQTT DISCONNECT packet, the Host
Application MUST publish a Death Certificate payload before terminating the MQTT
connection with the timestamp set to the current UTC time the disconnect is occurring.
30
Chapter 5. Operational Behavior
An MQTT based SCADA system is unique in that the Primary Host Application is not responsible for
establishing and maintaining connections to the Edge Nodes as is the case in most existing legacy
poll/response device protocols. With an MQTT based architecture, both the Host Applications as well as
the Edge Nodes establish MQTT Sessions with one or more central MQTT Servers. This is the desired
functionality as it provides the necessary decoupling from any one application and any given Edge
Node/Device. Additional Sparkplug Host Application MQTT clients can connect and subscribe to any of
the real time data without impacting the Primary Host Application.
Due to the nature of real time SCADA solutions, it is very important for the Primary Host Application
and all connected Edge Nodes to have the MQTT Session state information for each other. In order to
accomplish this the Sparkplug Topic Namespace definitions for Birth/Death Certificates along with the
defined payloads provide both state and context between the Primary Host Application and the
associated Edge Nodes. In most use cases and solution scenarios there are two main reasons for this
"designation" of a Primary Host Application:
1. Only the Primary Host Application should have the permission to issue commands to Edge Nodes.
2. In high availability and redundancy use cases where multiple MQTT Servers are used, Sparkplug
Edge Nodes need to be aware of whether the Primary Host Application is connected to each MQTT
Server in the infrastructure. If the Primary Host Application STATE shows that an Edge Node is
connected to an MQTT Server that the Primary Host Application is NOT connected to, then the Edge
Node should connect to the next available MQTT Server where STATE for the Primary Host
Application shows online=true.
31
have Sparkplug IDs (Group, Edge Node, or Device IDs) that when converted to lower case
match
◦ For example there should not be two different Edge Nodes publishing NBIRTH messages on
these two topics spBv1.0/Group1/NBIRTH/EdgeNode1 and spBv1.0/group1/NBIRTH/edgenode1
◦ For example a DBIRTH should not contain a metric a and another metric A.
32
Primary Host Application
MQTT Server
(1) CONNECT
(normal operation)
Loss of TCP/IP
connection to MQTT
Server sets Metric to
OFFLINE.
CONNECT
SUBSCRIBE( spBv1.0/# )
SUBSCRIBE( STATE/host_app_id )
(normal operation)
33
The session diagram in Figure 3 - Host Session Establishment shows a very simple topology with a
single MQTT Server. The steps outlined in the session diagram are defined as follows:
1. Sparkplug Host Applications will try to create an MQTT Session using the MQTT CONNECT Control
Packet. A Death Certificate is constructed into the MQTT Will Topic and Will Payload of the
CONNECT Control Packet with a Will QoS set to 1 and Will Retain flag set to true.
The MQTT CONNECT Control Packet is acknowledged as successful with a valid MQTT CONNACK
Control Packet from the MQTT Server. From this point forward in time, the MQTT Server is ready to
deliver a Host Death Certificate any time the Sparkplug Host Application MQTT Client loses
connectivity to the MQTT Server.
2. With the MQTT Session established, Sparkplug Host Application MUST issue an MQTT subscription
for the defined Sparkplug Topic Namespace.
The Host Application is now ready to start receiving MQTT messages from any connected Edge
Node within the infrastructure. At this point, the Host Application can update the MQTT Client
metrics in the Host Application with a current state of online once each Edge Node publishes its
Sparkplug NBIRTH and DBIRTH messages. Since the Sparkplug Host Application is also relying on
the MQTT Session to the MQTT Server(s), the availability of MQTT Servers to the Host Application is
34
also being monitored and reflected in the MQTT Client metrics in the Host Application.
4. If at any point in time Host Application loses connectivity with the defined MQTT Server(s), the
online=true state of the Server is immediately reflected in the MQTT Client metrics in the Host
Application.
All metric data associated with any Sparkplug Edge Node that was connected to that MQTT
Server and known by the Host Application MUST be updated to a STALE data quality if the
Host Application loses connection to the MQTT Server.
◦ This subscription is mandatory as Edge Nodes MUST be able to respond to rebirth requests.
After subscribing, the Edge Node must follow these additional rules.
35
INT64, and the value MUST be incremented by one from the value in the previous MQTT
CONNECT packet unless the value would be greater than 255. If in the previous NBIRTH a
value of 255 was sent, the next MQTT Connect packet Will Message payload bdSeq number
value MUST have a value of 0.
Edge Nodes can be configured to support the concept of a Primary Host Application. In this case, the
Edge Node must wait until the Primary Host Application is online and subscribed to Sparkplug
messages before the Edge Node publishes its NBIRTH and DBIRTH messages. Specifying a Primary Host
is not required for an Edge Node. But it is often desired. For example say an Edge Node is in a
Sparkplug environment and there is a single consuming Host Application that historizes the data. It
would not be beneficial for the Sparkplug Edge Node to publish data if the Host Application is not
connected and subscribed to messages. Instead, it would be better for the Edge Node to store data
while the Host Application is offline. Once the Host Application is properly connected, it could then
send all of its stored data and continue publishing normally. Once the Sparkplug Edge Node has
successfully connected to the MQTT Server, it must publish a NBIRTH message. The NBIRTH message
must follow the following rules. Note if Primary Host is configured for the Edge Node, it must also wait
until the Primary Host denotes it is online before the Edge Node publishes its NBIRTH message.
36
• [tck-id-message-flow-edge-node-birth-publish-nbirth-payload] The Edge Node’s NBIRTH
payload MUST be a Sparkplug Google Protobuf encoded payload.
◦ This will become the starting sequence number which all following messages will include a
sequence number that is one more than the previous up to 255 where it wraps back to zero.
◦ If the Edge Node did not previously receive a STATE message from this Primary Host
Application, it can not check the timestamp value against the previous value. In this case it
MUST honor the online boolean status flag as denoted in the payload.
Most implementations of a Sparkplug Edge Node for real time SCADA systems will try to maintain a
persistent MQTT Session with the MQTT Server Infrastructure. But there are use cases where the MQTT
Session does not need to be persistent. In either case, an Edge Node can try to establish an MQTT
Session at any time and is completely asynchronous from any other MQTT Client in the infrastructure.
The only exception to this rule is the use case where there are multiple MQTT Servers and a Primary
Host Application. Note this does not refer to the use of the MQTT Clean Session flag in MQTT 3.1.1 or the
Clean Start flag in MQTT 5.0. All types of MQTT clients (both Host and Edge Nodes) in a Sparkplug
system MUST always set the Clean Session flag in the MQTT 3.1.1 CONNECT packet to true. When using
MQTT 5.0 the Clean Start flag must be set to true and the MQTT Session Expiry Interval to zero.
37
Primary Host Application Sparkplug Edge Node
MQTT Server
(1) CONNECT
(normal operation)
Death Certificate
CONNECT
(normal operation)
MQTT Server
Primary Host Application Sparkplug Edge Node
38
The session diagram in Figure 4 - Edge Node MQTT Session Establishment shows a very simple
topology with a single MQTT Server. The steps outlined in the session diagram are defined as follows:
1. The Edge Node MQTT Client will attempt to create an MQTT connection to the available MQTT
Server(s) using the MQTT CONNECT Control Packet. The Death Certificate constructed into the Will
Topic and Will Payload follows the format defined in section on NDEATH messages.
2. The subscription to NCMD level topics ensures that Edge Node targeted messages from the Primary
Host Application are delivered. The subscription to DCMD ensures that device targeted messages
from the Primary Host Application are delivered. In infrastructures with multiple MQTT Servers
and a designated Primary Host Application, the subscription to STATE informs the Edge Node the
current state of the Primary Host Application. At this point the Edge Node has fully completed the
steps required for establishing a valid MQTT Session with the Primary Host Application.
3. Once an MQTT Session has been established, the Edge Node MQTT client MUST publish an
application level NBIRTH as defined here. At this point, the Primary Host Application will have all
the information required to build out the Edge Node metric structure and show the Edge Node in
an online state once it publishes its NBIRTH and DBIRTH messages.
4. If at any point in time the Edge Node MQTT Client loses connectivity to the defined MQTT Server(s),
a Death Certificate (NDEATH) is issued by the MQTT Server on behalf of the Edge Node. Upon
receipt of the Death Certificate with a bdSeq number metric that matches the preceding bdSeq
number in the NBIRTH messages, the Primary Host Application should set the state of the Edge
Node to ‘online=false’ and update all metric timestamps related to this Edge Node. Any defined
metrics will be set to a STALE data quality.
a. The bdSeq number is used to correlate an NBIRTH with a NDEATH. Because the NDEATH is
included in the MQTT CONNECT packet, its timestamp (if included) is not useful to Sparkplug
Host Applications. Instead, a bdSeq number must be included as a metric in the payload of the
NDEATH. The same bdSeq number metric value must also be included in the NBIRTH message
published immediately after the MQTT CONNECT. This allows Host Applications to know that a
NDEATH matches a specific NBIRTH message. This is required because timing with Will
Messages may result in NDEATH messages arriving after a new/next NBIRTH message. The
bdSeq number allows Host Applications to know when it must consider the Edge Node offline.
• If an MQTT DISCONNECT packet is sent by the Edge Node, this signals to the MQTT Server that the
Will Message MUST not be delivered by the MQTT Server to subscribers of that message. These
subscribers are typically Sparkplug Host Applications. This is why a Death message MUST be
published before disconnecting from the MQTT Server. It ensures Edge Nodes are notified the Edge
39
Node is now offline.
• If an MQTT DISCONNECT packet is not sent by the Sparkplug Edge Node, the MQTT Server will
eventually deliver the Will Message (Death Certificate) to the subscribers. However, this can take
some time to occur based on when the MQTT Server detects that the Edge Node is no longer
connected. By sending the Death Certificate before disconnecting without sending an MQTT
DISCONNECT packet, we are ensuring that a Death message will be delivered to subscribing clients
promptly. The fact that a second Death message will arrive when the Will Message is delivered is
not significant. This is because the Will Message Death message will contain a bdSeq number that
matches the bdSeq number that is published by the Edge Node immediately before the disconnect.
Because it has a duplicate bdSeq, the Will Message Death message MUST be ignored by the
subscribing Sparkplug Host Application clients.
This allows the MQTT Server to be notified that the Edge Node is offline and as a result the MQTT Will
Message of the Edge Node will not be delivered by the MQTT Server to subscribed MQTT clients.
When an Edge Node goes offline by sending its NDEATH or if an MQTT Server delivers an NDEATH on
behalf of an Edge Node, it is implied that all of the Edge Node’s associated Devices are also offline. In
addition, it is also implied that all metrics in the previous associated NBIRTH and all DBIRTHs in this
Sparkplug session under that Edge Node are now STALE.
For the following normative statements it is up to the designers of the Sparkplug Host Application with
regard to how they mark the Sparkplug Edge Node or Sparkplug Device as offline. It is also up to the
designers of the Sparkplug Host Application on how they mark a metric as STALE. This is an important
aspect of Sparkplug in that an NDEATH means the data was accurate at a time, but now that the MQTT
session has been lost can no longer be considered current or up to date.
Because an NDEATH may be sent on behalf of an Edge Node by an MQTT Server in the MQTT Will
Message, the Sparkplug payload timestamp does not represent the time that the Edge Node actually
went offline. As a result, the timestamp associated with NDEATH events must use the timestamp of
receipt on the Sparkplug Host Application. This is in part why Sparkplug Edge Nodes and Host
Applications must have synced system clocks and all Sparkplug timestamps must be in UTC time.
• [tck-id-operational-behavior-edge-node-termination-host-action-ndeath-node-offline]
Immediately after receiving an NDEATH from an Edge Node, Host Applications MUST mark
the Edge Node as offline using the current Host Application’s system UTC time
• [tck-id-operational-behavior-edge-node-termination-host-action-ndeath-node-tags-stale]
Immediately after receiving an NDEATH from an Edge Node, Host Applications MUST mark
all metrics that were included in the previous NBIRTH as STALE using the current Host
Application’s system UTC time
• [tck-id-operational-behavior-edge-node-termination-host-action-ndeath-devices-offline]
Immediately after receiving an NDEATH from an Edge Node, Host Applications MUST mark
all Sparkplug Devices associated with the Edge Node as offline using the current Host
Application’s system UTC time
• [tck-id-operational-behavior-edge-node-termination-host-action-ndeath-devices-tags-stale]
40
Immediately after receiving an NDEATH from an Edge Node, Host Applications MUST mark
all of the metrics that were included with associated Sparkplug Device DBIRTH messages as
STALEusing the current Host Application’s system UTC time
For the following assertions an online STATE message is one where a Host Application’s JSON payload
has the online key’s value set to true. An offline STATE message is one where the Host Application’s
JSON payload has the online key’s value set to false.
If the Edge Node is configured to use a Primary Host Application, it must also watch for STATE
messages from the Primary Host Application via an MQTT subscription. If the Primary Host
Application denotes it is offline, the Edge Node must disconnect from the current MQTT server
following these rules:
• [tck-id-operational-behavior-edge-node-termination-host-offline-timestamp] Consider an
Edge Node that is configured to use a Primary Host Application and the Edge Node is
connected and publishing. Then it receives an offline STATE message. It MUST NOT
disconnect if the timestamp value is less than the value from the previous online STATE
message.
◦ It must not disconnect because the older timestamp value indicates the Host Application MQTT
session that is being denoted as lost is not the one the current session the Host Application has
established with the MQTT Server. Due to how an MQTT connection can be lost it is possible and
likely that an old Host Application death message could be delivered after a new Host
Application MQTT session is established. In this case, the timestamp value on the incoming
death message will be older than the current timestamp value. For this reason, it must be
ignored.
The preceding sections in this document detail how the Sparkplug Host Application interacts with the
41
MQTT Server infrastructure and how that infrastructure interacts with the notion of a Sparkplug Edge
Node. But to a large extent the technical requirements of those pieces of the infrastructure have
already been provided. For most use cases in this market sector the primary focus will be on the
implementation of the Sparkplug Specification between the native device and the Edge Node API’s.
Prior to sending a DBIRTH message, if the Device supports writing to outputs the MQTT client
associated with the Sparkplug Device must subscribe to receive DCMD messages with the following
rules.
A Device can publish a DBIRTH as long as an NBIRTH has been sent previously and the MQTT session is
active. The DBIRTH message must follow the following rules.
In order to expose and populate the metrics from any device, the following simple session diagram
outlines the requirements:
42
Primary Host Application Sparkplug Edge Node Sparkplug Device
MQTT Server
(1)
(1)
(2)
(3)
Primary Host Application MQTT Server Sparkplug Edge Node Sparkplug Device
The session diagram in Figure 5 - MQTT Device Session Establishment shows a simple topology with all
the Sparkplug elements in place i.e. Host Application, MQTT Server(s), Sparkplug Edge Node and this
element, the device element. The steps outlined in the session diagram are defined as follows:
This flow diagram assumes that at least one MQTT Server is available and operational within the
infrastructure. Without at least a single MQTT Server the remainder of the infrastructure is
unavailable.
2. Assuming the Primary Host Application established MQTT Session with the MQTT Server(s).
3. The Session Establishment of the associated Sparkplug Edge Node is described in Edge Node
Session Establishment. This flow diagram assumes that the Edge Node session has already been
established with the Primary Host Application. Depending on the target platform, the Edge Node
may be a physical "Edge of Network" gateway device polling physical legacy devices via Modbus,
43
AB, DNP3.0, HART, etc, an MQTT enabled sensor or device, or it might be a logical implementation
of one of the Eclipse Tahu compatible implementations for prototype Edge Nodes running on a
Raspberry Pi. Regardless of the implementation, at some point the device interface will need to
provide a state and associated metrics to publish to the MQTT infrastructure.
4. State #4 in the session diagram represents the state at which the Edge Node is ready to report all of
its metric data to the MQTT Server(s) as defined in Sparkplug. It is the responsibility of the Edge
Node (logical or physical) to put this information in the form defined in DBIRTH messages. Upon
receiving the DBIRTH message, the Primary Host Application can build out the proper metric
structure and set the Sparkplug Device to online.
5. Following the Sparkplug Specification in Device Data Messages (DDATA), all subsequent metrics are
published to the Primary Host Application on a Report by Exception (RBE) basis using the DDATA
message format. Time based reporting is not explicitly disallowed by the Sparkplug Specification
but it is discouraged and often unnecessary.
6. If at any time the Sparkplug Device cannot provide real time information, the Sparkplug
Specification requires that an DDEATH be published. This will inform the Primary Host Application
that all metric information associated with that Sparkplug Device be set to a STALE data quality.
When a Sparkplug Device goes offline by having its DDEATH published by an Edge Node, it allows
Sparkplug Host Applications to know that the Sparkplug Device is no longer reporting current and
accurate values to the Edge Node. Therefore the Edge Node is not able to report live/accurate data
values on behalf of the Sparkplug Device to the MQTT Server or in turn to Sparkplug Host Applications.
As a result the Sparkplug Host Applications must mark the Device as offline and denote the Sparkplug
Device’s tags as stale.
For the following normative statements it is up to the designers of the Sparkplug Host Application with
regard to how they mark the Sparkplug Device as offline. It is also up to the designers of the Sparkplug
Host Application on how they mark a metric as STALE. This is an important aspect of Sparkplug in that
an DDEATH means the data was accurate at a time, but now that the connection between the
Sparkplug Edge Node and the Sparkplug Device has been lost can no longer be considered current or
up to date.
The DDEATH is sent on behalf of a Sparkplug Device by a Sparkplug Edge Node. Because of this, the
Sparkplug payload timestamp associated with a DDEATH is considered accurate and must be used as
the timestamp for a Sparkplug Device being marked as offline and for its associated metrics being set
to STALE.
[tck-id-operational-behavior-edge-node-termination-host-action-ddeath-devices-offline]
Immediately after receiving an DDEATH from an Edge Node, Host Applications MUST mark the
Sparkplug Device associated with the Edge Node as offline using the timestamp in the DDEATH
44
payload
[tck-id-operational-behavior-edge-node-termination-host-action-ddeath-devices-tags-stale]
Immediately after receiving an DDEATH from an Edge Node, Host Applications MUST mark all of
the metrics that were included with the associated Sparkplug Device DBIRTH messages as STALE
using the timestamp in the DDEATH payload
But unlike legacy SCADA system implementations, all real time process variable information being
published through the MQTT infrastructure is available to any number of additional MQTT Clients in
the business that might be interested in subsets if not all of the real time data.
The only fundamental difference between a Primary Host Application MQTT Client and other
Sparkplug Host Application MQTT Clients is that the Edge Nodes in the infrastructure know to make
sure the Primary Host Application is online before publishing data.
For example, if a Sparkplug Host Application receives messages from an Edge Node with sequence
numbers 1, 2, and 4 then at the time the message with a sequence number 4 arrives, a timer SHOULD
be started within the Host Application. This is the start of the Reordering Timeout timer. A message
with sequence number 3 MUST arrive before the Reordering Timeout elapses. If a message with
sequence number 3 does not arrive before the timeout, a Rebirth Request should be sent to the Edge
Node. This ensures that the session state is properly reestablished. If a message with a sequence
number of 3 arrives before the Reorder Timeout occurs then the timer can be shutdown and normal
operation of the Host Application can continue.
It is also important to note that depending on the Sparkplug Host Application’s purpose it may make
45
sense to never process messages out of order. It also may make sense to not process a message that
arrived out of sequence if its preceding messages didn’t arrive before the Reorder Timeout. These
choices are left to the Sparkplug Host Application developer. For example, a Host Application that is a
time series database may want to insert all data that arrives regardless of the message order. However,
a rules engine Host Application may require that messages are processed in order of their sequence
numbers to preserve the order of events as they occurred at the Edge Node.
◦ Non-normative comment: In most cases a Primary Host Application would send a Rebirth
Request but a Non-Primary Host may not
[tck-id-operational-behavior-primary-application-state-with-multiple-servers-state-subs] When
using multiple MQTT Servers and Edge Nodes are configured with a Primary Host Application,
the Primary Host Application instance MUST be configured to publish a STATE Birth Certificate
and all Edge Nodes configured with a Primary Host Application MUST subscribe to this STATE
message.
[tck-id-operational-behavior-primary-application-state-with-multiple-servers-state] Regardless
of the number of MQTT Servers in a Sparkplug Infrastructure, every time a Primary Host
Application establishes a new MQTT Session with an MQTT Server, the STATE Birth Certificate
46
defined in the STATE description section MUST be the first message that is published after a
successful MQTT Session is established with each MQTT Server.
Sparkplug Edge Nodes in an infrastructure that provides multiple MQTT Servers can establish a
session to any one of the MQTT Servers.
[tck-id-operational-behavior-primary-application-state-with-multiple-servers-single-server] The
Edge Nodes MUST not connected to more than one server at any point in time.
Upon establishing a session, the Edge Node should issue a subscription to the STATE message published
by the Primary Host Application. Since the STATE message is published with the MQTT RETAIN flag set,
MQTT will guarantee that the last STATE message is always available. The Edge Node should examine
the JSON payload of this message to ensure that the value of the online key is true. If the value is false,
this indicates the Primary Application has lost its MQTT Session to this particular MQTT Server.
[tck-id-operational-behavior-primary-application-state-with-multiple-servers-walk] If the
Primary Host Application is offline as denoted via the STATE MQTT Message, the Edge Node
MUST terminate its session with this MQTT Server and move to the next available MQTT Server
that is available.
47
Primary Host Application MQTT Server MQTT Server MQTT Server Sparkplug Edge Node
#1 #2 #n
(5)
Primary Host Application MQTT Server MQTT Server MQTT Server Sparkplug Edge Node
#1 #2 #n
1. When an Edge Node is configured with multiple available MQTT Servers in the infrastructure it
should issue a subscription to the Primary Host Application STATE message. The Edge Nodes are
free to establish an MQTT Session to any of the available servers over any available network at any
time and examine the current STATE value. If the STATE message payload is online=false then the
Edge Node should disconnect and walk to the next available server.
2. Upon startup, the configured Primary Host Application’s MQTT Client MUST include the Primary
Host Application DEATH Certificate that indicates STATE is online=false with the message RETAIN
flag set to true in the MQTT Will Message. Then the Primary Host Application BIRTH Certificate
must be published with a STATE payload of online=true. In both of these messages the timestamp
value must match each other and represent the current connection time. The timestamp value
must be a JSON number and represent the number of UTC milliseconds since Epoch.
3. As the Edge Node walks its available MQTT Server list, it will establish an MQTT Session with a
server that has a STATE message with a JSON payload that has online=true. The Edge Node can stay
connected to this server if its MQTT Session stays intact and it does not receive the Primary Host
Application DEATH Certificate.
4. Having a subscription registered to the MQTT Server on the STATE topic will result in any change to
the current Primary Host Application STATE being received immediately. In this case, a network
disruption causes the Primary Host Application MQTT Session to server #2 to be terminated. This
48
will cause the MQTT Server, on behalf of the now terminated the Primary Host Application MQTT
Client, to deliver the Death Certificate to clients that are currently subscribed to it. Upon receipt of
the Primary Host Application Death Certificate each Edge Node will disconnect from the current
MQTT Server and connect to the next MQTT Server in its list. Before the Edge Node disconnects and
connects to the next MQTT Server it must validate that the JSON payload denotes online=false and
the timestamp value is greater than or equal to the prior STATE message timestamp value from that
Host Application’s BIRTH message.
5. The Edge Node connects to the next available MQTT Server and since the current STATE on this
server is online=true, it can stay connected. In the meantime, the network disruption between the
Primary Host Application and MQTT Server #2 has been corrected. The Primary Host Application
has a new MQTT Session established to server #2 with an updated Birth Certificate of online=true.
Now MQTT Server #2 is ready to accept new Edge Node session requests.
• Edge Node Rebirth command to republish all Edge Node and Device Birth Certificates
• Edge Node Next server command to move to next available MQTT Server
The important point to realize is that the metrics exposed in the Primary Host Application for use in
49
the design of applications are completely determined by what metric information is published in the
NBIRTH. This is entirely dependent on the application and use-case. Each specific Edge Node can best
determine what data to expose, and how to expose it, and it will automatically appear in the Primary
Host Application metric structure. Metrics can even be added dynamically at runtime and with a new
NBIRTH and DBIRTH sequence of messages. These metrics will automatically be added to the Primary
Host Application metric structure.
The other very important distinction to make here is that Edge Node NDATA and NCMD messages are
decoupled from the Sparkplug Device level data and command messages of DDATA and DCMD. This
decoupling in the Topic Namespace is important because it allows interaction from all MQTT Clients in
the system (to the level of permission and application) with the Edge Nodes, but NOT to the level of
sending device commands. The Primary Host Application could provide a configuration parameter
that would BLOCK output DDATA and DCMD messages but still allow NDATA and NCMD messages to
flow. In this manner, multiple application systems can be connected to the same MQTT infrastructure,
but only the ones with DCMD enabled can publish Device commands.
It is also important to note that an Access Control List (ACL) can be used to allow one or more
Sparkplug Host Applications to publish NCMD and DCMD messages to one or more Edge Nodes.
Furthermore the ability to publish NCMD or DCMD messages by other Sparkplug Host Applications
could be blocked. The decoupled nature of the commands and data messages allows for this type of
granular access and control.
The following simple message flow diagram demonstrates the messages used to update a changing
cellular RSSI value in the Primary Host Application and sending a command from the Primary Host
Application to the Edge Node to use a different primary network path.
50
Primary Host Application Sparkplug Edge Node
MQTT Server
(1)
(1)
(2)
(3)
PRI_NETWORK set to a
(5)
new value of 2.
2. Assuming the Primary Host Application established MQTT Session with the MQTT Server(s).
3. The Edge Node has an established MQTT Session and the NBIRTH has been published. Primary Host
Application now has all defined metrics and their current value.
4. The Edge Node is monitoring its local cellular RSSI level. The level has changed and now the Edge
Node wants to publish the new value to the associated metric in Primary Host Application.
5. From an operational requirement, the Edge Node needs to be told to switch its primary network
interface from cellular to Ethernet. From the Primary Host Application, the new metric value is
published to the Edge Node using a NCMD Sparkplug message.
51
5.12. MQTT Enabled Device Session Establishment
When implementing Sparkplug directly on an I/O enabled Device, there are two options. The notion of
a Sparkplug Device can be removed entirely. In this scenario the MQTT Client can publish Edge Node
level messages (e.g. NBIRTH, NDEATH, NCMD, and NDATA) and never use the concept of Device level
messages (e.g. DBIRTH, DDEATH, DCMD, and DDATA messages. All of the metrics can be published on
the Edge Node level Sparkplug verbs and simply omit use of the Device level Sparkplug verbs. Because
the Edge Node level verbs encapsulate the MQTT/Sparkplug Session, this is all that is required.
Alternatively, the implementation can use the concept of both Edge Node and Device Sparkplug verbs
(NBIRTH, NDEATH, NDATA, NCMD, DBIRTH, DDEATH, DDATA, and DCMD) as any other Gateway based
Edge Node would. From any consuming application this would look like any other Edge Node Gateway
that may be managing one or more attached devices.
Once the Sparkplug Host Application has successfully connected to the MQTT Server, it must publish a
birth with the following rules.
52
identifier of the Sparkplug Host Application
The following additional rule applies if the Host Application is connecting to more than one MQTT
Server.
◦ For example if a connection is lost to one MQTT Server, when the Host Application reconnects
and publishes a new STATE message, it must update the STATE Message timestamp for only this
MQTT Server and not any others it may be connected to.
◦ If an MQTT DISCONNECT packet is sent by the Host Application, this signals to the MQTT Server
53
that the Will Message MUST not be delivered by the MQTT Server to subscribers of that
message. These subscribers are typically Sparkplug Edge Nodes. This is why a Death message
MUST be published before disconnecting from the MQTT Server. It ensures Edge Nodes are
notified the Host Application is now offline.
◦ If an MQTT DISCONNECT packet is not sent by the Sparkplug Host Application, the MQTT Server
will eventually deliver the Will Message (Death Certificate) to the subscribers. However, this
can take some time to occur based on when the MQTT Server detects that the Host Application
is no longer connected. By sending the Death Certificate before disconnecting without sending
an MQTT DISCONNECT packet, we are ensuring that a Death message will be delivered to
subscribing clients promptly. The fact that a second Death message will arrive when the Will
Message is delivered is not significant. This is because the Will Message Death message will
contain a timestamp older than the timestamp that is published by the Host Application
immediately before the disconnect. Because it has an older timestamp, the Will Message Death
message MUST be ignored by the subscribing Sparkplug clients.
Because there is so much flexibility in what a Sparkplug Host Application may do with the data it
receives there aren’t hard requirements on what it does with it once it receives it. However, there are
some things to consider:
• A Sparkplug Host Application MAY send Node Control/Rebirth NCMD messages if messages arrive
out of sequence order and can not be reordered within the sequence reordering timeout. It is often
reasonable for whether or not a Host Application sends Rebirths to be a configuration option as
this can have an impact on the overall Sparkplug system.
• A Sparkplug Host Application MAY send Node Control/Rebirth NCMD messages if malformed
payloads arrive. Because this can have an impact on the overall system this should be configurable
by the Host Application.
• There are other reasons a Host Application may send out Node Control/Rebirth NCMD messages.
These include but are not limited to:
◦ Receiving any DBIRTH, NDATA, DDATA, or DDEATH before receiving an NBIRTH from a
Sparkplug Edge Node
◦ Receiving a metric in an NDATA message that was not included in the previous NBIRTH
message
54
◦ Receiving a metric in a DDATA message that was not included in the previous DBIRTH message
◦ Receiving an alias value that was not included in the corresponding NBIRTH or DBIRTH
◦ In other words, metric values that have not changed within the same Sparkplug Session
SHOULD not be resent until a new Sparkplug session is established.
◦ This is up to the application developer in terms of how many metrics should be aggregated in a
single message, but it typically doesn’t make sense to publish an MQTT message for every single
metric change.
◦ Multiple value changes for the same metric MAY be included in the same Sparkplug NDATA
message as long as they have different timestamps.
55
set to true and MUST NOT have a value specified.
◦ In other words, metric values that have not changed within the same Sparkplug Session
SHOULD not be resent until a new Sparkplug session is established.
◦ This is up to the application developer in terms of how many metrics should be aggregated in a
single message, but it typically doesn’t make sense to publish an MQTT message for every single
metric change.
◦ Multiple value changes for the same metric MAY be included in the same Sparkplug DDATA
message as long as they have different timestamps.
5.17. Commands
Commands are used in Sparkplug to allow Sparkplug Host Applications to send data to Sparkplug Edge
Nodes. Examples include writing to outputs of Sparkplug Edge Nodes and Devices or to request
Rebirths from Edge Nodes. Custom command endpoints can be declared in an NBIRTH or DBIRTH
message by an Edge Node or Device that may support functionality such as rebooting an Edge Node or
Device. This is up to the Sparkplug implementor to define what functionality can be exposed.
Security and access is an important aspect of commands. It may be the case that not all Sparkplug Host
Applications should have the ability to send commands. This can be controlled in multiple ways. ACLs
(Access Control Lists) may be used to allow/disallow certain MQTT clients from publishing NCMD and
DCMD messages. Security features in the Sparkplug Host Application itself could be used to
allow/disallow certain users or applications from sending certain commands. Security features in the
Sparkplug Edge Node application could be used to allow/disallow CMD messages to be honored. There
are a number of ways in which this can be achieved based on the use case. However, implementation
details are not covered in the Sparkplug Specification and is left to specific application designers to
consider.
There are two types of command (CMD) verbs in Sparkplug. These are NCMD and DCMD messages
which target Edge Nodes and Devices respectively.
There is one NCMD that is required to be implemented for all Sparkplug Edge Nodes and that is the
Node Control/Rebirth command. This exists to allow a Sparkplug Host Application to reset its end-to-
end session with a specific Edge Node. For example, say an Edge Node has been in an established
Sparkplug session and is publishing DATA messages. Now say a new Sparkplug Host Application
connects to the same MQTT Server that the Edge Node is connected to. On the next DATA message
published by the Edge Node, the Host Application will receive it without ever having received the
BIRTH message(s) associated with the Edge Node. As a result, it can send a Rebirth Request using the
56
Node Control/Refresh metric to reset its understanding of that Edge Node and become aware of all
metrics associated with it.
◦ This is to ensure that any Host Application connecting to the MQTT Server is capable of
requesting a rebirth without knowledge of any potential alias being used for this metric.
A Rebirth Request consists of the following message from a Sparkplug Host Application with the
following characteristics.
Upon receipt of a Rebirth Request, the Edge Node must do the following.
◦ Because a new MQTT Session is not being established, there is no reason to update the bdSeq
number
• After the new BIRTH sequence is published, the Edge Node may continue sending DATA messages.
Another common use case for sending commands is to use them to write to outputs on Sparkplug
57
Devices. Often these are PLCs or RTUs with writable outputs. NCMD and DCMD messages can be used
for these writes. The general flow is for a Host Application to send a command message, the Edge
Device receives the message and writes to the output using the native protocol. Then when the output
changes value, it results in the Edge Node publishing a DATA message denoting the new value.
For Edge Node level commands, the following rules must be followed.
◦ Sparkplug Edge Node Applications should be resilient to receiving metrics names that were not
included in the NBIRTH message.
◦ In other words, if the metric has a datatype of a boolean the value must be true or false.
◦ Sparkplug Edge Node Applications should be resilient to receiving metrics names that were not
included in the DBIRTH message.
◦ In other words, if the metric has a datatype of a boolean the value must be true or false.
58
Chapter 6. Payloads
6.1. Overview
The MQTT specification does not define any required data payload format. From an MQTT
infrastructure standpoint, the payload is treated as an agnostic binary array of bytes that can be
anything from no payload at all, to a maximum of 256MB. But for applications within a known solution
space to work using MQTT the payload representation does need to be defined.
This section of the Eclipse Sparkplug specification defines how MQTT Sparkplug payloads are encoded
and the data that is required. Sparkplug supports multiple payloads encoding definitions. There is an A
payload format as well as a B payload format. As described in the Introduction Section Sparkplug A is
deprecated and is not included in this document. This section will only cover the details of the
Sparkplug B payload format.
The majority of devices connecting into next generation IIoT infrastructures are legacy equipment
using poll/response protocols. This means we must take in account register based data from devices
that talk protocols like Modbus. The existing legacy equipment needs to work in concert with emerging
IIoT equipment that is able to leverage message transports like MQTT natively.
Google Protocol Buffers, sometimes referred to as "Google Protobufs", provide the efficiency of packed
binary data encoding while providing the structure required to make it easy to create, transmit, and
parse register based process variables using a standard set of tools while enabling emerging IIoT
requirements around richer metadata. Google Protocol Buffers development tools are available for:
• C
• C++
• C#
• Java
• Python
• GO
• JavaScript
https://developers.google.com/protocol-buffers/
59
6.3. Sparkplug A MQTT Payload Definition
As described in the Introduction Section Sparkplug A is deprecated and is not included in this
document.
The Sparkplug B MQTT payload format has come about based on the feedback from many system
integrators and end users who wanted to be able to natively support a much richer data model within
the MQTT infrastructures that they were designing and deploying. Using the feedback from the user
community Sparkplug B provides support for:
• Datasets
• Richer metrics with the ability to add property metadata for each metric
• Metric alias support to maintain rich metric naming while keeping bandwidth usage to a minimum
• Historical data
• File data
The Sparkplug B payload definition creates a bandwidth efficient data transport for real time device
data. For WAN based SCADA/IIoT infrastructures this equates to lower latency data updates while
minimizing the amount of traffic and therefore cellular and/or VSAT bandwidth required. In situations
where bandwidth savings is not the primary concern, the efficient use enables higher throughput of
more data eliminating sensor data that may have previously been left stranded in the field. It is also
ideal for LAN based SCADA infrastructures equating to higher throughput of real time data to
consumer applications without requiring extreme networking topologies and/or equipment.
There are many data encoding technologies available that can all be used in conjunction with MQTT.
Sparkplug B selected an existing, open, and highly available encoding scheme that efficiently encodes
register based process variables. The encoding technology selected for Sparkplug B is Google Protocol
Buffers.
Using lessons learned on the feedback from the Sparkplug A implementation a new Google Protocol
Buffer schema was developed that could be used to represent and encode the more complex data
models being requested. The entire Google Protocol Buffers definition is below.
60
// * Copyright (c) 2015-2021 Cirrus Link Solutions and others
// *
// * This program and the accompanying materials are made available under the
// * terms of the Eclipse Public License 2.0 which is available at
// * http://www.eclipse.org/legal/epl-2.0.
// *
// * SPDX-License-Identifier: EPL-2.0
// *
// * Contributors:
// * Cirrus Link Solutions - initial implementation
//
// To compile:
// cd client_libraries/java
// protoc --proto_path=../../ --java_out=src/main/java ../../sparkplug_b.proto
//
syntax = "proto2";
package org.eclipse.tahu.protobuf;
enum DataType {
// Indexes of Data Types
// Basic Types
Int8 = 1;
Int16 = 2;
Int32 = 3;
Int64 = 4;
UInt8 = 5;
UInt16 = 6;
UInt32 = 7;
UInt64 = 8;
Float = 9;
Double = 10;
Boolean = 11;
String = 12;
DateTime = 13;
Text = 14;
// Array Types
Int8Array = 22;
Int16Array = 23;
Int32Array = 24;
61
Int64Array = 25;
UInt8Array = 26;
UInt16Array = 27;
UInt32Array = 28;
UInt64Array = 29;
FloatArray = 30;
DoubleArray = 31;
BooleanArray = 32;
StringArray = 33;
DateTimeArray = 34;
}
message Payload {
message Template {
message Parameter {
optional string name = 1;
optional uint32 type = 2;
oneof value {
uint32 int_value = 3;
uint64 long_value = 4;
float float_value = 5;
double double_value = 6;
bool boolean_value = 7;
string string_value = 8;
ParameterValueExtension extension_value = 9;
}
message ParameterValueExtension {
extensions 1 to max;
}
}
message DataSet {
message DataSetValue {
oneof value {
uint32 int_value = 1;
uint64 long_value = 2;
float float_value = 3;
double double_value = 4;
bool boolean_value = 5;
string string_value = 6;
DataSetValueExtension extension_value = 7;
}
message DataSetValueExtension {
extensions 1 to max;
}
}
62
message Row {
repeated DataSetValue elements = 1;
extensions 2 to max; // For third party extensions
}
message PropertyValue {
oneof value {
uint32 int_value = 3;
uint64 long_value = 4;
float float_value = 5;
double double_value = 6;
bool boolean_value = 7;
string string_value = 8;
PropertySet propertyset_value = 9;
PropertySetList propertysets_value = 10; // List of Property Values
PropertyValueExtension extension_value = 11;
}
message PropertyValueExtension {
extensions 1 to max;
}
}
message PropertySet {
repeated string keys = 1; // Names of the properties
repeated PropertyValue values = 2;
extensions 3 to max;
}
message PropertySetList {
repeated PropertySet propertyset = 1;
extensions 2 to max;
}
message MetaData {
// Bytes specific metadata
optional bool is_multi_part = 1;
// General metadata
optional string content_type = 2; // Content/Media type
optional uint64 size = 3; // File size, String size, Multi-part size, etc
optional uint64 seq = 4; // Sequence number for multi-part messages
// File metadata
optional string file_name = 5; // File name
optional string file_type = 6; // File type (i.e. xml, json, txt, cpp, etc)
optional string md5 = 7; // md5 of data
63
extensions 9 to max;
}
message Metric {
oneof value {
uint32 int_value = 10;
uint64 long_value = 11;
float float_value = 12;
double double_value = 13;
bool boolean_value = 14;
string string_value = 15;
bytes bytes_value = 16; // Bytes, File
DataSet dataset_value = 17;
Template template_value = 18;
MetricValueExtension extension_value = 19;
}
message MetricValueExtension {
extensions 1 to max;
}
}
For the remainder of this document JSON will be used to represent components of a Sparkplug B
payload. It is important to note that the payload is a binary encoding and is not actually JSON.
However, JSON representation is used in this document to represent the payloads in a way that is easy
to read. For example, a simple Sparkplug B payload with a single metric can be represented in JSON as
follows:
64
{
"timestamp": <timestamp>,
"metrics": [{
"name": <metric_name>,
"alias": <alias>,
"timestamp": <timestamp>,
"dataType": <datatype>,
"value": <value>
}],
"seq": <sequence_number>
}
{
"timestamp": 1486144502122,
"metrics": [{
"name": "My Metric",
"alias": 1,
"timestamp": 1479123452194,
"dataType": "String",
"value": "Test"
}],
"seq": 2
}
Note that the ‘name’ of a metric may be hierarchical to build out proper folder structures for
applications consuming the metric values. For example, in an application where an Edge Node in
connected to several devices or data sources, the ‘name’ could represent discrete folder structures of:
Using this convention in conjunction with the group_id, edge_node_id and device_id already defined
in the Topic Namespace, consuming applications can organize metrics in the same hierarchical
fashion:
65
Metric Value Data Type
group_id
edge_node_id
device_id
Metric Level 1
Metric Level 2
Metric Name
Figure 9 – Payload Metric Folder Structure
The Sparkplug specification Topics Section defines the Topic Namespace that Sparkplug uses to publish
and subscribe between Edge Nodes and Host Applications within the MQTT infrastructure. Using that
Topic Namespace, this section of the specification defines the actual payload contents of each message
type in Sparkplug B v1.0.
Sparkplug B consists of a series of one or more metrics with metadata surrounding those metrics. The
following definitions explain the components that make up a payload.
6.4.5. Payload
A Sparkplug B payload is the top-level component that is encoded and used in an MQTT message. It
contains some basic information such as a timestamp and a sequence number as well as an array of
metrics which contain key/value pairs of data. A Sparkplug B payload includes the following
components.
• payload
◦ timestamp
▪ This is the timestamp in the form of an unsigned 64-bit integer representing the number of
milliseconds since epoch (Jan 1, 1970).
▪ This timestamp represents the time at which the message was published.
◦ metrics
◦ seq
66
▪ [tck-id-payloads-sequence-num-always-included] A sequence number MUST be
included in the payload of every Sparkplug MQTT message from an Edge Node
except NDEATH messages.
◦ uuid
▪ This is a field which can be used to represent a schema or some other specific form of the
message. Example usage would be to supply a UUID which represents an encoding
mechanism of the optional array of bytes associated with a payload.
◦ body
▪ This is an array of bytes which can be used for any custom binary encoded data.
6.4.6. Metric
A Sparkplug B metric is a core component of data in the payload. It represents a key, value, timestamp,
and datatype along with metadata used to describe the information it contains. These also represent
tags in classic SCADA systems. It includes the following components.
• name
◦ This is the friendly name of a metric. It should be represented as a forward-slash delimited UTF-
8 string. The slashes in the string represent folders of the metric to represent hierarchical data
structures. For example, ‘outputs/A’ would be a metric with a unique identifier of ‘A’ in the
‘outputs’ folder. There is no limit to the number of folders. However, across the infrastructure
of MQTT publishers a defined folder should always remain a folder.
◦ All UTF-8 characters are allowed in the metric name. However, special characters including but
not limited to the following are discouraged: . , \ @ # $ % ^ & * ( ) [ ] { } | ! ` ~ : ; ' " < > ?. This is
because many Sparkplug Host Applications may have issues handling them.
• alias
◦ This is an unsigned 64-bit integer representing an optional alias for a Sparkplug B payload.
Aliases are optional and not required. If aliases are used, the following rules apply.
▪ Non-normative comment: no two metrics for the same Edge Node can have the same
67
alias. Upon being defined in the NBIRTH or DBIRTH, subsequent messages can supply
only the alias instead of the metric friendly name to reduce overall message size.
• timestamp
◦ This is the timestamp in the form of an unsigned 64-bit integer representing the number of
milliseconds since epoch (Jan 1, 1970).
▪ Non-normative comment: This timestamp represents the time at which the value of a metric
was captured.
• datatype
• is_historical
◦ This is a Boolean flag which denotes whether this metric represents a historical value. In some
cases, it may be desirable to send metrics after they were acquired from a device or Edge Node.
This can be done for batching, store and forward, or sending local backup data during network
communication loses. This flag denotes that the message should not be considered a real
time/current value.
• is_transient
◦ This is a Boolean flag which denotes whether this metric should be considered transient.
Transient metrics can be considered those that are of interest to a host application(s) but should
not be stored in a historian.
• is_null
◦ This is a Boolean flag which denotes whether this metric has a null value. This is Sparkplug B’s
68
mechanism of explicitly denoting a metric’s value is actually null.
• metadata
◦ This is a MetaData object associated with the metric for dealing with more complex datatypes.
This is covered in the metadata section.
• properties
◦ This is a PropertySet object associated with the metric for including custom key/value pairs of
metadata associated with a metric. This is covered in the property set section.
• value
◦ The value of a metric utilizes the ‘oneof’ mechanism of Google Protocol Buffers. The value
supplied with a metric MUST be one of the following types. Note if the metrics is_null flag is set
to true the value can be omitted altogether. More information on the Google Protocol Buffer
types can be found here: https://developers.google.com/protocol-buffers/docs/proto#scalar
▪ Sparkplug DataSet
▪ Defined here.
▪ Sparkplug Template
▪ Defined here.
6.4.7. MetaData
A Sparkplug B MetaData object is used to describe different types of binary data. These are optional
and includes the following components.
• is_multi_part
◦ A Boolean representing whether this metric contains part of a multi-part message. Breaking up
large quantities of data can be useful for keeping the flow of MQTT messages flowing through
the system. Because MQTT ensures in-order delivery of QoS 0 messages on the same topic, very
large messages can result in messages being blocked while delivery of large messages takes
place.
• content_type
◦ This is a UTF-8 string which represents the content type of a given metric value if applicable.
69
• size
◦ This is an unsigned 64-bit integer representing the size of the metric value. This is useful when
metric values such as files are sent. This field can be used for the file size.
• seq
◦ If this is a multipart metric, this is an unsigned 64-bit integer representing the sequence
number of this part of a multipart metric.
• file_name
◦ If this is a file metric, this is a UTF-8 string representing the filename of the file.
• file_type
◦ If this is a file metric, this is a UTF-8 string representing the type of the file.
• md5
◦ If this is a byte array or file metric that can have a md5sum, this field can be used as a UTF-8
string to represent it.
• description
◦ This is a freeform field with a UTF-8 string to represent any other pertinent metadata for this
metric. It can contain JSON, XML, text, or anything else that can be understood by both the
publisher and the subscriber.
6.4.8. PropertySet
A Sparkplug B PropertySet object is used with a metric to add custom properties to the object. The
PropertySet is a map expressed as two arrays of equal size, one containing the keys and one containing
the values. It includes the following components.
• keys
◦ This is an array of UTF-8 strings representing the names of the properties in this PropertySet.
• values
◦ This is an array of PropertyValue objects representing the values of the properties in the
PropertySet.
6.4.9. PropertyValue
A Sparkplug B PropertyValue object is used to encode the value and datatype of the value of a property
in a PropertySet. It includes the following components.
70
• type
• is_null
◦ This is a Boolean flag which denotes whether this property has a null value. This is Sparkplug
B’s mechanism of explicitly denoting a property’s value is actually null.
• value
◦ The value of a property utilizes the ‘oneof’ mechanism of Google Protocol Buffers. The value
supplied with a metric MUST be one of the following types. Note if the metrics is_null flag is set
to true the value can be omitted altogether. More information on the Google Protocol Buffer
types can be found here: https://developers.google.com/protocol-buffers/docs/proto#scalar
▪ Sparkplug PropertySet
▪ Defined here.
▪ Sparkplug PropertySetList
▪ Defined here.
Quality Codes
There is one specific property key in Sparkplug called Quality. This defines the quality of the value
associated with the metric. This property is optional and is only required if the quality of the metric is
not GOOD.
There are three possible quality code values. These are defined below with their associated meanings.
• 0
◦ BAD
• 192
71
◦ GOOD
• 500
◦ STALE
6.4.10. PropertySetList
• propertyset
6.4.11. DataSet
A Sparkplug B DataSet object is used to encode matrices of data. It includes the following components.
• num_of_columns
• columns
• types
72
• rows
◦ This is an array of DataSet.Row objects. It contains the data that makes up the data rows of this
DataSet.
6.4.12. DataSet.Row
A Sparkplug B DataSet.Row object represents a row of data in a DataSet. It includes the following
components.
• elements
◦ This is an array of DataSet.DataSetValue objects. It represents the data contained within a row
of a DataSet.
6.4.13. DataSet.DataSetValue
• value
◦ The value of a DataSet.DataSetValue utilizes the ‘oneof’ mechanism of Google Protocol Buffers.
6.4.14. Template
A Sparkplug B Template is used for encoding complex datatypes in a payload. It is a type of metric and
can be used to create custom datatype definitions and instances. These are also sometimes referred to
as User Defined Types or UDTs. There are two types of Templates.
• Template Definition
73
▪ A Template Instance can not reference a Template Definition that was not included in
the NBIRTH.
▪ These act as the defaults for any template instances that don’t include parameter values
in the NBIRTH or DBIRTH messages.
• Template Instance
▪ It must be set to the name of the metric that represents the template definition.
▪ A Template Instance does not need to be a complete set of all member metrics that were
included in the Template Definition.
▪ If a parameter value was included in the Template Definition but not in the Template
Instance the value of that parameter is implicitly the default value from the Template
Definition.
• version
◦ This is an optional field and can be included in a Template Definition or Template Instance.
74
• metrics
◦ This is an array of metrics representing the members of the Template. These can be primitive
datatypes or other Templates as required.
• parameters
◦ This is an option field and is an array of Parameter objects representing parameters associated
with the Template.
• template_ref
• is_definition
6.4.15. Template.Parameter
A Sparkplug B Template.Parameter is a metadata field for a Template. This can be used to represent
parameters that are common across a Template Definition but the values are unique to the Template
instances. It includes the following components.
• name
• type
75
• value
◦ The value of a template parameter utilizes the ‘oneof’ mechanism of Google Protocol Buffers.
◦ For a template definition, this is the default value of the parameter. For a template instance, this
is the value unique to that instance.
Sparkplug defines the valid data types used for various Sparkplug constucts including Metric datatypes
Property Value types, DataSet types, and Template Parameter types. Datatypes are represented as an
enum in Google Protobufs as shown below.
enum DataType {
// Indexes of Data Types
// Basic Types
Int8 = 1;
Int16 = 2;
Int32 = 3;
Int64 = 4;
UInt8 = 5;
UInt16 = 6;
UInt32 = 7;
UInt64 = 8;
Float = 9;
Double = 10;
Boolean = 11;
String = 12;
DateTime = 13;
Text = 14;
76
PropertySet = 20;
PropertySetList = 21;
// Array Types
Int8Array = 22;
Int16Array = 23;
Int32Array = 24;
Int64Array = 25;
UInt8Array = 26;
UInt16Array = 27;
UInt32Array = 28;
UInt64Array = 29;
FloatArray = 30;
DoubleArray = 31;
BooleanArray = 32;
StringArray = 33;
DateTimeArray = 34;
}
• Basic Types
◦ Unknown
◦ Int8
◦ Int16
◦ Int32
◦ Int64
77
▪ Sparkplug enum value: 4
◦ UInt8
◦ UInt16
◦ UInt32
◦ UInt64
◦ Float
◦ Double
◦ Boolean
▪ Boolean value
◦ String
78
▪ Sparkplug enum value: 12
• DateTime
◦ Date time value as uint64 value representing milliseconds since epoch (Jan 1, 1970)
• Text
• Additional Types
◦ UUID
◦ DataSet
◦ Bytes
▪ Array of bytes
◦ File
◦ Template
◦ PropertySet
79
▪ PropertySet as defined here
◦ PropertySetList
• Array Types
All array types use the bytes_value field of the Metric value field. They are simply little-endian packed
byte arrays.
For example, consider an Int32 array with two decimal values [123456789, 987654321]
The bytes_value of the Sparkplug Metric must be: [0x15, 0xCD, 0x5B, 0x07, 0xB1, 0x68, 0xDE, 0x3A]
• Int8Array
• Int16Array
◦ Example (Decimal to Metric bytes_value): [-30000, 30000] → [0xD0, 0x8A, 0x30, 0x75]
• Int32Array
◦ Example (Decimal to Metric bytes_value): [-1, 315338746] → [0xFF, 0xFF, 0xFF, 0xFF, 0xFA,
0xAF, 0xCB, 0x12]
• Int64Array
80
◦ Google Protocol Buffer Type: bytes
• UInt8Array
• UInt16Array
◦ Example (Decimal to Metric bytes_value): [30, 52360] → [0x1E, 0x00, 0x88, 0xCC]
• UInt32Array
◦ Example (Decimal to Metric bytes_value): [52, 3293969225] → [0x34, 0x00, 0x00, 0x00, 0x49,
0xFB, 0x55, 0xC4]
• UInt64Array
• FloatArray
◦ Example (Decimal to Metric bytes_value): [1.23, 89.341] → [0x3F, 0x9D, 0x70, 0xA4, 0x42, 0xB2,
0xAE, 0x98]
• DoubleArray
81
◦ DoubleArray as an array of packed little endian 64-bit float bytes
◦ Example (Decimal to Metric bytes_value): [12.354213, 1022.9123213] → [0x40, 0x28, 0xB5, 0x5B,
0x68, 0x05, 0xA2, 0xD7, 0x40, 0x8F, 0xF7, 0x4C, 0x6F, 0x1C, 0x17, 0x8E]
• BooleanArray
◦ BooleanArray as an array of bit-packed bytes preceeded by a 4-byte integer that represents the
total number of boolean values
◦ Example (boolean array to Metric bytes_value): [false, false, true, true, false, true, false, false,
true, true, false, true] → [0x0C, 0x00, 0x00, 0x00, 0x34, 0xDX]
▪ Note an X above is a do not care. It can be either 1 or 0 but must be present so the array ends
on a byte boundary.
• StringArray
◦ Example (string array to Metric bytes_value): [ABC, hello] → [0x41, 0x42, 0x43, 0x00, 0x68, 0x65,
0x6c, 0x6c, 0x6f, 0x00]
• DateTimeArray
◦ DateTimeArray as an array of packed little endian bytes where each Datetime value is an 8-byte
value representing the number of milliseconds since epoch in UTC
◦ Example (DateTime array → ms since epoch → Metric bytes_value): [Wednesday, October 21,
2009 5:27:55.335 AM, Friday, June 24, 2022 9:57:55 PM] → [1256102875335, 1656107875000] →
[0xC7, 0xD0, 0x90, 0x75, 0x24, 0x01, 0xB8, 0xBA, 0xB8, 0x97, 0x81, 0x01]
Sparkplug B payloads in conjunction with the Sparkplug topic namespace result in hierarchical data
structures that can be represented in folder structures with metrics which are often called tags.
6.4.19. NBIRTH
The NBIRTH is responsible for informing host applications of all of the information about the Edge
82
Node. This includes every metric it will publish data for in the future.
There is a dependency on the MQTT CONNECT packet with regard to NBIRTH messages that are
subsequently sent for that given MQTT Session. These are can be found in the Edge Node Session
Establishment Section
◦ Note if a new NBIRTH is being sent (due to a Rebirth request or ant other reason) the Sparkplug
Edge Node MQTT client MUST publish the same bdSeq number that was sent in the prior MQTT
CONNECT packet Will Message payload. This is because the NDEATH bdSeq number MUST
always match the bdSeq number of the associated NBIRTH that is stored in the MQTT Server via
the MQTT Will Message.
◦ This is used by Host Applications to force an Edge Node to send a new birth sequence (NBIRTH
and DBIRTH messages) if errors are detected by the Host Application in the data stream.
• [tck-id-payloads-nbirth-qos] NBIRTH messages MUST be published with the MQTT QoS set to
0.
spBv1.0/Sparkplug B Devices/NBIRTH/Raspberry Pi
In the topic above the following information is known based on the Sparkplug topic definition:
• The Edge Node Descriptor is the combination of the Group ID and Edge Node ID.
83
Consider the following Sparkplug B payload in the NBIRTH message shown above:
{
"timestamp": 1486144502122,
"metrics": [{
"name": "bdSeq",
"timestamp": 1486144502122,
"dataType": "Int64",
"value": 0
}, {
"name": "Node Control/Reboot",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Node Control/Rebirth",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Node Control/Next Server",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Node Control/Scan Rate",
"timestamp": 1486144502122,
"dataType": "Int64",
"value": 3000
}, {
"name": "Properties/Hardware Make",
"timestamp": 1486144502122,
"dataType": "String",
"value": "Raspberry Pi"
}, {
"name": "Properties/Hardware Model",
"timestamp": 1486144502122,
"dataType": "String",
"value": "Pi 3 Model B"
}, {
"name": "Properties/OS",
"timestamp": 1486144502122,
"dataType": "String",
"value": "Raspbian"
}, {
"name": "Properties/OS Version",
"timestamp": 1486144502122,
84
"dataType": "String",
"value": "Jessie with PIXEL/11.01.2017"
}, {
"name": "Supply Voltage",
"timestamp": 1486144502122,
"dataType": "Float",
"value": 12.1
}],
"seq": 0
}
6.4.20. DBIRTH
The DBIRTH is responsible for informing the Host Application of all of the information about the
device. This includes every metric it will publish data for in the future.
• [tck-id-payloads-dbirth-qos] DBIRTH messages MUST be published with the MQTT QoS set to
0.
85
• [tck-id-payloads-dbirth-retain] DBIRTH messages MUST be published with the MQTT retain
flag set to false.
In the topic above the following information is known based on the Sparkplug topic definition:
Consider the following Sparkplug B payload in the DBIRTH message shown above:
{
"timestamp": 1486144502122,
"metrics": [{
"name": "Inputs/A",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Inputs/B",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Inputs/C",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Inputs/D",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Inputs/Button",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Outputs/E",
86
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Outputs/F",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Outputs/G",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Outputs/H",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Outputs/LEDs/Green",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Outputs/LEDs/Red",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Outputs/LEDs/Yellow",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Outputs/Buzzer",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": false
}, {
"name": "Properties/Hardware Make",
"timestamp": 1486144502122,
"dataType": "String",
"value": "Pibrella"
}],
"seq": 1
}
87
This would result in a structure as follows on the Host Application.
6.4.21. NDATA
NDATA messages are used to update the values of any Edge Node metrics that were originally
published in the NBIRTH message. Any time an input changes on the Edge Node, a NDATA message
should be generated and published to the MQTT Server. If multiple metrics on the Edge Node change,
they can all be included in a single NDATA message. It is also important to note that changes can be
aggregated and published together in a single NDATA message. Because the Sparkplug B payload uses
an ordered List of metrics, multiple different change events for multiple different metrics can all be
included in a single NDATA message.
88
value that is one greater than the previous sequence number sent by the Edge Node. This
value MUST never exceed 255. If in the previous sequence number sent by the Edge Node was
255, the next sequence number sent MUST have a value of 0.
• [tck-id-payloads-ndata-order] All NDATA messages sent by an Edge Node MUST NOT be sent
until all the NBIRTH and all DBIRTH messages have been published by the Edge Node.
• [tck-id-payloads-ndata-qos] NDATA messages MUST be published with the MQTT QoS set to 0.
• [tck-id-payloads-ndata-retain] NDATA messages MUST be published with the MQTT retain flag
set to false.
spBv1.0/Sparkplug B Devices/NDATA/Raspberry Pi
In the topic above the following information is known based on the Sparkplug topic definition:
Consider the following Sparkplug B payload in the NDATA message shown above:
{
"timestamp": 1486144502122,
"metrics": [{
"name": "Supply Voltage",
"timestamp": 1486144502122,
"dataType": "Float",
"value": 12.3
}],
"seq": 2
}
This would result in the host application updating the value of the Supply Voltage metric.
6.4.22. DDATA
DDATA messages are used to update the values of any device metrics that were originally published in
the DBIRTH message. Any time an input changes on the device, a DDATA message should be generated
and published to the MQTT Server. If multiple metrics on the device change, they can all be included in
a single DDATA message. It is also important to note that changes can be aggregated and published
together in a single DDATA message. Because the Sparkplug B payload uses an ordered List of metrics,
multiple different change events for multiple different metrics can all be included in a single DDATA
89
message.
• [tck-id-payloads-ddata-order] All DDATA messages sent by an Edge Node MUST NOT be sent
until all the NBIRTH and all DBIRTH messages have been published by the Edge Node.
• [tck-id-payloads-ddata-qos] DDATA messages MUST be published with the MQTT QoS set to 0.
• [tck-id-payloads-ddata-retain] DDATA messages MUST be published with the MQTT retain flag
set to false.
Consider the following Sparkplug B payload in the DDATA message shown above:
{
"timestamp": 1486144502122,
"metrics": [{
"name": "Inputs/A",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": true
}, {
"name": "Inputs/C",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": true
}],
"seq": 0
}
This would result in the Host Application updating the value of the ‘Inputs/A’ metric and ‘Inputs/C’
90
metric.
6.4.23. NCMD
NCMD messages are used by Host Applications to write to Edge Node outputs and send Node Control
commands to Edge Nodes. Multiple metrics can be supplied in a single NCMD message.
• [tck-id-payloads-ncmd-qos] NCMD messages MUST be published with the MQTT QoS set to 0.
• [tck-id-payloads-ncmd-retain] NCMD messages MUST be published with the MQTT retain flag
set to false.
spBv1.0/Sparkplug B Devices/NCMD/Raspberry Pi
Consider the following Sparkplug B payload in the NCMD message shown above:
{
"timestamp": 1486144502122,
"metrics": [{
"name": "Node Control/Rebirth",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": true
}]
}
This NCMD payload tells the Edge Node to republish its NBIRTH and DBIRTH(s) messages. This can be
requested if a Host Application gets an out of order seq number or if a metric arrives in an NDATA or
DDATA message that was not provided in the original NBIRTH or DBIRTH messages.
6.4.24. DCMD
DCMD messages are used by Host Applications to write to device outputs and send Device Control
commands to devices. Multiple metrics can be supplied in a single DCMD message.
91
• [tck-id-payloads-dcmd-timestamp] DCMD messages MUST include a payload timestamp that
denotes the time at which the message was published.
• [tck-id-payloads-dcmd-qos] DCMD messages MUST be published with the MQTT QoS set to 0.
• [tck-id-payloads-dcmd-retain] DCMD messages MUST be published with the MQTT retain flag
set to false.
Consider the following Sparkplug B payload in the DCMD message shown above:
{
"timestamp": 1486144502122,
"metrics": [{
"name": "Outputs/LEDs/Green",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": true
}, {
"name": "Outputs/LEDs/Yellow",
"timestamp": 1486144502122,
"dataType": "Boolean",
"value": true
}]
}
The DCMD payload tells the Edge Node to write true to the attached device’s green and yellow LEDs. As
a result, the LEDs should turn on and result in a DDATA message back to the MQTT Server after the
LEDs are successfully turned on.
6.4.25. NDEATH
The NDEATH messages are registered with the MQTT Server in the MQTT CONNECT packet as the Will
Message. This is used by Host Applications to know when an Edge Node has lost its MQTT connection
with the MQTT Server.
92
• [tck-id-payloads-ndeath-seq] Every NDEATH message MUST NOT include a sequence number.
• [tck-id-payloads-ndeath-will-message-qos] The NDEATH message MUST set the MQTT Will QoS
to 1 in the MQTT CONNECT packet.
• [tck-id-payloads-ndeath-bdseq] The NDEATH message MUST include the same bdSeq number
value that will be used in the associated NBIRTH message.
◦ This is used by Host Applications to correlate the NDEATH messages with a previously received
NBIRTH message.
◦ It is important to note that any new CONNECT packet must increment the bdSeq number in the
payload compared to what was in the previous CONNECT packet. This ensures that any Host
Applications will be able to distinguish between current and old bdSeq numbers in the event
that messages are delivered out of order. When incrementing the bdSeq number, if the
previous value was 255, the next must be zero.
◦ This allows Host Applications advanced notice that an Edge Node has disconnected rather than
waiting for the NDEATH to be delivered by the MQTT Server based on an MQTT keep alive
timeout.
◦ This is to ensure Host Applications are notified that the Edge Node is disconnecting. Because an
MQTT DISCONNECT packet is sent, the MQTT Server will not deliver the Will Message/NDEATH
on behalf of the disconnecting Edge Node.
◦ This is to ensure Host Applications are notified that the Edge Node is disconnecting by the
MQTT Server.
◦ It should be noted that this timestamp is typically set at the time of the MQTT CONNECT
message and as a result may not be useful to Host Applications. If the timestamp is set, Host
Applications SHOULD NOT use it to determine corresponding NBIRTH messages. Instead, the
bdSeq number used in the NBIRTH and NDEATH messages MUST be used to determine that an
NDEATH matches a prior NBIRTH.
93
The following is a representation of a NDEATH message on the topic:
spBv1.0/Sparkplug B Devices/NDEATH/Raspberry Pi
Consider the following Sparkplug B payload in the NDEATH message shown above:
{
"timestamp": 1486144502122,
"metrics": [{
"name": "bdSeq",
"timestamp": 1486144502122,
"dataType": "UInt64",
"value": 0
}]
}
The payload metric named bdSeq allows a Host Application to reconcile this NDEATH with the NBIRTH
that occurred previously.
6.4.26. DDEATH
The DDEATH messages are published by an Edge Node on behalf of an attached device. If the Edge
Node determines that a device is no longer accessible (i.e. it has turned off, stopped responding, etc.)
the Edge Node should publish a DDEATH to denote that device connectivity has been lost.
94
• The ‘Edge Node ID’ is: Raspberry Pi
Consider the following Sparkplug B payload in the DDEATH message shown above:
{
"timestamp": 1486144502122,
"seq": 123
}
6.4.27. STATE
As noted previously, the STATE messages published by Sparkplug Host Applications do not use
Sparkplug B payloads. State messages are used by Sparkplug Host Applications to denote to Edge Nodes
whether or not the Sparkplug Host Application is online and operational or not.
◦ The [sparkplug_host_id] should be replaced with the Sparkplug Host Application’s ID. This can
be any UTF-8 string.
◦ The [sparkplug_host_id] should be replaced with the Sparkplug Host Application’s ID. This can
be any UTF-8 string.
◦ Non-normative comment: This allows the Sparkplug Host Application handle timing issues
around STATE offline messages being published on it’s behalf by the MQTT Server when it is in
fact online.
95
topic, the Sparkplug Host Application MUST publish an MQTT message on the topic
spBv1.0/STATE/[sparkplug_host_id] with a QoS of 1, and the retain flag set to true.
◦ The [sparkplug_host_id] should be replaced with the Sparkplug Host Application’s ID. This can
be any UTF-8 string.
96
Chapter 7. Security
This chapter is provided for guidance only and is non-normative.
7.1. TLS
The MQTT specification does not specify any TCP/IP security scheme as it was envisaged that TCP/IP
security would (and did) change over time. Although this document will not specify any TCP/IP specific
security requirements it will provide guidelines on how to secure a Sparkplug infrastructure.
7.2. Authentication
There are several levels of security and access control configured within an MQTT infrastructure. From
a pure MQTT client perspective, the client does need to provide a unique Client ID, and an optional
username and password.
7.3. Authorization
Although access control is not mandated in the MQTT specification for use in MQTT Server
implementations, Access Control List (ACL) functionality is available for many MQTT Server
implementations. The ACL of an MQTT Server implementation is used to specify which MQTT topics
any MQTT Client can subscribe and/or publish on. Examples are provided on how to setup and manage
MQTT Client credentials and some considerations on setting up proper ACL’s on the MQTT Servers.
When using public networks and data is sensitive, the underlying socket connections being used by
Sparkplug components should be encrypted. This can be done using
link:https://datatracker.ietf.org/doc/html/rfc5246[TLS] or potential future mechanisms for securing
and encrypting the underlying TCP/IP connection.
ACLs can be defined for Sparkplug clients to restrict each Edge Node to a specific set of topics it can
97
publish and subscribe on. Many MQTT Servers offer the ability to configure ACLs based on client
connection credentials. When supported by the MQTT Server, ACLs offer some security in preventing
compromised credentials from being able to be used to spoof Edge Nodes, write to other Edge Node
outputs, or see all messages flowing through the MQTT Server. Consider the Edge Node with a single
attached Device with the following Sparkplug IDs.
Group ID = G1
Edge Node ID = E1
Device ID = D1
Based on this, the following could be reasonable MQTT ACLs to be provisioned in the MQTT Server for
the MQTT client associated with this Edge Node:
Publish: spBv1.0/G1/NBIRTH/E1
Publish: spBv1.0/G1/NDATA/E1
Publish: spBv1.0/G1/NDEATH/E1
Publish: spBv1.0/G1/DBIRTH/E1/D1
Publish: spBv1.0/G1/DDATA/E1/D1
Publish: spBv1.0/G1/DDEATH/E1/D1
Subscribe: spBv1.0/STATE/my_primary_host
Subscribe: spBv1.0/G1/NCMD/E1
Subscribe: spBv1.0/G1/DCMD/E1/D1
However, there may be other considerations when creating ACLs for clients. It may be the case that an
Edge Node has many dynamic associated devices. In this case, it may make sense to wildcard the
device level topic token. For example, it could look like this:
Publish: spBv1.0/G1/NBIRTH/E1
Publish: spBv1.0/G1/NDATA/E1
Publish: spBv1.0/G1/NDEATH/E1
Publish: spBv1.0/G1/DBIRTH/E1/+
Publish: spBv1.0/G1/DDATA/E1/+
Publish: spBv1.0/G1/DDEATH/E1/+
Subscribe: spBv1.0/STATE/my_primary_host
Subscribe: spBv1.0/G1/NCMD/E1
Subscribe: spBv1.0/G1/DCMD/E1/+
Also, it may be the case that DCMD messages should not be writable. In this case, maybe DCMD
subscriptions should not be allowed at all. In this case, the ACLs could look like this:
98
Publish: spBv1.0/G1/NBIRTH/E1
Publish: spBv1.0/G1/NDATA/E1
Publish: spBv1.0/G1/NDEATH/E1
Publish: spBv1.0/G1/DBIRTH/E1/+
Publish: spBv1.0/G1/DDATA/E1/+
Publish: spBv1.0/G1/DDEATH/E1/+
Subscribe: spBv1.0/STATE/my_primary_host
Subscribe: spBv1.0/G1/NCMD/E1
By using ACLs in this way, the access each Edge Node has is restricted to only topics that it should be
able to publish and subscribe on. If the client credentials for some Edge Node were to be compromised,
the potential harm that could be done by a malicious client would be limited in scope. For example, a
client would not be able to appear to be as some other client. Subscribing on # would not be allowed so
the full scope of a Sparkplug topic namespace could not be realized by the malicious client with the
compromised credentials.
99
Chapter 8. High Availability
Sparkplug based infrastructures are often used in mission-critical environments. Planning for high
availability is a key requirement for many Sparkplug users. This section discusses non-normative
approaches to achieving high availability.
There are two options for MQTT Server High Availability in Sparkplug:
Both approaches have been deployed successfully in mission critical environments and depending on
the MQTT Server software used, not all options might be available.
A single MQTT Server is a single point of failure in a Sparkplug infrastructure, which means a failure
of the Server will cause a downtime for all other components.
MQTT Servers that support clustering allow to install multiple MQTT Servers and connect them to a
cluster. This means all relevant MQTT data is synchronized between these servers. If one or multiple
MQTT Server fail, all data is still present at the other MQTT Servers.
The main advantage of MQTT Server clusters is operations simplicity. Sparkplug components don’t
need to distribute state themselves between MQTT Servers (which is required for Multiple MQTT
Server Topologies). From the perspective of an MQTT Edge Node, MQTT enabled Device, or Sparkplug
Host Application, any of the MQTT Servers can be used and devices are not required to be connected to
the same MQTT Server. A MQTT cluster provides the illusion to MQTT clients that there is only one
MQTT server while providing High Availability.
There are two options available for deploying HA MQTT Server clusters:
In traditional clustered MQTT Server settings, each MQTT Server is reachable by all MQTT Edge Nodes,
100
Sparkplug Host Applications, and MQTT enabled Devices. Each component can connect directly to any
MQTT Server. A message sent to any MQTT Server will be distributed to all available MQTT Servers in
the cluster (which will distribute the message to all subscribing Sparkplug components).
MQTT Edge
Node
Primary Host
Application
MQTT Enabled
Device
MQTT Server
Figure 12 – High Availability MQTT Server Cluster
If any MQTT Server would fail, the MQTT connection for components connected to the broker will
break and the component can connect to any other MQTT Server to resume operations.
For dynamic environments where the IP addresses of the MQTT Servers might not be available
beforehand (like in cloud native deployment environments such as Kubernetes) or for cases where it’s
not desired that all IP addresses (or DNS lookup names) are configured on the Sparkplug components,
a load balancer might be used.
101
Primary Host
Application
MQTT Enabled
Load Balancer
Device
MQTT Edge
Node MQTT Server
A load balancer acts as the single point of contact for Sparkplug components, so only a single IP
address or DNS name needs to be configured on the components. The load balancer will proxy the
MQTT connections of the components and route to one available MQTT Server. In case of a MQTT
Server failure, the component only needs to reconnect to the load balancer again.
The use of a specific load balancer depends on the MQTT Server used. Usually most load balancers
work with most Sparkplug compatible MQTT Servers on the market.
When multiple MQTT Servers are available there is the possibility of “stranding” and Edge Node if the
Primary command/control of the Primary Host Application loses network connectivity to one of the
MQTT Servers. In this instance the Edge Node would stay properly connected to the MQTT Server
publishing information not knowing that Primary Host Application was not able to receive the
messages. When using multiple MQTT Servers, the Primary Host Application instance must be
configured to publish a STATE Birth Certificate and all Edge Nodes need to subscribe to this STATE
message.
The Primary Host Application will need to specify whether it is a “Primary” command/control instance
or not. If it is a primary instance then every time it establishes a new MQTT Session with an MQTT
102
Server, the STATE Birth Certificate defined in section above is the first message that is published after a
successful MQTT Session is established.
Edge Nodes in an infrastructure that provides multiple MQTT Servers can establish a session to any
one of the MQTT Servers. Upon establishing a session, the Edge Node should issue a subscription to the
STATE message published by Primary Host Application. Since the STATE message is published with the
RETAIN message flag set, MQTT will guarantee that the last STATE message is always available. The
Edge Node should examine the JOSN payload of this message to ensure that it is a value of
“online=true”. If the value is “online=false”, this indicates the Primary Application has lost its MQTT
Session to this particular MQTT Server. This should cause the Edge Node to terminate its session with
this MQTT Server and move to the next available MQTT Server that is available. This use of the STATE
message in this manner ensures that any loss of connectivity to an MQTT Server to the Primary Host
Application does not result in Edge Nodes being “stranded” on an MQTT server because of network
issues. The following message flow diagram outlines how the STATE message is used when three (3)
MQTT Servers are available in the infrastructure:
(1)
Establish an MQTT Session with
server and then subscribe to the
STATE message. If payload is
"OFFLINE" walk to the next server.
(2) STATE="ONLINE"
STATE="ONLINE"
STATE="ONLINE"
All tags for all Edge Nodes and Network issues and MQTT session terminated (4) STATE="OFFLINE"
Devices connected to server #2
set to a data quality of "STALE".
All connection metrics updated.
(5)
(6) STATE="ONLINE"
1. When an Edge Node is configured with multiple available MQTT Servers in the infrastructure it
103
should issue a subscription to the Primary Host Application STATE message. The Edge Nodes are
free to establish an MQTT Session to any of the available servers over any available network at any
time and examine the current STATE online value. If the STATE message payload contains
‘online=false’ and the bdSeq number value in the paylaod matches the bdSeq number in the prior
Host Application BIRTH message then the Edge Node should disconnect and walk to the next
available server.
2. Upon startup, the configured Primary Application, the MQTT Session will be configured to register
the Primary Host Application DEATH Certificate that indicates STATE is ‘online=false’ with the
message RETAIN flag set to true. Then the Primary Host Application BIRTH Certificate will be
published with a STATE payload of ‘online=true’.
3. As the Edge Node walks its available MQTT Server table, it will establish an MQTT Session with a
server that has a STATE message with a JSON payload that contains ‘online=true’. The Edge Node
can stay connected to this server if its MQTT Session stays intact and it does not receive the Primary
Host Application DEATH Certificate.
4. Having a subscription registered to the MQTT Server on the STATE topic will result in any change to
the current the Primary Host Application STATE being received immediately. In this case, a network
disruption causes the Primary Host Application MQTT Session to server #2 to be terminated. This
will cause the MQTT Server, on behalf of the now terminated the Primary Host Application MQTT
Client to publish the DEATH certificate to anyone that is currently subscribed to it. Upon receipt of
the Primary Host Application DEATH Certificate this Edge Node will move to the next MQTT Server
in its table.
5. The Edge Node moved to the next available MQTT Server and since the current STATE on this
server is ‘online=true’, it can stay connected.
6. In the meantime, the network disruption between Primary Host Application and MQTT Server #2
has been corrected. The Primary Host Application has a new MQTT Session established to server #2
with an update Birth Certificate with 'online=true’. Now MQTT Server #2 is ready to accept new
Edge Node session requests.
104
Chapter 9. Acknowledgements
The specification would not exist without the initial contribution of the Sparkplug specification by
Cirrus Link Solutions, Wes Johnson, Chad Kienle, and Arlen Nipper. They have also continued to be
involved in promoting, developing, and contributing to the Sparkplug community.
The following individuals are members of the Eclipse Sparkplug Working Group, the Eclipse Sparkplug
Specification project, the Eclipse Tahu project, or otherwise contributed in a meaningful way to the
Sparkplug Specification.
105
Chapter 10. Conformance
10.1. Conformance Profiles
There are four Sparkplug target applications. A Sparkplug infrastructure typically consists of one or
more of the following application types
Each application type has specific conformance requirements that must be met. Typically a Sparkplug
application would only implement one of these profiles. For example an MQTT client wouldn’t
typically be both an Edge Node and a Host Application.
A Sparkplug Edge Node is typically an Edge Gateway. It sends and receives data to an MQTT Server
using the spBv1.0/# namespace. Edge Nodes typically interact with physical devices to gather data and
also write to device outputs.
A Sparkplug Host Application is typically at a central location and primarily receives data from
multiple Sparkplug Edge Nodes. It also may send command messages to Sparkplug Edge Nodes to write
to outputs of Sparkplug Edge Nodes and/or Devices. Sparkplug Host Applications may also sends
rebirth requests to Edge Nodes when required.
Sparkplug infrastructures have a specific subset of requirements on MQTT Servers. Any fully MQTT
v3.1.1 or v5.0 MQTT Server will meet the requirements of Sparkplug infrastructures. However, not all
of the features of the MQTT Specification are required. The following are the required portions of the
MQTT Specification that a Sparkplug Compliant MQTT Server must meet.
106
• [tck-id-conformance-mqtt-will-messages] A Sparkplug conformant MQTT Server MUST
support all aspects of Will Messages including use of the retain flag and QoS 1
A Sparkplug Aware MQTT Server includes all of the aspects of a Sparkplug Compliant MQTT Server. In
addition, it also must have the ability to store NBIRTH and DBIRTH messages of Sparkplug Edge Nodes
that pass through it. Any stored NBIRTH or DBIRTH message must always be the most recent NBIRTH
or DBIRTH that was published to the MQTT Server. In addition, it must make the stored NBIRTH and
DBIRTH messages available to MQTT clients via a retained MQTT message on the appropriate
$sparkplug topic. Note this does not mean that NBIRTH or DBIRTH messages must be published with
the MQTT retain flag set to true. NBIRTH and DBIRTH messages must be published with the MQTT
retain flag set to false. The difference with a Sparkplug Aware MQTT Server is that it will treat NBIRTH
and DBIRTH messages as though their retain flag is set to true even though it is not when published by
a Sparkplug Edge Node.
It is important to note these stored messages are the original NBIRTH and DBIRTH messages published
by each Edge Node. As a result, the metric values can not be expected to be the current values. In a
typical Sparkplug environment the Edge Node likely would have published NDATA and/or DDATA
messages after the NBIRTH and DBIRTH messages denoting metric values that had changed at the Edge
Node and its associated Sparkplug Devices. Consumers of the stored NBIRTH and DBIRTH messages
should take this into consideration when using the information in the stored NBIRTH and DBIRTH
payloads.
◦ Example: Given a group_id=G1 and edge_node_id=E1, the topic the Sparkplug Aware MQTT
Server must make the NBIRTH message available on is:
$sparkplug/certificates/spBv1.0/G1/NBIRTH/E1
107
◦ Example: Given a group_id=G1, edge_node_id=E1 and device_id=D1, the topic the Sparkplug
Aware MQTT Server must make the DBIRTH message available on is:
$sparkplug/certificates/spBv1.0/G1/DBIRTH/E1/D1
108
Chapter 11. Appendix A: Open Source
Software (non-normative)
11.1. OASIS MQTT Specifications
The Sparkplug Specification specifies that MQTT Server/Clients in the infrastructure adhere to the
MQTT v3.1.1 and MQTT v5.0 Specifications. The Sparkplug Specification documentation refers to the
following two links for the MQTT v3.1.1 and v5.0 Specifications.
Also referred is an addendum document to the MQTT v3.1.1 Specification document that discusses best
practices for implementing security on MQTT TCP/IP networks:
• http://docs.oasis-open.org/mqtt/mqtt-nist-cybersecurity/v1.0/mqtt-nist-cybersecurity-v1.0.doc
• https://sparkplug.eclipse.org/
In addition to the Sparkplug Working Group, the Eclipse Foundation has an Internet of Things (IoT)
working group providing a wealth of information and projects around the Internet of Things.
• https://iot.eclipse.org/
• http://www.eclipse.org/paho/
109
https://developers.google.com/protocol-buffers/
• https://github.com/eclipse/kura/blob/develop/kura/org.eclipse.kura.core.cloud/src/main/protobuf/
kurapayload.proto
110
Chapter 12. Appendix B: List of Normative
Statements (non-normative)
12.1. Host Applications
• [tck-id-intro-sparkplug-host-state] Sparkplug Host Applications MUST publish STATE messages
denoting their online and offline status.
• [tck-id-intro-group-id-chars] Because the Group ID is used in MQTT topic strings the Group ID MUST
only contain characters allowed for MQTT topics per the MQTT Specification.
• [tck-id-intro-edge-node-id-string] The Edge Node ID MUST be a UTF-8 string and used as part of the
Sparkplug topics as defined in the Topics Section.
• [tck-id-intro-edge-node-id-chars] Because the Edge Node ID is used in MQTT topic strings the Edge
Node ID MUST only contain characters allowed for MQTT topics per the MQTT Specification.
• [tck-id-intro-device-id-string] The Device ID MUST be a UTF-8 string and used as part of the
Sparkplug topics as defined in the Topics Section.
• [tck-id-intro-device-id-chars] Because the Device ID is used in MQTT topic strings the Device ID
MUST only contain characters allowed for MQTT topics per the MQTT Specification.
111
12.5. Persistent vs Non-Persistent Connections for Edge
Nodes
• [tck-id-principles-persistence-clean-session-311] If the MQTT client is using MQTT v3.1.1, the Edge
Node’s MQTT CONNECT packet MUST set the Clean Session flag to true.
112
12.11. device_id Element
• [tck-id-topic-structure-namespace-valid-device-id] The format of the device_id MUST be a valid
UTF-8 string except for the reserved characters of + (plus), / (forward slash), and # (number sign).
• [tck-id-topics-nbirth-seq-num] The NBIRTH MUST include a sequence number in the payload and it
MUST have a value of 0.
• [tck-id-topics-nbirth-timestamp] The NBIRTH MUST include a timestamp denoting the date and
time the message was sent from the Edge Node.
• [tck-id-topics-nbirth-metric-reqs] The NBIRTH MUST include every metric the Edge Node will ever
report on.
• [tck-id-topics-nbirth-metrics] At a minimum each metric MUST include the metric name, datatype,
and current value.
• [tck-id-topics-nbirth-bdseq-matching] This MUST match the bdSeq number provided in the MQTT
CONNECT packet’s Will Message payload.
• [tck-id-topics-nbirth-bdseq-increment] The bdSeq number MUST start at zero and increment by one
113
on every new MQTT CONNECT packet.
• [tck-id-topics-nbirth-rebirth-metric] The NBIRTH message MUST include a metric with the name
Node Control/Rebirth. It MUST be of datatype boolean and have a value of false.
• [tck-id-topics-ndata-seq-num] The NDATA MUST include a sequence number in the payload and it
MUST have a value of one greater than the previous MQTT message from the Edge Node contained
unless the previous MQTT message contained a value of 255. In this case the sequence number
MUST be 0.
• [tck-id-topics-ndata-timestamp] The NDATA MUST include a timestamp denoting the date and time
the message was sent from the Edge Node.
• [tck-id-topics-ndata-payload] The NDATA MUST include the Edge Node’s metrics that have changed
since the last NBIRTH or NDATA message.
114
the form namespace/group_id/NCMD/edge_node_id where the namespace is replaced with the
specific namespace for this version of Sparkplug and the group_id and edge_node_id are replaced
with the Group and Edge Node ID for this specific Edge Node.
• [tck-id-topics-ncmd-timestamp] The NCMD MUST include a timestamp denoting the date and time
the message was sent from the Host Application’s MQTT client.
• [tck-id-topics-ncmd-payload] The NCMD MUST include the metrics that need to be written to on the
Edge Node.
• [tck-id-topics-dbirth-seq] The DBIRTH MUST include a sequence number in the payload and it MUST
have a value of one greater than the previous MQTT message from the Edge Node contained unless
the previous MQTT message contained a value of 255. In this case the sequence number MUST be 0.
• [tck-id-topics-dbirth-timestamp] The DBIRTH MUST include a timestamp denoting the date and time
the message was sent from the Edge Node.
• [tck-id-topics-dbirth-metric-reqs] The DBIRTH MUST include every metric the Edge Node will ever
report on.
• [tck-id-topics-dbirth-metrics] At a minimum each metric MUST include the metric name, metric
datatype, and current value.
115
12.23. Payload (DDATA)
• [tck-id-topics-ddata-mqtt] DDATA messages MUST be published with MQTT QoS equal to 0 and
retain equal to false.
• [tck-id-topics-ddata-seq-num] The DDATA MUST include a sequence number in the payload and it
MUST have a value of one greater than the previous MQTT message from the Edge Node contained
unless the previous MQTT message contained a value of 255. In this case the sequence number
MUST be 0.
• [tck-id-topics-ddata-timestamp] The DDATA MUST include a timestamp denoting the date and time
the message was sent from the Edge Node.
• [tck-id-topics-ddata-payload] The DDATA MUST include the Device’s metrics that have changed
since the last DBIRTH or DDATA message.
• [tck-id-topics-ddeath-seq-num] The DDEATH MUST include a sequence number in the payload and
it MUST have a value of one greater than the previous MQTT message from the Edge Node
contained unless the previous MQTT message contained a value of 255. In this case the sequence
number MUST be 0.
• [tck-id-topics-dcmd-timestamp] The DCMD MUST include a timestamp denoting the date and time
116
the message was sent from the Host Application’s MQTT client.
• [tck-id-topics-dcmd-payload] The DCMD MUST include the metrics that need to be written to on the
Device.
• [tck-id-host-topic-phid-birth-retain] The MQTT retain flag for the Birth Certificate MUST be set to
TRUE
• [tck-id-host-topic-phid-death-retain] The MQTT retain flag for the Birth Certificate MUST be set to
TRUE
117
12.32. Death Certificate Topic (STATE)
• [tck-id-host-topic-phid-death-topic] The Sparkplug Host Application Death topic MUST be of the
form spBv1.0/STATE/sparkplug_host_id where the sparkplug_host_id must be replaced with the
specific Sparkplug Host ID of this Sparkplug Host Application.
• [tck-id-case-sensitivity-metric-names] An Edge Node SHOULD NOT publish metric names that when
converted to all lower case match.
118
Namespace and the STATE topic MUST be done immediately after successfully establishing the
MQTT session and before publishing its own STATE message.
• All metric data associated with any Sparkplug Edge Node that was connected to that MQTT Server
and known by the Host Application MUST be updated to a STALE data quality if the Host
Application loses connection to the MQTT Server.
119
the value MUST be incremented by one from the value in the previous MQTT CONNECT packet
unless the value would be greater than 255. If in the previous NBIRTH a value of 255 was sent, the
next MQTT Connect packet Will Message payload bdSeq number value MUST have a value of 0.
120
immediately publish an NDEATH message and disconnect from the MQTT Server and start the
connection establishment process over.
• [tck-id-operational-behavior-edge-node-termination-host-action-ndeath-node-offline] Immediately
after receiving an NDEATH from an Edge Node, Host Applications MUST mark the Edge Node as
offline using the current Host Application’s system UTC time
• [tck-id-operational-behavior-edge-node-termination-host-action-ndeath-node-tags-stale]
Immediately after receiving an NDEATH from an Edge Node, Host Applications MUST mark all
metrics that were included in the previous NBIRTH as STALE using the current Host Application’s
system UTC time
• [tck-id-operational-behavior-edge-node-termination-host-action-ndeath-devices-offline]
Immediately after receiving an NDEATH from an Edge Node, Host Applications MUST mark all
Sparkplug Devices associated with the Edge Node as offline using the current Host Application’s
system UTC time
• [tck-id-operational-behavior-edge-node-termination-host-action-ndeath-devices-tags-stale]
Immediately after receiving an NDEATH from an Edge Node, Host Applications MUST mark all of
the metrics that were included with associated Sparkplug Device DBIRTH messages as STALEusing
the current Host Application’s system UTC time
121
spBv1.0/group_id/DCMD/edge_node_id/device_id where group_id is the Sparkplug Group ID the
edge_node_id is the Sparkplug Edge Node ID and the device_id is the Sparkplug Device ID for this
Device. It MUST subscribe on this topic with a QoS of 1.
• [tck-id-operational-behavior-edge-node-termination-host-action-ddeath-devices-offline]
Immediately after receiving an DDEATH from an Edge Node, Host Applications MUST mark the
Sparkplug Device associated with the Edge Node as offline using the timestamp in the DDEATH
payload
• [tck-id-operational-behavior-edge-node-termination-host-action-ddeath-devices-tags-stale]
Immediately after receiving an DDEATH from an Edge Node, Host Applications MUST mark all of
the metrics that were included with the associated Sparkplug Device DBIRTH messages as STALE
using the timestamp in the DDEATH payload
122
the Host Application MUST start a timer denoting the start of the Reorder Timeout window
• [tck-id-operational-behavior-primary-application-state-with-multiple-servers-state] Regardless of
the number of MQTT Servers in a Sparkplug Infrastructure, every time a Primary Host Application
establishes a new MQTT Session with an MQTT Server, the STATE Birth Certificate defined in the
STATE description section MUST be the first message that is published after a successful MQTT
Session is established with each MQTT Server.
• [tck-id-operational-behavior-primary-application-state-with-multiple-servers-single-server] The
Edge Nodes MUST not connected to more than one server at any point in time.
123
MUST be JSON UTF-8 data. It MUST include two key/value pairs where one key MUST be online and
it’s value is a boolean false. The other key MUST be timestamp and the value MUST be the same
value that was used for the timestamp in its own prior MQTT CONNECT packet Will Message
payload.
124
• [tck-id-operational-behavior-host-application-death-retained] The Sparkplug Host Application’s
Death retained flag MUST be set to true.
12.45. Commands
• [tck-id-operational-behavior-data-commands-rebirth-name] An NBIRTH message MUST include a
metric with a name of Node Control/Rebirth.
125
in the NBIRTH message MUST have a value of false.
12.46. Payload
• [tck-id-payloads-timestamp-in-UTC] This timestamp MUST be in UTC.
126
following message MUST be zero.
12.47. Metric
• [tck-id-payloads-name-requirement] The name MUST be included with every metric unless aliases
are being used.
12.48. PropertySet
• [tck-id-payloads-propertyset-keys-array-size] The array of keys in a PropertySet MUST contain the
same number of values included in the array of PropertyValue objects.
12.49. PropertyValue
• [tck-id-payloads-metric-propertyvalue-type-type] This MUST be an unsigned 32-bit integer
representing the datatype.
127
• [tck-id-payloads-metric-propertyvalue-type-req] This MUST be included in Property Value
Definitions in NBIRTH and DBIRTH messages.
12.51. DataSet
• [tck-id-payloads-dataset-column-size] This MUST be an unsigned 64-bit integer representing the
number of columns in this DataSet.
• [tck-id-payloads-dataset-column-num-headers] The size of the array MUST have the same number
of elements that the types array contains.
• [tck-id-payloads-dataset-types-num] The array of types MUST have the same number of elements
that the columns array contains.
• [tck-id-payloads-dataset-types-value] This values in the types array MUST be one of the enumerated
values as shown in the Sparkplug Basic Data Types.
12.52. DataSet.DataSetValue
• [tck-id-payloads-template-dataset-value] The value supplied MUST be one of the following Google
Protobuf types: uint32, uint64, float, double, bool, or string.
12.53. Template
• [tck-id-payloads-template-definition-nbirth-only] Template Definitions MUST only be included in
NBIRTH messages.
128
metrics that will ever be included in corresponding template instances.
12.54. Template.Parameter
• [tck-id-payloads-template-parameter-name-required] This MUST be included in every Template
Parameter definition.
129
• [tck-id-payloads-template-parameter-value-type] This MUST be an unsigned 32-bit integer
representing the datatype.
12.55. NBIRTH
• [tck-id-payloads-nbirth-timestamp] NBIRTH messages MUST include a payload timestamp that
denotes the time at which the message was published.
• [tck-id-payloads-nbirth-seq] Every NBIRTH message MUST include a sequence number and it MUST
have a value between 0 and 255 (inclusive).
• [tck-id-payloads-nbirth-bdseq-repeat] The bdSeq number value MUST match the bdSeq number
value that was sent in the prior MQTT CONNECT packet WILL Message.
• [tck-id-payloads-nbirth-rebirth-req] Every NBIRTH MUST include a metric with the name Node
Control/Rebirth and have a boolean value of false.
• [tck-id-payloads-nbirth-qos] NBIRTH messages MUST be published with the MQTT QoS set to 0.
• [tck-id-payloads-nbirth-retain] NBIRTH messages MUST be published with the MQTT retain flag set
to false.
12.56. DBIRTH
• [tck-id-payloads-dbirth-timestamp] DBIRTH messages MUST include a payload timestamp that
denotes the time at which the message was published.
130
• [tck-id-payloads-dbirth-qos] DBIRTH messages MUST be published with the MQTT QoS set to 0.
• [tck-id-payloads-dbirth-retain] DBIRTH messages MUST be published with the MQTT retain flag set
to false.
12.57. NDATA
• [tck-id-payloads-ndata-timestamp] NDATA messages MUST include a payload timestamp that
denotes the time at which the message was published.
• [tck-id-payloads-ndata-seq-inc] Every NDATA message MUST include a sequence number value that
is one greater than the previous sequence number sent by the Edge Node. This value MUST never
exceed 255. If in the previous sequence number sent by the Edge Node was 255, the next sequence
number sent MUST have a value of 0.
• [tck-id-payloads-ndata-order] All NDATA messages sent by an Edge Node MUST NOT be sent until all
the NBIRTH and all DBIRTH messages have been published by the Edge Node.
• [tck-id-payloads-ndata-qos] NDATA messages MUST be published with the MQTT QoS set to 0.
• [tck-id-payloads-ndata-retain] NDATA messages MUST be published with the MQTT retain flag set to
false.
12.58. DDATA
• [tck-id-payloads-ddata-timestamp] DDATA messages MUST include a payload timestamp that
denotes the time at which the message was published.
• [tck-id-payloads-ddata-seq-inc] Every DDATA message MUST include a sequence number value that
is one greater than the previous sequence number sent by the Edge Node. This value MUST never
exceed 255. If in the previous sequence number sent by the Edge Node was 255, the next sequence
number sent MUST have a value of 0.
• [tck-id-payloads-ddata-order] All DDATA messages sent by an Edge Node MUST NOT be sent until all
the NBIRTH and all DBIRTH messages have been published by the Edge Node.
• [tck-id-payloads-ddata-qos] DDATA messages MUST be published with the MQTT QoS set to 0.
• [tck-id-payloads-ddata-retain] DDATA messages MUST be published with the MQTT retain flag set to
false.
12.59. NCMD
• [tck-id-payloads-ncmd-timestamp] NCMD messages MUST include a payload timestamp that
denotes the time at which the message was published.
131
• [tck-id-payloads-ncmd-qos] NCMD messages MUST be published with the MQTT QoS set to 0.
• [tck-id-payloads-ncmd-retain] NCMD messages MUST be published with the MQTT retain flag set to
false.
12.60. DCMD
• [tck-id-payloads-dcmd-timestamp] DCMD messages MUST include a payload timestamp that
denotes the time at which the message was published.
• [tck-id-payloads-dcmd-qos] DCMD messages MUST be published with the MQTT QoS set to 0.
• [tck-id-payloads-dcmd-retain] DCMD messages MUST be published with the MQTT retain flag set to
false.
12.61. NDEATH
• [tck-id-payloads-ndeath-seq] Every NDEATH message MUST NOT include a sequence number.
• [tck-id-payloads-ndeath-will-message-qos] The NDEATH message MUST set the MQTT Will QoS to 1
in the MQTT CONNECT packet.
• [tck-id-payloads-ndeath-bdseq] The NDEATH message MUST include the same bdSeq number value
that will be used in the associated NBIRTH message.
12.62. DDEATH
• [tck-id-payloads-ddeath-timestamp] DDEATH messages MUST include a payload timestamp that
denotes the time at which the message was published.
132
that is one greater than the previous sequence number sent by the Edge Node. This value MUST
never exceed 255. If in the previous sequence number sent by the Edge Node was 255, the next
sequence number sent MUST have a value of 0.
12.63. STATE
• [tck-id-payloads-state-will-message] Sparkplug Host Applications MUST register a Will Message in
the MQTT CONNECT packet on the topic spBv1.0/STATE/[sparkplug_host_id].
• [tck-id-payloads-state-will-message-qos] The Sparkplug Host Application MUST set the the MQTT
Will QoS to 1 in the MQTT CONNECT packet.
133
aspects of Will Messages including use of the retain flag and QoS 1
134