1

up front, i am somewhat new to MQTT and especially new to Google's Protobuf. with that in mind, i'm working with a leftover project from the previous Python "developer" and am finding myself a little lost because he didn't document any of his code.

to get up an running, as it were, i wrote a quick script following the tute on the Paho MQTT site, which works only in that i am GETTING messages. but i am unable to decode them. i ran a loop through the many ecoding types and found that latin-1 gave me somewhat human-readable results. so this is my first roadblock. it is supposed to be utf-8 but that generates a can't decode byte 0xf3: invalid continuation type error.

here's the complete code:

import paho.mqtt.client as mqtt
import json

def decodeMQTT(msg):
    #
    #       it's coming in as SparkplugB v1.0
    #       
    print('x!x!x-- decoding payload... --x!x!x')

def on_connect(client, userdata, flags, rc):
    print('connected with result code: ' + str(rc))

    client.subscribe("spBv1.0/spanky/+/TCG4 Test1/#")

def on_message(client, userdata, msg):
    tokens = msg.topic.split('/')
    print('--- tokens ---> ',tokens)

    #   OUTPUTS: --- tokens --->  ['spBv1.0', 'spanky', 'NCMD', 'TCG4 Test1']

    print('-+-+-+- raw payload: ', msg.payload)
    # OUTPUTS: -+-+-+- raw payload: b'\x08\xa8\xbe\xbc\xad\x9f1\x12\x12\x10\x03\x18\xa8\xbe\xbc\xad\x9f1 
    #                                 \t8\x00e\x00\x00\xa0A\x18\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01'

    try:
        #
        #       this should be using UTF-8 to decode the message string... but it isn't
        #           which leads me to believe it has something to do with protobuf (dammit)
        #           if UTF-8 is used, i get this error:
        #               »»  can't decode byte 0xf3: invalid continuation type  ««
        #           which i can't seem to find any explanation for...  :P
        #
        decoded = msg.payload.decode('latin-1')
        print('♥♥♥-» decoded payload: ', str(decoded), '«-♥♥♥')
        #
        #        this prints: ♥♥♥-» decoded payload: ÅÒÖ1↕&
        #                     ‼/tags/inputs/input1►♥↑ÇÒÖ1 ♀z♦2.01↑^ «-♥♥♥
        #        NOTE the line break is part of the decoded output
        #
    except Exception as ex:
        print('↓↓↓↓↓ decoding failed: ', str(ex), '↓↓↓↓↓')

def main():
    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    client.username_pw_set('fnork', 'blarp')

    client.connect("nunyabiznitz", 16500, 10)

    client.loop_forever()

if __name__ == '__main__':
    main()

the messages are coming from an Ignition server in the SparkplugB v1.0 format. which i presumed Paho MQTT would be able to decode...

the original code i took over used Protobuf, but as you can see here, i'm not. both as an attempt to simply understand the MQTT exchange and to evaluate if it actually brings anything to the table, since Paho MQTT should be handling all the necessary bits; primary of which is the encoding and decoding of message strings, no?

i DO understand that Protobuf ensures there's no structure issues or data-type issues (and there's a brick-ton of other stuff that lacks documentation), but if i'm only reading a handful of values, i don't know that there's value in an extra 600 lines of code...

anyway. as you can see, the return message from the Ignition MQTT module is NOT decoding properly and i want to know why. is there something i am missing here? if i'm missing information that could help clear up this question better, please let me know and i'll supply as best i am able.

EDIT: forgot a line of code that actually did the decoding. fixed.

EDIT2: okay. this morning i came in and this is the payload coming through now:

\x08\xd0\xca\x99\xf4\x9f1\x12&\n\x13/tags/inputs/input1\x10\x03\x18\x8e\xcd\x99\xf4\x9f1 \x0cz\x042.01\x18\xae\x01

as you can see, the parts i actually care about are in clear text. this makes me think that, yes, i actually DO need the Protobuf after all. it looks like the hex parts are the shorthand for the header and flags, while the payload has some other kind of decorators going on... which will require Protobuf to decode for full use. dang it. i was hoping for a sleeker build. that stuff is bloated AF.

WhiteRau
  • 818
  • 14
  • 32
  • 2
    "Paho MQTT would be able to decode" not really. Paho MQTT will handle the MQTT side of things (i.e. getting the message to your app). MQTT is payload agnostic (it's just data); the paho library will deliver whatever payload the publisher transmitted. Sparkplug defines the payload format (section 6.4.1 in [the spec](https://sparkplug.eclipse.org/specification/version/3.0/documents/sparkplug-specification-3.0.0.pdf); encoding/decoding this is not something the Paho MQTT client handles. – Brits Aug 15 '23 at 21:33
  • The `msg.payload` value that you include appears to **not** be a valid protobuf message. You should be able to paste the value of `msg.payload.hex()` into [Protobuf Decoder](https://protobuf-decoder.netlify.app/) – DazWilkin Aug 15 '23 at 23:31
  • gotcha. thank you very much guys. i wasn't seeing that Protobuf was doing the encoding, i thought it was a standard MQTT thing. thanks for pointing me in the right direction. – WhiteRau Aug 23 '23 at 13:28

0 Answers0