Sparkplug-B MQTT Payload Format

 

Overview of Sparkplug-B

The Sparkplug-B protocol is based on MQTT as a protocol transport and uses Google Protobuf (Protocol Buffers) as the encapsulated data payload format. Sparkplug-B was developed by Cirrus Link for communication with Inductive Automation’s Ignition® platform, and is managed as an open source IoT protocol in the Eclipse Sparkplug project (based on Eclipse Tahu). See the following link for the full Sparkplug-B protocol specification:

https://www.eclipse.org/tahu/spec/sparkplug_spec.pdf

A few portions of the protocol specification are shown here, for understanding the examples given below:

enum DataType {
// Indexes for "datatype"
Unknown = 0;
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;
}
message Payload {

optional uint64 timestamp = 1; // Timestamp at message sending time
repeated Metric metrics = 2; // Repeated forever - no limit in Google Protobufs
optional uint64 seq = 3; // Sequence number
optional string uuid = 4; // UUID to track message type in terms of schema definitions
optional bytes body = 5; // To optionally bypass the whole definition above
extensions 6 to max; // For third party extensions

message Metric {

optional string name = 1; // Metric name - should only be included on birth
optional uint64 alias = 2; // Metric alias - included in all later DATA messages
optional uint64 timestamp = 3; // data acquisition time
optional uint32 datatype = 4; // DataType of the metric/tag value
optional bool is_historical = 5; // If historical value, don't update real time tag
optional bool is_transient = 6; // Don't store this as a tag
optional bool is_null = 7; // If this is null
optional MetaData metadata = 8; // Metadata for the payload
optional PropertySet properties = 9;
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;
}

}
}

Example Messages

What follows in this document is not a full description of the spec, but just a few examples of Sparkplug-B messages in the RediGate, with some explanatory notes.

NCMD - Edge Node Command Message

Node Rebirth Message

Node Control command (NCMD) to request “Rebirth” from gateway. The gateway must respond with all NBIRTH and DBIRTH messages for the gateway node and its attached devices.

(Note: the Sparkplug-B specification allows an optional DCMD for individual device “Rebirth”, which is not currently implemented in the RediGate. Use NCMD instead.)

Topic: spBv1.0/Group/NCMD/NodeName

Example Sparkplug-B message:

08 9f af b8 f8 8d 31 12 23 0a 14 4E 6F 64 65 20 43 6F 6E 74 72 6F 6C 2F 52 65 62 69 72 74 68 18 9f af b8 f8 8d 31 20 0b 38 00 70 01 18 ff ff ff ff ff ff ff ff ff 01

Interpretation of Protobuf payload:

{“timestamp”: 1687369422751,
”metrics”:[
  {“name”:”Node Control/Rebirth”,”timestamp”:1687369422751,
”datatype”:11,”is_null”:0,”boolean_value”:1} // datatype=Boolean
  ],
”seq”:-1}

DCMD - Device Command Message

Set Register Value

Device Control command (DCMD) to set the value of a register. The RediGate will typically pass this value through to the end device based on Poll Table remapping. For Internal Master or Virtual RTU, it may be passed directly into the RTDB database. RediGate uses the RTDB register address for the “alias,” and either the RTDB register address or a configured Tag name for the “name” of the data item.

Topic: spBv1.0/Group/DCMD/NodeName/DeviceName

Example Sparkplug-B message:

08 c0 b8 d8 9e 8e 31 12 0f 10 9a ef 02 18 c0 b8 d8 9e 8e 31 20 03 50 0f 18 ff ff ff ff ff ff ff ff ff 01 0a

Interpretation of Protobuf payload:

{“timestamp”: 1687449640000,
”metrics”:[
  {“alias”:47002,”timestamp”:1687449640000,
”datatype”:3,”int_value”:15} // datatype=Int32
  ],
”seq”:-1}

Interpretation of integer values: Protobuf uses variable-width integers (varint) that allows encoding up to 64-bit unsigned integers using between 1 and 10 bytes, depending on the size of the value. If the most-significant bit (MSB) is a 1, then byte value continues to the next byte. The continuation bit must be dropped in order to calculate the value. Bytes are in little-endian order.

9a ef 02 ==> 10011010 11101111 00000010
drop continuation bits and reverse order: 0000010 1101111 0011010
group bits and calculate: 10110111 10011010 = 0xB79A = 47,002

There are two different ways to encode negative integers in Protobuf (2’s complement or zigzag encoding), depending on the data type used. See Protobuf documentation for further explanation, or below for an example.

DDATA - Device Data Message

Device Data message (DDATA) reports a set of data values from the RediGate. On initial connection, all values will be reported, and after that typically only changes. The DDATA message may have any number of repeated “metrics” elements with the reported data values. RediGate uses the RTDB register address for the “alias,” and either the RTDB register address or a configured Tag name for the “name” of the data item.

Topic: spBv1.0/Group/DDATA/NodeName/DeviceName

Example Sparkplug-B message:

08 b5 c7 fb a3 8e 31 12 08 10 9d ef 02 20 03 50 05 12 0c 10 9e ef 02 20 03 50 fa ff ff ff 0f 18 2b

Interpretation of Protobuf payload:

{“timestamp”: 1687460701109,
”metrics”:[
  {“alias”:47005,”datatype”:3,”int_value”:5}, // datatype=Int32
  {“alias”:47006,”datatype”:3,”int_value”:-6} // datatype=Int32
  ],
”seq”:43}

Interpretation of the negative integer value in Protobuf encoding:

fa ff ff ff 0f ==> 11111010 11111111 11111111 11111111 00001111
drop continuation bits and reverse order: 0001111 1111111 1111111 1111111 1111010
group bits and calculate: 11111111 11111111 11111111 11111010 = 0xFFFA
take 2’s complement (invert bits and add 1, or subtract from 0x10000): -6

DBIRTH - Device Birth Message

Device Birth (DBIRTH) reports when a device has gone to online status. All tags in the device are reported with both name and numeric alias and their current value. Note that in this example, there is no Tag object configured in the RediGate, so the string “name” matches the numeric “alias.” If Tags are defined, the tag would be used for the “name.”

Topic: spBv1.0/Group/DBIRTH/NodeName/DeviceName

Example Sparkplug-B message:

08 dc dc 84 84 8e 31 12 0e 0a 05 31 30 30 30 31 10 91 4e 20 0b 70 01 12 0f 0a 05 33 30 30 30 31 10 b1 ea 01 20 06 50 13 12 13 0a 05 34 31 30 30 31 10 a9 c0 02 20 03 50 9c ff ff ff 0f 12 12 0a 05 34 32 30 30 31 10 91 c8 02 20 09 65 d0 0f 49 40 12 14 0a 05 34 35 30 30 31 10 c9 df 02 20 0c 7a 05 48 65 6c 6c 6f 18 01

Interpretation of Protobuf payload:

{“timestamp”: 1687393742428,
”metrics”:[
{“name”:”10001”,”alias”:10001,”datatype”:11,”boolean_value”:1}, // datatype=Boolean
{“name”:”30001”,”alias”:30001,”datatype”:6,”int_value”:19}, // datatype=UInt16
{“name”:”41001”,”alias”:41001,”datatype”:3,”int_value”:-100}, // datatype=Int32
{“name”:”42001”,”alias”:42001,”datatype”:9,”float_value”:3.14159}, // datatype=Float
{“name”:”45001”,”alias”:45001,”datatype”:12,”string_value”:”Hello”} // datatype=String
  ],
”seq”:1}

NDEATH - Node Death Message

Node Death (NEATH) is reported from the broker when a node device (RediGate) has gone offline due to a clean disconnection or loss of communication (after keep-alive timeout).

Topic: spBv1.0/Group/NDEATH/NodeName

Example Sparkplug-B message:

08 9c c1 84 84 8e 31 12 14 0a 05 62 64 53 65 71 10 63 18 9d c1 84 84 8e 31 20 08 58 00 18 00

Interpretation of Protobuf payload:

{“timestamp”: 1687393738908
”metrics”:[
{“name”:”bdseq”,”alias”:99,”timestamp”:1687393738909,
”datatype”:8,”long_value”:0} // datatype=UInt64
  ],
”seq”:182}

DDEATH - Device Death Message

Device Death (DEATH) reports when a device has gone to offline status.

Topic: spBv1.0/Group/DDEATH/NodeName/DeviceName

Example Sparkplug-B message:

08 ae d1 c9 a6 8e 31 18 b6 01

Interpretation of Protobuf payload:

{“timestamp”: 1687466174638,”seq”:182}