MQTT Pub each JSON value

Hi,
I'd like to publish several JSON object values from my weather station via MQTT. I am using a http request node to get the JSON object. First I started off using a change node to extract only one value but now I've decided it could be useful in the future to publish all of them. Is there a better approach than using a function node to loop through the array of objects, outputting to a mqtt output node for each value?

Here's my array of objects, just the 2 so far.

[{"macAddress":"XX:XX:XX:XX:XX:XX","lastData":{"dateutc":1563819660000,"winddir":206,"windspeedmph":0.45,"windgustmph":1.12,"maxdailygust":9.17,"tempf":81.3,"battout":1,"humidity":43,"hourlyrainin":0,"eventrainin":0,"dailyrainin":0,"weeklyrainin":0,"monthlyrainin":0.12,"yearlyrainin":0.12,"totalrainin":0.12,"tempinf":73,"battin":1,"humidityin":52,"baromrelin":29.37,"baromabsin":29.31,"uv":7,"solarradiation":750.41,"temp1f":69.26,"humidity1":58,"batt1":1,"feelsLike":81.2,"dewPoint":56.64,"lastRain":"2019-07-17T20:16:00.000Z","tz":"America/Chicago","date":"2019-07-22T18:21:00.000Z"},"info":{"name":"Name1","location":""}},{"macAddress":"XX:XX:XX:XX:XX:XX","lastData":{"dateutc":1563819660000,"winddir":266,"windspeedmph":3.36,"windgustmph":4.47,"maxdailygust":10.29,"tempf":77.5,"battout":1,"humidity":47,"hourlyrainin":0,"eventrainin":0,"dailyrainin":0,"weeklyrainin":0,"monthlyrainin":0.02,"yearlyrainin":0.02,"totalrainin":0.02,"uv":7,"solarradiation":789.92,"feelsLike":77.16,"dewPoint":55.66,"lastRain":"2019-07-19T01:07:00.000Z","tz":"America/Chicago","date":"2019-07-22T18:21:00.000Z"},"info":{"location":"","name":"Name2"}}]

The objects are different in content.

What do you plan to store in mqtt?

  • each value, each with their own topic ?
  • Or 1 topic per object ? (as you can store an object in mqtt).

I was thinking of storing each value in their own topic, something like:
weather/[.info.name]/winddir = [.lastData.winddir]
and do that for each item in lastData.

Not sure why you would want to do this but you will have to loop (jsonata could probably work as well, but I wouldn't know how)

Separate topics and the elements with their values.

[{"id":"3fea323a.4b628e","type":"inject","z":"6cc72cbf.91db94","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":235,"y":300,"wires":[["76cbac0f.c31d54"]]},{"id":"76cbac0f.c31d54","type":"function","z":"6cc72cbf.91db94","name":"","func":"obj = [{\"macAddress\":\"XX:XX:XX:XX:XX:XX\",\"lastData\":{\"dateutc\":1563819660000,\"winddir\":206,\"windspeedmph\":0.45,\"windgustmph\":1.12,\"maxdailygust\":9.17,\"tempf\":81.3,\"battout\":1,\"humidity\":43,\"hourlyrainin\":0,\"eventrainin\":0,\"dailyrainin\":0,\"weeklyrainin\":0,\"monthlyrainin\":0.12,\"yearlyrainin\":0.12,\"totalrainin\":0.12,\"tempinf\":73,\"battin\":1,\"humidityin\":52,\"baromrelin\":29.37,\"baromabsin\":29.31,\"uv\":7,\"solarradiation\":750.41,\"temp1f\":69.26,\"humidity1\":58,\"batt1\":1,\"feelsLike\":81.2,\"dewPoint\":56.64,\"lastRain\":\"2019-07-17T20:16:00.000Z\",\"tz\":\"America/Chicago\",\"date\":\"2019-07-22T18:21:00.000Z\"},\"info\":{\"name\":\"Name1\",\"location\":\"\"}},{\"macAddress\":\"XX:XX:XX:XX:XX:XX\",\"lastData\":{\"dateutc\":1563819660000,\"winddir\":266,\"windspeedmph\":3.36,\"windgustmph\":4.47,\"maxdailygust\":10.29,\"tempf\":77.5,\"battout\":1,\"humidity\":47,\"hourlyrainin\":0,\"eventrainin\":0,\"dailyrainin\":0,\"weeklyrainin\":0,\"monthlyrainin\":0.02,\"yearlyrainin\":0.02,\"totalrainin\":0.02,\"uv\":7,\"solarradiation\":789.92,\"feelsLike\":77.16,\"dewPoint\":55.66,\"lastRain\":\"2019-07-19T01:07:00.000Z\",\"tz\":\"America/Chicago\",\"date\":\"2019-07-22T18:21:00.000Z\"},\"info\":{\"location\":\"\",\"name\":\"Name2\"}}]\n\nfor (let item in obj){\n    \n    for (let key of Object.keys(obj[item].lastData)){\n      \n        t = 'weather/'+obj[item].info.name+\"/\"+key\n        v = obj[item].lastData[key]\n        \n        node.send({topic:t,payload:v})  \n    }\n    \n}\n","outputs":1,"noerr":0,"x":400,"y":300,"wires":[["afadda2a.e14e28"]]},{"id":"afadda2a.e14e28","type":"debug","z":"6cc72cbf.91db94","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":550,"y":300,"wires":[]}]
1 Like

That sounds like my cue... ;*)

If you just want to split every field/value in your payload objects into their own msg objects, this JSONata expression can do it:

payload.(
    $data := $;
    $keys(lastData).{
        "topic": "weather/" & $data.info.name & "/" & $,
        "payload": $lookup($data.lastData, $)
    }
)

Here is how it looks when I paste your data into the expression tester of the change node:

The output will be an array of msg objects -- wire that to a split node, and each element of the array will be sent as a separate msg -- wire that to your mqtt out node, and every reading ends up being published as a separate key/value pair.

2 Likes