MQTT - not getting it - again. message structure

It would seem my thinking I understand MQTT and messages is wrong.

Or I am missing something - again.

This is my test flow.

[{"id":"b87b117d64f2fc0a","type":"mqtt out","z":"65c9b63cb09879a0","name":"","topic":"test","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"8941f4c3.0f151","x":340,"y":1870,"wires":[]},{"id":"8cccb4dff9644103","type":"mqtt in","z":"65c9b63cb09879a0","name":"","topic":"test","qos":"2","datatype":"auto","broker":"8941f4c3.0f151","nl":false,"rap":true,"rh":0,"x":470,"y":1870,"wires":[["1401dff22e7b167b"]]},{"id":"1401dff22e7b167b","type":"json","z":"65c9b63cb09879a0","name":"","property":"payload","action":"","pretty":false,"x":590,"y":1870,"wires":[["639e04cb31c14b7d","2adf3a80409bc323"]]},{"id":"639e04cb31c14b7d","type":"debug","z":"65c9b63cb09879a0","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":730,"y":1870,"wires":[]},{"id":"523ce62d14a37f87","type":"inject","z":"65c9b63cb09879a0","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"payload\":\"text\"}","payloadType":"json","x":190,"y":1870,"wires":[["b87b117d64f2fc0a"]]},{"id":"2adf3a80409bc323","type":"switch","z":"65c9b63cb09879a0","name":"","property":"payload.payload","propertyType":"msg","rules":[{"t":"eq","v":"text","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":590,"y":1940,"wires":[["bbc460a221fd8fd6"]]},{"id":"bbc460a221fd8fd6","type":"debug","z":"65c9b63cb09879a0","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":740,"y":1940,"wires":[]},{"id":"8941f4c3.0f151","type":"mqtt-broker","name":"Local","broker":"","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]

Local MQTT broker.

I create a JSON message - I hope - in the inject node.

Send that into the MQTT node then it is received.

I send it through a JSON node and look at the output in a debug node.

I need the JSON node to de-construct the message from the MQTT wrapping.

Ideally I should get text in the debug node.

Then the switch node will pass the message is the msg.payload (don't get ahead of me) is text.

Or so it should.

But it only works if I make the switch node compare the msg.payload.payload.
Shouldn't the JSON node strip all that stuff off?

I know I've been through this before and I remember way back in the early days NicOleary helped me when I was going around in circles with the JSON (or more so: message structure) problem.

But for reasons unknown: I can't seem to get it working to simply send a message through.

Andrew, lets walk thru what you have done. First the inject node

You need to remember that msg is an object and it initially contains only a single name/value pair. You can see this if you have an inject node and delete the 'payload' and 'topic' options and connect it to a debug node set to display the complete msg object. This is what you will see in the debug panel:

9/25/2021, 2:13:47 AMnode: 68761c9e6b27fb67
msg : Object
  _msgid: "89ad90bf1540ce68"

You can add a 'name/value' pair named 'payload' to the msg object and the value can take many forms. It can be a string, a number or an other object.

This is what it would look like containing a string:

9/25/2021, 2:20:34 AMnode: 68761c9e6b27fb67
msg : Object
  _msgid: "61ef2e5133c3a9d1"
  payload: "Hi Andrew"

so this msg object has two name/value pairs and the second name/value pair has a name 'payload' and a value 'Hi Andrew'

Now let's look at the inject you used
Screen Shot 2021-09-25 at 2.09.47 AM

In this case, you have added two name/value pairs to the msg object. The first name/value pair has a name called payload and a value that is an object. That object contains a name/value pair and you have chosen to use payload as the name and the string text as the value. So your complete omsg object looks like this:

msg : Object
_msgid: "f4d7a31e38eff874"
  payload: object
     payload: "text"
  topic: ""

So to get to the value 'text' you need to use msg (to identify the object), .payload (to identify the name/value pair that has a 'name' of 'payload') then within the 'payload' the value is an object, so you need to use the 'name' to access the value and you used the name 'payload' (ohhh confusion alert!!) so you need to use .payload to finally complete the access to the value 'text'.

So the full path is msg.payload.payload

You probably should have used a 'name' of 'mydata' to keep from getting confused and then the path would be msg.payload.mydata.

_ _

Secondly the mqtt-out node. If the data (msg.payload) being sent is an object, it is converted to a string before being sent. So in your case msg.payload is converted to a string and sent.

The mqtt-in receives the string and you send it thru a json node to convert it back to an object (remember that the mqtt-in node now has an option to convert it to an object so you don't need the following json node.

[If you set the mqtt-in node to convert the string to an object then pass it thru a json node, it will be converted back to a string]

So you send the msg to a switch node and you test msg.payload.payload to see if the value is 'text' and it is, so you pass the msg on to a debug node.

In the debug node you display the contents of msg.payload and the contents is an object so that is what is displayed. IF you want to display the value of the name/value pair that is in msg.payload then you have to specify the 'name' so your debug would have to be this:
Screen Shot 2021-09-25 at 2.50.53 AM
Remember, the switch node does not change the contents of the msg object, it is just testing parts of it.

If you wanted the 'value' of the name/value pair msg.payload.payload to end up in msg.payload you could use a change node to set msg.payload to msg.payload.payload

Now you might understand why I suggested you set the original msg.payload to a name/value pair where the name was 'mydata'.


You are sending to mqtt a payload containing {payload: "text"} so that is exactly what you get out of the JSON node. Where is the confusion?

You don't need the JSON node though. In the mqtt in node tell it to parse the JSON for you and that will achieve the same thing.

1 Like

I seem to be making things difficult for myself.

I think I am making my own life more difficult than it needs to be, but.....

I have been bitten by a big mistake I just realised and I'm not sure you actually meant to show me it.

The fact is that the inject is sending what ever I put in it already .... embedded (wrong word) as msg.payload, and not msg.{} so I am shooting myself in the foot.

The problem is compounded because in the real application of it I have made problems for myself which are only now coming to light.

If I had a different structured message - the way I meant it to be in the example the message would actually be - or should have been -
msg.{"payload": "text"," something_else": "Foo"}

So I've moved on from that stupid mistake.

Now, the other problem.

Back to the basics though:

msg.payload = {"payload":"Hello"}

Which is .......

Because it is the inject node it is already in paload... I just said that. Yikes!
Ok, that's the ah-ha! moment.

So if I simply send "Hello" as msg.payload into the MQTT node.... at the other end, I don't need the JSON node.

To make my life a bit easier I think I will pick/make a whole new topic in MQTT and send the message and parse it all alone.

I was trying to piggyback it on an existing channel that expects JSON messages and when my effort was received it was causing problems (in the REAL version) and so I went down the this rabbit hole, and got lost/confused.

Sorry to both of you: @zenofmud and @Colin.
It was a Brain failure in a regrettably bad way.
I'll leave it here.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.