Set change-node Payloadpath to msg.payload.+global

Hello,

i would like to do sth simple i guess, but i cannot figure out how to do it exactly.

I would like to let my msg.payload be sth like "msg.payload.ZbReceived.0xCE25" with a change node. Of course there is no issue with that. But i would like to be able to change the last part "0xCE25" with my stored Global Variable.

I have many things coming from mqtt with different names "0x...." and sometimes i need to change them and it would be easier to just change the Globals instead of change every change node again.

i hope it is understandable what my issue is.

Thanks alot for your help.

Best regards Dominik

Not so much :wink:
so .. you want to dynamically pass whatever is in Globals to msg.payload.ZbReceived ?
does Global only have ZbReceived values stored in it .. or does it store other values also ?
what is the structure of Globals ? send us a screenshot .. a screenshot is a thousand words :wink:

[EDIT]
if you want all Global entries to be set to msg.payload.ZbReceived then using a jsonata expression in your Change node can do that.

image

I think this is one of the cases where a simple function node instead of a change node will make your life much easier. In JavaScript you can use the square brackets to use the value of another var as a key:

const key = flow.get("test");
msg.payload = msg[key];
return msg;

For example would set msg.payload to msg + whatever the the value of flow.test was.

Hello thanks for reply. I get an MQTT Message with different Topics for different sensors/switches ( ZigbeeGateway). These Things al have a different (Hex?) Number ind this devices for Example 0x631D.
Sometimes i need to repair the devices and the Hexnumbers are changing then. So i need to go everytime in every node where this Hexnumber is used. I would like to have Globals for all these Hexnumbers. Then i woud not need to change every Changenode and just need to change the globals then. For Example Global BathroomMotion to 0x12345.

Thanks alot

That’s exactly what the function I posted above does. just adapt it to you global instead of the test flow and add your path:

const key = global.get("BathroomMotion");
msg.payload = msg.payload.ZbReceived[key];
return msg;

Than use a function node with those three lines instead of each of the change nodes.

1 Like

Uhuuu. Thanks alot. It works. Would have never found such solution on my own.

Have a great day :smiley:

And for info this is the same thing in JSONata and change node.

[{"id":"d58991db.43c948","type":"inject","z":"8d22ae29.7df6d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{}","payloadType":"str","x":120,"y":2460,"wires":[["b0b83020.838418"]]},{"id":"b0b83020.838418","type":"change","z":"8d22ae29.7df6d","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$merge(\t   [\t       $type(payload) = \"object\" ? payload : {},\t       {\t        \"ZbReceived\":{$globalContext(\"test\"):\"a value\"}\t       }\t   ]\t)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":2460,"wires":[["8f888c94.94e39"]]},{"id":"8f888c94.94e39","type":"debug","z":"8d22ae29.7df6d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":560,"y":2460,"wires":[]}]
1 Like

Awesome,

thanks alot

As much as i like jsonata for a lot of things this is one where i find the syntax just a little bit too convoluted for my liking and prefer the straight forward function node but nice to know the jsonata way too :+1:

1 Like

My example was more convoluted as i assumed msg.payload all ready may have properties, so add some checks. It is simpler if you want to over write msg.payload.

	   {"ZbReceived":{$globalContext("test"):"a value"}}

I think your not doing what was requested. Its not about setting msg.payload.ZBreceived.something to a specific value. But instead its about setting msg.payload to the value of msg.payload.ZBreceived.something where the something key is dynamic so we need to get it from the value of global.BathroomMotion and build the object reference dynamically as the key where what we want msg.payload to be can change.

You are mistaken it is setting the key dynamically

[{"id":"49e56cf3.3c833c","type":"debug","z":"1b5e73a9.1939fc","name":"what we want","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1820,"y":960,"wires":[]},{"id":"b2136b39.e8ad2","type":"inject","z":"1b5e73a9.1939fc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1140,"y":900,"wires":[["83be35b2.6a4a98"]]},{"id":"83be35b2.6a4a98","type":"change","z":"1b5e73a9.1939fc","name":"","rules":[{"t":"set","p":"BathroomMotion","pt":"global","to":"test","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1370,"y":900,"wires":[[]]},{"id":"82c00fc0.32f318","type":"function","z":"1b5e73a9.1939fc","name":"","func":"const key = global.get(\"BathroomMotion\");\nmsg.payload = msg.payload.ZbReceived[key];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":1640,"y":960,"wires":[["49e56cf3.3c833c"]]},{"id":"b105c10f.00e18","type":"debug","z":"1b5e73a9.1939fc","name":"jsonata output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1860,"y":1040,"wires":[]},{"id":"b0b83020.838418","type":"change","z":"1b5e73a9.1939fc","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$merge(\t   [\t       $type(payload) = \"object\" ? payload : {},\t       {\t        \"ZbReceived\":{$globalContext(\"BathroomMotion\"):\"a value\"}\t       }\t   ]\t)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1660,"y":1040,"wires":[["b105c10f.00e18"]]},{"id":"b75d775.f73cf08","type":"change","z":"1b5e73a9.1939fc","name":"","rules":[{"t":"delete","p":"payload","pt":"msg"},{"t":"set","p":"payload.ZbReceived.test","pt":"msg","to":"this is what we want as the msg.payload","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1320,"y":960,"wires":[["82c00fc0.32f318","b0b83020.838418"]]},{"id":"64b63e60.f389b8","type":"inject","z":"1b5e73a9.1939fc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1140,"y":960,"wires":[["b75d775.f73cf08"]]}]

This is what is wanted i think. And your jsonata @E1cid is not doing it as you see. He only wants to set the key and dont set any values. The purpose is to set msg.payload to the value of that dynamically generated key. Maybe you know a jsonata which has exactly the same end result / function as the function node?

@JGKK

Exactly like this.

I have now a great Function Node where i can change all my HexCodes in One Window. And the other Function Nodes taking the needed Globalvalues from it.

Only small issue i have now is that i get everytime a message in my Debugwindow from the function nodes when no explicit data for the sensor is sended and instead for another.

TypeError: Cannot read property '0x1E7F' of undefined

Can i add sth in my function node, that its only "executing" when the payload ist not empty or undefined?

//Just want to add. Everything works like exprected. There are only this errormessages.

adapt the function to:

const key = global.get("BathroomMotion");
if (msg.payload.ZbReceived.hasOwnProperty(key)) {
    msg.payload = msg.payload.ZbReceived[key];
    return msg;
} else {
    return null;
}

It will only send a message if the key matches.

1 Like

I see your Mqtt node is subscribed too all topics #

Copy/paste a msg coming from your Mqtt .. maybe there's a better way to optimize your flow because i dont understand what the point of setting globals and then reading them since when you make a change on the device you still need to go in your "setAllZigbeeDeviceHexCode" function and hard code the new hex :wink:

Thank you

I tried the following way but i think yours is the right way.

Just for information:
const key = global.get("ZBB_SZMotionMain");
msg.payload = msg.payload.ZbReceived[key];
if(msg.payload !== null && msg.payload !== '')
{
return msg;
}

1 Like

The js hasOwnProperty() function is especially made for this purpose to check if a certain property exists.
You an read more about it here:

i was thinking of a function with many outputs doing the switching ?
no need for globals

Multiple Outputs

thanks for the idea. would be possible too i guess.