Trying to react to a variable name contained in another variable (Solved)

Hello everyone. I’m trying to create a flow that activates a couple of switches depending on many states and variables, but I want to be able to easily duplicate this flow and change the switches and variables it interacts with, without needing to edit all the nodes every time I duplicate the flow.

For this, the idea is to create msg and flow variables at the start of the sequence, containing the names of the switches and variables that will be read later in the sequence.

image

I was able to do something similar but I only used these “dynamic” variables for setting the devices, and now I am trying to use this method to set variables too, but I’m being unsuccessful making the variables work.

The real sequence would start with only two switches:
image

But I created a test flow with four inputs to emulate the on/off for each switch:

[{"id":"056618f10d0fcd33","type":"inject","z":"fbb020a344ed4251","name":"laundryLight1 on","props":[{"p":"payload"},{"p":"topic","vt":"str"},{"p":"bypassVar","v":"laundryLightBypass","vt":"str"},{"p":"otherDevice","v":"laundryLight2","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"laundryLight1","payload":"on","payloadType":"str","x":140,"y":1900,"wires":[["59a9aabac40a8b9c"]]},{"id":"d0090a82389b1492","type":"debug","z":"fbb020a344ed4251","name":"debug 17","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":1840,"wires":[]},{"id":"bc15d828433c9813","type":"change","z":"fbb020a344ed4251","name":"set bypass true","rules":[{"t":"set","p":"{{bypassVar}}","pt":"flow","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":640,"y":1920,"wires":[["64471639d9b6d95a"]]},{"id":"59a9aabac40a8b9c","type":"switch","z":"fbb020a344ed4251","name":"if bypass is false","property":"{{bypassVar}}","propertyType":"flow","rules":[{"t":"false"}],"checkall":"true","repair":false,"outputs":1,"x":380,"y":1900,"wires":[["bc15d828433c9813","d0090a82389b1492"]]},{"id":"64471639d9b6d95a","type":"switch","z":"fbb020a344ed4251","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":430,"y":2000,"wires":[["dd2a8c7dd06953bd"],["afbae3d9cd97438b"]]},{"id":"dd2a8c7dd06953bd","type":"api-call-service","z":"fbb020a344ed4251","name":"","server":"8a86b0cc.b2bac","version":5,"debugenabled":false,"domain":"light","service":"turn_on","areaId":[],"deviceId":[],"entityId":["{{otherDevice}}"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":630,"y":1980,"wires":[["78eb5f7804f757ea"]]},{"id":"afbae3d9cd97438b","type":"api-call-service","z":"fbb020a344ed4251","name":"","server":"8a86b0cc.b2bac","version":5,"debugenabled":false,"domain":"light","service":"turn_off","areaId":[],"deviceId":[],"entityId":["{{otherDevice}}"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":630,"y":2040,"wires":[["78eb5f7804f757ea"]]},{"id":"78eb5f7804f757ea","type":"change","z":"fbb020a344ed4251","name":"set bypass false","rules":[{"t":"set","p":"{{bypassVar}}","pt":"flow","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":840,"y":2000,"wires":[[]]},{"id":"4e9165e561071d42","type":"inject","z":"fbb020a344ed4251","name":"laundryLight1 off","props":[{"p":"payload"},{"p":"topic","vt":"str"},{"p":"bypassVar","v":"laundryLightBypass","vt":"str"},{"p":"otherDevice","v":"laundryLight2","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"laundryLight1","payload":"off","payloadType":"str","x":140,"y":1940,"wires":[["59a9aabac40a8b9c"]]},{"id":"3ee93036540e07ce","type":"inject","z":"fbb020a344ed4251","name":"laundryLight2 on","props":[{"p":"payload"},{"p":"topic","vt":"str"},{"p":"bypassVar","v":"laundryLightBypass","vt":"str"},{"p":"otherDevice","v":"laundryLight1","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"laundryLight2","payload":"on","payloadType":"str","x":140,"y":1980,"wires":[["59a9aabac40a8b9c"]]},{"id":"593e2d27d3defad4","type":"inject","z":"fbb020a344ed4251","name":"laundryLight2 off","props":[{"p":"payload"},{"p":"topic","vt":"str"},{"p":"bypassVar","v":"laundryLightBypass","vt":"str"},{"p":"otherDevice","v":"laundryLight1","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"laundryLight2","payload":"off","payloadType":"str","x":140,"y":2020,"wires":[["59a9aabac40a8b9c"]]},{"id":"dd6899f71541c809","type":"inject","z":"fbb020a344ed4251","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":1800,"wires":[["0f64027646dd1f0a"]]},{"id":"0f64027646dd1f0a","type":"change","z":"fbb020a344ed4251","name":"","rules":[{"t":"set","p":"laundryLightBypass","pt":"flow","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":1800,"wires":[["d0090a82389b1492"]]},{"id":"a7724de6aaf8cff4","type":"comment","z":"fbb020a344ed4251","name":"Manually set bypass false","info":"","x":150,"y":1760,"wires":[]},{"id":"8a86b0cc.b2bac","type":"server","name":"Home Assistant","version":4,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30,"areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m"}]

So I’d be thankful if anyone could point me in any direction on how to achieve this :slight_smile:

Thanks,
Rodrigo

To set a flow variable use a change node like this

image

And catch it with a switch node like this

image

Just a note flow variables are only available on their respective page. If you need it available on other pages use the global option.

Thanks @Mikefila for your reply. I have tested it your way before and it works, but if I do it that way it would defeat the purpose of what I’m trying to achieve here, which is simplifying the sequence duplication process.

In the current simplified version of the sequence, there are three nodes that set or react to the bypass variable. If I achieve what I’m trying to do, the sequence will end up being more complex, but for the moment there are three nodes that interact with the bypass variable.

If I do it the way you are recommending, each time I duplicate this flow and set different lights/switches, apart of editing the first two state nodes to set the devices, I would need to edit each one of those three nodes that interact with the bypass variable (because the bypass variable would have a new name for every new device group).

In a previous topic, I learnt that I could use these brackets {{}} for a device name to be set by a variable’s content. So if I set msg.device1 = “light.laundry1” then I could tell a call service node to turn on {{device1}} and it would turn on light.laundry1. I want to achieve something similar with variable names (the variable would contain a variable name instead of a device name), so I don’t need to edit these three nodes mentioned above, and instead, every time I copy this sequence, I just need to edit the two first state nodes.

The idea is: These two first state nodes set the msg.bypassVar with the bypass variable name that the next nodes will interact with. In this case, I’m working with the light and switch of the laundry room, so the name of the bypass variable will be laundryLightBypass, msg.bypassVar = “laundryLightBypass”.
Then, the following switch and change nodes would need to get the variable laundryLightBypass from msg.bypassVar. To achieve this, I’m trying the same method mentioned before, putting the variable name between these brackets {{bypassVar}}. This is the part that is not working and I need help with.
image

I believe that if this brackets method works for devices, there should be a way to make this work for variables too.

Thanks!
Rodrigo

You can leave the switch node the way you had it, then at the start of the flow set msg.laundrytLightBypass to the flow variable

image

e. it would probably be better to use a less specific topic msg.bypass for instance then in each copied node you would need to change which flow variable is set.

image

Thanks! But I’m not being able to make it work… In the msg.bypass I get “true” or “false” instead of the name of the variable that the next switch and change nodes will interact with, I have three of these nodes that need to change the value of the flow.laundryLightBypasss to block other events that happen in the middle.

The purpose of this is that if switch 1 changes, it needs to change switch 2 to the same on/off state, and the same in the opposite way. So if I turn the switch 1 ond and then off quickly, it could start a loop of each switch turning each other on and off indefinitely. That is the reason why I need the bypass variable, so if I turn on switch 1 on, and then turn it off, it won’t start a loop hell, and the worst that could happen is that I have to wait for the loop to end before clicking the switch again.

Could you please show me a sequence that does this?

Thanks,
Rodrigo

Sorry I’m having trouble following your logic. It looks like you are trying to replicate a 3 way switch? You show as if there are distinct on and off commands for the switches. This is how I accomplish a 3way.

image

[{"id":"27e408618c0dc407","type":"trigger-state","z":"f80b6c338afd5483","name":"switches off","server":"6b1110b5.183a4","version":2,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityid":["light.lefty","light.righty"],"entityidfiltertype":"list","debugenabled":false,"constraints":[{"targetType":"this_entity","targetValue":"","propertyType":"current_state","propertyValue":"new_state.state","comparatorType":"is","comparatorValueDatatype":"str","comparatorValue":"off"}],"inputs":0,"outputs":2,"customoutputs":[],"outputinitially":false,"state_type":"str","enableInput":false,"x":590,"y":3260,"wires":[["96c527d60b3f40b5"],[]]},{"id":"5b51d4b9f8216470","type":"trigger-state","z":"f80b6c338afd5483","name":"switches on","server":"6b1110b5.183a4","version":2,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityid":["light.lefty","light.righty"],"entityidfiltertype":"list","debugenabled":false,"constraints":[{"targetType":"this_entity","targetValue":"","propertyType":"current_state","propertyValue":"new_state.state","comparatorType":"is","comparatorValueDatatype":"str","comparatorValue":"on"}],"inputs":0,"outputs":2,"customoutputs":[],"outputinitially":false,"state_type":"str","enableInput":false,"x":590,"y":3200,"wires":[["96c527d60b3f40b5"],[]]},{"id":"96c527d60b3f40b5","type":"api-call-service","z":"f80b6c338afd5483","name":"","server":"6b1110b5.183a4","version":5,"debugenabled":true,"domain":"light","service":"turn_{{payload}}","areaId":[],"deviceId":[],"entityId":["light.rgbcw"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":920,"y":3220,"wires":[[]]},{"id":"6b1110b5.183a4","type":"server","name":"Home Assistant","version":4,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m"}]

Scratch that mine are linked through their proprietary software. Now I understand the problem. Let me see if I can figure something out.

1 Like

You can use jsonata to pass the variable to the switch.

image

1 Like

Thanks a lot @Mikefila, this worked for the Switch node, which hasn’t worked before, so it’s a big step forward.
Now I need the same to work with the Change node, but I don’t find a way to insert an expression there. I over-simplified the flow to make this part easier to solve (before, I was trying to explain the complexity of it, to see if there maybe was a way to do it all different, but I’m now confident that if I solve this for the Change node, the whole thing would be solved).

[{"id":"f1dab4dab2cef4a4","type":"debug","z":"fbb020a344ed4251","name":"Complete Msg Debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":810,"y":2920,"wires":[]},{"id":"1674b1082d7cc8bc","type":"inject","z":"fbb020a344ed4251","name":"set msg.bypassVar to string laundryLightBypass","props":[{"p":"bypassVar","v":"laundryLightBypass","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":220,"y":2800,"wires":[["78b2932ec14e36df"]]},{"id":"78b2932ec14e36df","type":"change","z":"fbb020a344ed4251","name":"set laundryLightBypass true","rules":[{"t":"set","p":"laundryLightBypass","pt":"flow","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":2800,"wires":[["c51b0530a8d7ba59"]]},{"id":"c51b0530a8d7ba59","type":"switch","z":"fbb020a344ed4251","name":"check if bypassVar (should read from laundryLightBypass) is true, JSON expression","property":"$flowContext(bypassVar)","propertyType":"jsonata","rules":[{"t":"true"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":330,"y":2880,"wires":[["63288d5ac34dad95"],["f1dab4dab2cef4a4"]]},{"id":"63288d5ac34dad95","type":"debug","z":"fbb020a344ed4251","name":"Complete Msg Debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":810,"y":2860,"wires":[]}]

Currently the Change node is set this way, which would need to be edited for each duplicated flow:
image

The ideal would be if it could change the flow.laundryLightBypass from a setting like this:
image
But I don’t see that it has the option to write an expression. Maybe using the a function node instead?

I really need to learn some json basics, what would you recommend me as a start point?

Thanks!!
Rodrigo

You can use a function node for that

[{"id":"a5347e659f8cc73f","type":"function","z":"f80b6c338afd5483","name":"set var","func":"var bypass = msg.bypassVar\nflow.set(\"bypass\", \"true\");\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1110,"y":4020,"wires":[[]]}]

Ok, I’ve been trying to make this code set the variable without success :worried:

[{"id":"a5347e659f8cc73f","type":"function","z":"fbb020a344ed4251","name":"this should set flow.testBypass to true but getting its variable name from msg.bypassVar","func":"var bypass = msg.bypassVar\nflow.set($flowContext(bypassVar), \"true\");\nreturn msg;","outputs":1,"noerr":2,"initialize":"","finalize":"","libs":[],"x":710,"y":2740,"wires":[["aa2af3d1671a8617"]]},{"id":"dfc236557ba6454d","type":"debug","z":"fbb020a344ed4251","name":"payload should read true","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":790,"y":2800,"wires":[]},{"id":"c74c935b00be405b","type":"inject","z":"fbb020a344ed4251","name":"set bypassVar name \"testBypass\"","props":[{"p":"bypassVar","v":"testBypass","vt":"flow"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":210,"y":2740,"wires":[["a5347e659f8cc73f"]]},{"id":"aa2af3d1671a8617","type":"change","z":"fbb020a344ed4251","name":"set payload to testBypass state","rules":[{"t":"set","p":"payload","pt":"msg","to":"testBypass","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":2800,"wires":[["dfc236557ba6454d"]]},{"id":"69012524c306fdd9","type":"inject","z":"fbb020a344ed4251","name":"set flow.testBypass to false","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"-","x":190,"y":2680,"wires":[["ddebb413a2a89f85"]]},{"id":"ddebb413a2a89f85","type":"change","z":"fbb020a344ed4251","name":"set flow.testBypass to false","rules":[{"t":"set","p":"testBypass","pt":"flow","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":2680,"wires":[[]]}]

The second node, without mentioning “testBypass” inside its code (so it doesn’t need to be edited after being duplicated), should be able to set flow.testBypass to true.

I find that this node creates a flow.bypass variable and sets it to true. I cannot have a flow.bypass variable because sometimes many switches will be activated at once and they would all be stopped by the same flow variable.

Seeing the solution that worked in the switch node, I imagine something like this:
image

Thanks again @Mikefila !!
Rodrigo

I finally got the solution for both nodes.

For the Switch node, the solution was in post #7 from @Mikefila (thx again!)

For the Change node, I the solution came from nodered forum (link to post), from user bakman2.

I’ll post another doubts I have in separate topics to keep things organized.

Rodrigo