Decode Sparkplug Encoded MQTT Messages with Node-RED

If you want a Sparkplug-compliant client to read in data two of the best options out there are Ignition Edge and MQTT.fx, but sometimes I need something that lies between these two applications — this is where Node-RED comes in.

Using Node-RED it’s possible to read in and decode Sparkplug messages right in your flow, then you can easily move that data into any other Node-RED endpoint, whether it’s groov View, a database, or even cloud analytic software.

Using this method Node-RED does not become a Sparkplug-compliant device, it is just a data consumer subscribed to an MQTT broker, but sometimes that’s all you need.
Here is the flow:

The blue node in the middle is a decoding node from the node-red-contrib-protobuf package that you can easily install through the pallet manager.

This node also requires the path to a *.proto file, which you can get for Sparkplug directly form the Eclipse Tahu project GitHub. The specific file you need is sparkplug_b.proto, which you can download from GitHub directly or just wget the raw file if you have SSH access.
If you do save it, make sure it’s a *.proto file and not a *.txt file.

For convenience, if you’re using groov EPIC you can just download the file attached to end of this forum post and move it into the unsecured file area through the groov Manage System menu.

Once the file is on your device make note of the full path to the file and put that into the decode node’s Proto File field, and set the protobuf type to “Payload”.


With that done you just need to set up your broker and put in the topic for some Sparkplug message, for example:


If you don’t know what your message topic looks like, download MQTT.fx, set up your broker, connect, change the “payload decoded by” to use the Sparkplug decoder, and then you can use the “topic collector” in the subscription window to find the topic you want.

Here I’m getting the “test_int32” publicly-readable numeric variable from the strategy running on my EPIC, as well as some useful meta data, all automatically split up into JSON:


Import the flow text below to try it out for yourself, and as always, happy coding! (2.3 KB)

[{"id":"199c087.0db14f8","type":"decode","z":"65e0d8c3.e0ef98","name":"sparkplug_b","protofile":"48ca2c90.fda3c4","protoType":"Payload","x":370,"y":360,"wires":[["f06989ae.5e6c68"]]},{"id":"f06989ae.5e6c68","type":"debug","z":"65e0d8c3.e0ef98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":510,"y":360,"wires":[]},{"id":"ad848b2b.490b28","type":"mqtt in","z":"65e0d8c3.e0ef98","name":"groovEPIC_dev","topic":"spBv1.0/Opto22/+/groovEPIC_developer/#","qos":"2","broker":"fcec5047.03e36","x":200,"y":360,"wires":[["199c087.0db14f8"]]},{"id":"48ca2c90.fda3c4","type":"protobuf-file","z":"","protopath":"/home/dev/unsecured/sparkplug_b.proto"},{"id":"fcec5047.03e36","type":"mqtt-broker","z":"","name":"Chariot","broker":"","port":"8883","tls":"","clientid":"","usetls":true,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]

1 Like