Variable in JSON path

Hi! Not quite sure how to call this, hopefully this question hasn't been answered many times before.

I have MyStrom light bulbs. When asked for their current state they return payload.(mac address).(various variables) as in the picture above. I'm trying to generalize some functionalities for these bulbs, however, I am unsure how to deal with the mac address in a flexible way. For example I might like to copy some of the information in the variables to outside the payload for later usage, for which I might for example like to reference msg.payload.(mac address).on, something like this:


(I would use msg.restore to eventually make a call to the bulb to return it to its initial state, so I might for example blink it a few times if something happens and then return it to normal)

So if I would like to use this for multiple MyStrom bulbs and don't want to duplicate my code, using a subflow instead, I'd need to flexibly reference this mac address they give back as the name of the object under payload. Is this at all possible, or is there some other way to accomplish my goal?

Thanks!

If I am reading this right, this should get you close...

function code...

var props = Object.entries(msg.payload);

for (let index = 0; index < props.length; index++) {
    const mac = props[index][0];
    const payload = props[index][1];
    payload.mac = mac;
    node.send({
        topic: mac,
        payload: payload
    })
}

demo flow...

[{"id":"fab4ff63.29219","type":"inject","z":"83a23089.dc697","name":"6001942C4720","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"6001942C4720\":{\"type\":\"rgblamp\",\"battery\":false,\"reachable\":true}}","payloadType":"json","x":860,"y":100,"wires":[["ec101660.53f988"]]},{"id":"3fe3101c.b0595","type":"inject","z":"83a23089.dc697","name":"6007942D5444","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"6007942D5444\":{\"type\":\"switch\",\"battery\":true,\"reachable\":true}}","payloadType":"json","x":860,"y":160,"wires":[["ec101660.53f988"]]},{"id":"ec101660.53f988","type":"function","z":"83a23089.dc697","name":"","func":"var props = Object.entries(msg.payload);\n\nfor (let index = 0; index < props.length; index++) {\n    const mac = props[index][0];\n    const payload = props[index][1];\n    payload.mac = mac;\n    node.send({\n        topic: mac,\n        payload: payload\n    })\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1070,"y":120,"wires":[["db4d50fa.ea774","6a268832.016038"]]},{"id":"db4d50fa.ea774","type":"debug","z":"83a23089.dc697","name":"","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"topic","targetType":"msg","statusVal":"payload","statusType":"auto","x":1260,"y":120,"wires":[]},{"id":"6a268832.016038","type":"debug","z":"83a23089.dc697","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1270,"y":180,"wires":[]}]

The way I would deal with this, I think, is, on receiving the data from the bulb, immediately restructure the payload so that the mac address is in msg.payload.macaddress and the other properties are moved up to msg.payload.type etc. That would give you the data in a much more easily manageable format. I would do all the node-red processing with the data in that format and then before sending it back to the bulb I would re-adjust the payload back to the format it expects.

@Steve-Mcl Thanks! That indeed seems like it should get me most of the way there.
@Colin Thanks! Combined with Steve's response I think that should be doable.

Object.entries is basically the hint I needed, together with props[index][0] to get to the mac address, I believe I can figure it out from here.

Just curious, is there a way to do what I was trying in my 2nd image?

Maybe, with JSONata in a change node (but I dont know / care to know) how :wink:

JS is easier (to me) and is faster (in terms of development and execution).

JS doesn't come that natural to me, I like graphically connecting up nodes. It's been long since I actually coded a lot, though I am not a complete stranger. Often I can think up the approach, but find myself searching pretty long for how to actually do it in JS.

Yes, there might be a graphical way of doing this (gimmie 10 mins) but if I know how to do it in 20 secs in JS, then thats the approach I take.

PS JSONata is not a graphical way either (its a language all of its own, and i think most would agree, a bit of a learning curve)

So your choices are... spend ages and MAYBE find a graphical way of doing something - or - learn a bit JS. the latter will get you further in the log run. (and its fun). Its just another tool for your tool box at the end of the day.

PS2: sometimes, the graphical solution ends up being so convoluted, it is hard to maintain or grasp (and the reverse is also sometimes true).

Possible in the change node but still would require code, as in a JSONata expression.


This may need changing as I do not know the payload objects length

{$keys(payload):{"on":payload.*.on}}

Yeah, not trying to argue your approach. JSONata also feels convoluted, at that point I would also likely go for a function instead.

Thanks @E1cid

1 Like

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