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”.

image

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

image

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:

image

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

sparkplug_b.proto.zip (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":"chariot.server.com","port":"8883","tls":"","clientid":"","usetls":true,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]

2 Likes

Hi Terry,

Have you used the encode part with protobuf to encode an outbound sparkplug_b message? I am using the encode function with the protobuf and the message I am getting from debug is: No protobuf type supplied!

I have a function that I built, and I am researching, but am not getting too far with encoding properly.
Not asking to fix, just any tips if you have.

My flow is enclosed.

[{"id":"8b8f8d4.5166a7","type":"inject","z":"f10784d0.015068","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":360,"y":720,"wires":[["af27afd3.3c2d2"]]},{"id":"29f44c8e.711f34","type":"mqtt out","z":"f10784d0.015068","name":"","topic":"","qos":"","retain":"","broker":"1008ff7a.33cd81","x":990,"y":720,"wires":[]},{"id":"af27afd3.3c2d2","type":"function","z":"f10784d0.015068","name":"","func":"var group_id = \"NetDNA\";       // Put Sparkplug group ID here\n\nvar edge_node_id = \"352656100597502\"; // Put Sparkplug edge node ID here\n\nmsg.qos = 1;\n\nmsg.retain = false;\n\nmsg.topic = \"spBv1.0/\" + group_id + \"/NCMD/\" + edge_node_id;\n\n       \n\nvar dout1_metric = {\n\nname: \"Dev1/DOUT1\",\n\ntimestamp: Date.now(),\n\ndatatype: 11,\n\nbooleanValue: true\n\n};\n\n \n\nvar payload = {\n\ntimestamp: Date.now(),\n\nseq: -1,\n\nmetrics: [dout1_metric]\n\n};\n\n \n\nmsg.payload = payload;\n\nreturn msg;","outputs":1,"noerr":0,"x":590,"y":720,"wires":[["5ac3043f.78453c","146daae5.d89fb5"]]},{"id":"5ac3043f.78453c","type":"debug","z":"f10784d0.015068","name":"send","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":890,"y":780,"wires":[]},{"id":"146daae5.d89fb5","type":"encode","z":"f10784d0.015068","name":"encode","protofile":"2693e25a.9357de","protoType":"","x":800,"y":720,"wires":[["29f44c8e.711f34","5ac3043f.78453c"]]},{"id":"1008ff7a.33cd81","type":"mqtt-broker","z":"","name":"Chariot","broker":"postman.cloudmqtt.com","port":"13650","tls":"","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"2693e25a.9357de","type":"protobuf-file","z":"","protopath":"/home/dev/unsecured/sparkplug_b.proto"}]

My mistake, I looked at the original code and realized i didn’t put Payload in the type field in protobuf node.

Thanks,
Dan

1 Like

2 posts were merged into an existing topic: Accessing where Palletes are stored on a AR1

Correct me, but the Ignition edge that comes with EPIC does not MQTT Engine out of the box, so we are unable to subscribe to MQTT using Ignition Edge?

I read sparkplug payload is encrypted for security. But if anyone can decode it directly, what is the use of encryption? Sorry if I miss anything.

It can subscribe to any topics that it is publishing to.

Only people with your SSL certificate can decode it.
That’s the whole point of HTTPS.

1 Like

Greetings,


Here are the results from 2 different EPIC. Can I know why is the 1st EPIC return “Metrics[0].Alias” data but the 2nd EPIC return “Metrics[0].Name” data? Is there any configuration needs to be done in Ignition/PAC Control?

Are both EPIC controllers running the same firmware version/Node-RED Version?

1 Like

As well as the firmware version, are you using the Sparkplug client built into groov Manage?

In firmware version 3.4.0 we have added the ability to enable / disable tag aliases This is enabled by default. You can find that under Data ServiceMQTT Sparkplug Configuration here:

Both EPICs running in different firmware
The 1st EPIC with metrics[0].alias data is a new device. Firmware Version 3.2.1-b.104.
The 2nd EPIC that showed metrics[0].name is the Demo Unit my employer gets from Opto22. Firmware version 1.2.1-b52

I strongly recommend updating the firmware, ideally on both devices, but especially on the 1.2.1 EPIC. That coming up on four years old at this point.

1 Like

Both EPIC devices’ versions didn’t have this kind of Tag alias setting. I wonder why both devices with the same MQTT configuration but have different payload results.
I am using HiveMQ MQTT Sparkplug broker:

Demo Center Epic MQTT configuration:

New Epic MQTT configuration:

The only difference is Demo Center Epic got a Chariot Client SSL certificate.

The firmware version @torchard took the screenshot from is the latest, 3.4.0. You can log into manage.groov.com and download it for free. Be sure and backup both EPIC’s before you do the firmware.
Be sure and be careful how you update the older one. We have made MANY changes and improvements to the backup/restore process over the years.
Take a look at our guide here: Opto22 - 2327 Technical Note: groov EPIC Update Checklist

They are different because, as @torchard said, you are running not only different versions, but in one case, 4 year old firmware. We have made many improvements and bug fixes to the MQTT software over the years.

Its a bit like saying you have a car of brand X one is about 1 year old and the other is 4 years old.
The question you are asking is why are the car stereos different, they are the same car…
Unlike the car, you can upgrade both EPICs firmware and they both will work the same.

2 Likes

After I updated the firmware, it solved the alias and name problem. Besides, new firmware added a lot of features and functions. I had join the partner meeting yesterday and feel really amazing with the latest firmware.

But I haven’t update the 1.2.1 EPIC, the reason is that the program in this EPIC device is original from OPTO22 including:

  • PAC control strategy. (Company doesn’t have a copy of the strategy.)
  • Node-Red
  • Groov View
  • MQTT Setting (Company doesn’t have a Chariot MQTT Broker.)
  • SSL Certificate (Company doesn’t have a copy of the SSL Certificate.)

So to prevent I messed up :sweat_smile: I have to double confirm my backup step at here:

  1. Backup Strategy from PAC Terminal
  2. Backup Groov Manage with SSL Certificate option enables
  3. Backup Groov View
  4. Backup Node-Red
  5. Backup Ignition-edge (Optional)

Good to hear!
The latest firmware really does add a lot of great features as you mention and glad you made the meeting last night (our time).

I wonder if the company stored a copy of the strategy on the EPIC? If they did, then you can upload it via PAC Terminal. If not, then you are really in a jam.

Your backup sounds pretty good.
Back up each part and the whole system. If you are using Ignition don’t forget to remove the license before the firmware update or else you will end up in 7 day emergency mode (which Inductive can reset for you).

Luckily the strategy was archived inside the EPIC memory storage, I was able to upload it from the PAC terminal. I will start the version update today and hopefully, everything goes right. Thank you.