Need help with a Node Red flow

So I’ve been trying to use a loop node with Node-Red to trigger a switch when a scene activates to no avail. It seems like the scene state is a timestamp which seems a bit weird, but I’m not sure. I have not been able to get this to work properly and I’m new so any advice would be helpful. I have added the JSON from the flow.

[
    {
        "id": "023b12ef7d84d6be",
        "type": "tab",
        "label": "Flow 1",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "789192c486d850ff",
        "type": "trigger-state",
        "z": "023b12ef7d84d6be",
        "name": "",
        "server": "58789d9e.7d1274",
        "version": 4,
        "inputs": 0,
        "outputs": 2,
        "exposeAsEntityConfig": "",
        "entityId": "scene.bed_time",
        "entityIdType": "exact",
        "debugEnabled": true,
        "constraints": [
            {
                "targetType": "this_entity",
                "targetValue": "",
                "propertyType": "current_state",
                "propertyValue": "new_state.state",
                "comparatorType": "is",
                "comparatorValueDatatype": "str",
                "comparatorValue": ""
            }
        ],
        "customOutputs": [],
        "outputInitially": true,
        "stateType": "habool",
        "enableInput": false,
        "x": 360,
        "y": 420,
        "wires": [
            [
                "352070a3682a3c6e"
            ],
            []
        ]
    },
    {
        "id": "352070a3682a3c6e",
        "type": "loop",
        "z": "023b12ef7d84d6be",
        "name": "",
        "kind": "fcnt",
        "count": "2",
        "initial": "1",
        "step": "1",
        "condition": "",
        "conditionType": "js",
        "when": "before",
        "enumeration": "enum",
        "enumerationType": "msg",
        "limit": "200",
        "loopPayload": "loop-index",
        "finalPayload": "final-count",
        "x": 670,
        "y": 420,
        "wires": [
            [],
            [
                "5be6c2b4b2e0d7c3"
            ]
        ]
    },
    {
        "id": "5be6c2b4b2e0d7c3",
        "type": "trigger-state",
        "z": "023b12ef7d84d6be",
        "name": "",
        "server": "58789d9e.7d1274",
        "version": 4,
        "inputs": 1,
        "outputs": 2,
        "exposeAsEntityConfig": "",
        "entityId": "switch.bot_5320",
        "entityIdType": "exact",
        "debugEnabled": true,
        "constraints": [
            {
                "targetType": "this_entity",
                "targetValue": "",
                "propertyType": "current_state",
                "propertyValue": "new_state.state",
                "comparatorType": "is",
                "comparatorValueDatatype": "str",
                "comparatorValue": "turn on"
            }
        ],
        "customOutputs": [],
        "outputInitially": false,
        "stateType": "str",
        "enableInput": true,
        "x": 680,
        "y": 620,
        "wires": [
            [
                "352070a3682a3c6e",
                "c0a20b484f79bf66"
            ],
            []
        ]
    },
    {
        "id": "c0a20b484f79bf66",
        "type": "debug",
        "z": "023b12ef7d84d6be",
        "name": "debug 1",
        "active": true,
        "tosidebar": true,
        "console": true,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "payload",
        "statusType": "auto",
        "x": 1020,
        "y": 680,
        "wires": []
    },
    {
        "id": "58789d9e.7d1274",
        "type": "server",
        "name": "Home Assistant",
        "addon": true
    }
]

I’m not familiar with the loop node but I don’t think you need it to do what you want to do:when an entity state changes (detected with either a events state or trigger state) turn on switch (usually done via a call service node) .

There are some good examples of how to do various activities in node-red here:

I need the switch to “turn on” multiple times, which is why I opted for the loop node. Here is the loop node I was referring to.

The “trigger: state” node responds to the change of an entity (like "events: state), it does not change the state itself. Instead you would need a “call service” node to call turn_on for the switch.

If there’s some need to turn the switch on multiple times (because it’s flaky?) then you could follow that node with a “wait until” that waits for the switch’s state to be “on”, and if it doesn’t happen within a timeout of (say) 2 seconds, link the second output back to the “call service” node to try again. No need for a “loop” node - and generally speaking you will never need a loop node, which is why one doesn’t exist in the built-in nodes.

If you go with the above, and the switch is never going to turn on for whatever reason, then this code will keep looping forever. Therefore you might also want to include some sort of counter on the message and incude a “switch” node to get out if you’ve tried more than 10 times. A “change” node to set “msg.counter” with JSONata of $exists(counter) ? counter+1 : 0 would handle setting the counter.

Similarly, your first “trigger: state” node should probably be an “event: state” node with the value set to something - “on” probably, but I don’t use scenes. At the moment it’s set to a boolean payload with no conditions, which doesn’t look right.

So I have the trigger state because I am actually triggering the scene through a voice command. I don’t think the switch is flaky, it’s just based on the way I’m automating something that is mechanical.

I’m confused about what’s not working, have you been able to actually get the switch to work at all? If not, then you need a call service node.

Otherwise, can you say more?

So the switches work, I just need them to activate multiple times in a row.

Node-RED, particularly when trying to work with the Home Assistant WebSocket nodes, is confusing when you first start, and so much has to be setup correctly it can sometimes be a real minefield to get anywhere.

The challenge here is as much to do with trying to unpick your flow, which for me I’m afraid does not make a lot of sense. In the spirit of trying to help (and also to perhaps leave a few posts that just may help others later on) here are my thoughts.

Scenes:
These are an HA thing, and can be setup in config to effectively execute a ‘script’ of things to do (entities to change) when activated. Hence, from HA, you activate or ‘run’ a scene.

They also get included as entities when you integrate things like Google Home - In my case I have integrated my Somfy TaHoma Switch (which has ‘scenes’) hence I too have scenes like ‘Morning_Sun’ in TaHoma. Because of my TaHoma (Overkiz) integration I have an entity for scene.morning_sun in HA.

Yes I can ‘activate’ the scene in HA, and the scene is then run inside TaHoma. The state value for the entity scene.morning_sun is nothing more than the timestamp for when it was last run or executed, so when I activate the scene from within HA, the state value of scene.morning_sun is set to ‘now’.

Node_RED flow - trigger:
All flows have to start with something triggering them. NR is after all an event based ‘language’.
So, yes you can listen out for the state of ‘scene.bed_time’ changing (which it will do every time it is run from within HA).

You are using the trigger: state node, which is an advanced version of the event: state node, with additional conditional checks for the actual state change. In reality, since the scene entity state will only ever be a timestamp, you can simply listen out for it to change, so you really don’t need anything more complicated than the event: state node. This would be easier to set up and much more likely to work.

(as the other posters above have said - your trigger: state node is set to listen to the Boolean version of the state - which, for a timestamp should always be a non-zero ‘true’ - and with no conditions, so it is probably just firing on any old state update anyway.)

Switches:
Yes, we are all confused here!
You have trigger nodes again, apparently listening to your switches changing state. This is very different to having a service call that turns on (or off) a switch, so your user experience here seems to be:-

I say “Hey Home Assistant, activate bed time”.
Then I turn a wall switch on and off (twice)
Then… (something happens but your flow is not going anywhere else)

If this is not what you want to happen, then yes change the switch trigger nodes for service calls that change a switch entity state.

Loops:
I find Node-RED not great when trying to do loops, and I really do miss a ‘while…do’ loop. Well yes there is the loop node, but I personally like to arrange my code myself to ensure it works correctly. Physical loops in Node-RED can be a real problem with non-termination (loop control), memory leaks, and spaghetti code.

Looking at your code, you really just seem to want to do (something) twice following the trigger. In Node-RED ‘better’ practice would be to use an array, and iterate (or loop) over this by splitting it into parts, so each part is processed (and then perhaps later join up the array).

Example flow:
So, I have set up a simple events: state node to listen to a scene being triggered.
( I have also removed all of the output properties to just msg.payload - as I don’t need them I like to try and keep things like this tidy)

Then I have used a change node and a JSONata expression to generate an integer array (the [a…b] construct in JSONata generates a list of integers between a and b, hence I end up with just a simple array [1, 2])

Then I have used a split node, which spits out a new message for each item in the array (ie two messages)

Then I have put in a delay node set to rate-limit the messages so they are spaced out a bit in sequence. This is a neat way of doing things repeatedly, but without having a loop.

Then I used a call service node to (in this case) toggle a switch (a smart plug).

Then I tidy up again by joining up my split (this is not that important, but it does reduce the potential risk of memory leak as I have found from experience…)

This all avoids going around any loop, hence no control required to do and to exit the loop, no risk of infinite looping, and no memory leak issues.

It works too - I tried it. Winking lights when I activate my scene. Just change your ‘scene’ and ‘switch’ and ‘service’ to whatever you require (and reset to your Home Assistant server as I have ‘scrubbed’ this from my exported flow).

Merry Christmas to one and all.

[{"id":"98805b1fceb0f656","type":"server-state-changed","z":"023b12ef7d84d6be","name":"When I activate my routine","server":"","version":5,"outputs":1,"exposeAsEntityConfig":"","entityId":"scene.morning_sun","entityIdType":"exact","outputInitially":false,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":true,"ignoreCurrentStateUnavailable":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"x":150,"y":80,"wires":[["781d8babde1e323a"]]},{"id":"0f231fe4979f1b1f","type":"split","z":"023b12ef7d84d6be","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":530,"y":80,"wires":[["0a93e223b2b8198a"]]},{"id":"781d8babde1e323a","type":"change","z":"023b12ef7d84d6be","name":"Set array 1 to n","rules":[{"t":"set","p":"payload","pt":"msg","to":"[1..2]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":80,"wires":[["0f231fe4979f1b1f"]]},{"id":"7e2f729a3c1aaa6b","type":"debug","z":"023b12ef7d84d6be","name":"debug 294","active":false,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":890,"y":180,"wires":[]},{"id":"0a93e223b2b8198a","type":"delay","z":"023b12ef7d84d6be","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"3","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":320,"y":180,"wires":[["ca94d21053e0e603"]]},{"id":"ca94d21053e0e603","type":"api-call-service","z":"023b12ef7d84d6be","name":"Toggle Light (switch)","server":"","version":5,"debugenabled":false,"domain":"switch","service":"toggle","areaId":[],"deviceId":[],"entityId":["switch.t2"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":540,"y":180,"wires":[["a2a50fb269b5697e"]]},{"id":"a2a50fb269b5697e","type":"join","z":"023b12ef7d84d6be","name":"","mode":"auto","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":true,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":730,"y":180,"wires":[["7e2f729a3c1aaa6b"]]},{"id":"de16c07f02115655","type":"inject","z":"023b12ef7d84d6be","name":"Manual Test","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":190,"y":40,"wires":[["781d8babde1e323a"]]}]

This seems pretty helpful. Let me apply some of this and get back to you. Thank you.

So I noticed that the “loop” doesn’t seem to be consistent with the adjustments I’ve made. The switches I referred to in the initial post are these. When my scene activates, the switches go off, but sometimes not as many times as I’m expecting (three times each). What did I do wrong?

[{"id":"28fef98818596f60","type":"tab","label":"Flow 2","disabled":false,"info":"","env":[]},{"id":"98805b1fceb0f656","type":"server-state-changed","z":"28fef98818596f60","name":"Night Time Mode Activated","server":"58789d9e.7d1274","version":5,"outputs":1,"exposeAsEntityConfig":"","entityId":"scene.bed_time","entityIdType":"exact","outputInitially":false,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":true,"ignoreCurrentStateUnavailable":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"x":290,"y":460,"wires":[["781d8babde1e323a"]]},{"id":"0f231fe4979f1b1f","type":"split","z":"28fef98818596f60","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":850,"y":380,"wires":[["0a93e223b2b8198a"]]},{"id":"781d8babde1e323a","type":"change","z":"28fef98818596f60","name":"Set array 1 to n","rules":[{"t":"set","p":"payload","pt":"msg","to":"[0..2]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":380,"wires":[["0f231fe4979f1b1f"]]},{"id":"7e2f729a3c1aaa6b","type":"debug","z":"28fef98818596f60","name":"debug 294","active":false,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1410,"y":480,"wires":[]},{"id":"0a93e223b2b8198a","type":"delay","z":"28fef98818596f60","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"5","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":640,"y":480,"wires":[["ca94d21053e0e603"]]},{"id":"ca94d21053e0e603","type":"api-call-service","z":"28fef98818596f60","name":"Toggle Bed Right Side","server":"58789d9e.7d1274","version":5,"debugenabled":false,"domain":"switch","service":"toggle","areaId":[],"deviceId":["673182d2fb6e13ccd9030cb017b0084d"],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":860,"y":480,"wires":[["a1a560f4302e104e"]]},{"id":"a2a50fb269b5697e","type":"join","z":"28fef98818596f60","name":"","mode":"auto","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":true,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":1250,"y":480,"wires":[["7e2f729a3c1aaa6b"]]},{"id":"de16c07f02115655","type":"inject","z":"28fef98818596f60","name":"Manual Test","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":310,"y":340,"wires":[["781d8babde1e323a"]]},{"id":"a1a560f4302e104e","type":"api-call-service","z":"28fef98818596f60","name":"Toggle Bed Left Side","server":"58789d9e.7d1274","version":5,"debugenabled":false,"domain":"switch","service":"toggle","areaId":[],"deviceId":["35dc5847a29bf11099a14c7a1319d2cf"],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1080,"y":480,"wires":[["a2a50fb269b5697e"]]},{"id":"58789d9e.7d1274","type":"server","name":"Home Assistant","addon":true}]

Sorry for that wall of text, I wasn’t sure how you did that formatting with you JSONata.

You will find that using the ‘</>’ option is better for posting code. Shorter, potentially readable by scrolling, and there is a nice ‘copy to clipboard’ icon at the right.

[{"id":"28fef98818596f60","type":"tab","label":"Flow 2","disabled":false,"info":"","env":[]},{"id":"98805b1fceb0f656","type":"server-state-changed","z":"28fef98818596f60","name":"Night Time Mode Activated","server":"58789d9e.7d1274","version":5,"outputs":1,"exposeAsEntityConfig":"","entityId":"scene.bed_time","entityIdType":"exact","outputInitially":false,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":true,"ignoreCurrentStateUnavailable":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"x":290,"y":460,"wires":[["781d8babde1e323a"]]},{"id":"0f231fe4979f1b1f","type":"split","z":"28fef98818596f60","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":850,"y":380,"wires":[["0a93e223b2b8198a"]]},{"id":"781d8babde1e323a","type":"change","z":"28fef98818596f60","name":"Set array 1 to n","rules":[{"t":"set","p":"payload","pt":"msg","to":"[0..2]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":380,"wires":[["0f231fe4979f1b1f"]]},{"id":"7e2f729a3c1aaa6b","type":"debug","z":"28fef98818596f60","name":"debug 294","active":false,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1410,"y":480,"wires":[]},{"id":"0a93e223b2b8198a","type":"delay","z":"28fef98818596f60","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"5","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":640,"y":480,"wires":[["ca94d21053e0e603"]]},{"id":"ca94d21053e0e603","type":"api-call-service","z":"28fef98818596f60","name":"Toggle Bed Right Side","server":"58789d9e.7d1274","version":5,"debugenabled":false,"domain":"switch","service":"toggle","areaId":[],"deviceId":["673182d2fb6e13ccd9030cb017b0084d"],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":860,"y":480,"wires":[["a1a560f4302e104e"]]},{"id":"a2a50fb269b5697e","type":"join","z":"28fef98818596f60","name":"","mode":"auto","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":true,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":1250,"y":480,"wires":[["7e2f729a3c1aaa6b"]]},{"id":"de16c07f02115655","type":"inject","z":"28fef98818596f60","name":"Manual Test","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":310,"y":340,"wires":[["781d8babde1e323a"]]},{"id":"a1a560f4302e104e","type":"api-call-service","z":"28fef98818596f60","name":"Toggle Bed Left Side","server":"58789d9e.7d1274","version":5,"debugenabled":false,"domain":"switch","service":"toggle","areaId":[],"deviceId":["35dc5847a29bf11099a14c7a1319d2cf"],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1080,"y":480,"wires":[["a2a50fb269b5697e"]]},{"id":"58789d9e.7d1274","type":"server","name":"Home Assistant","addon":true}]

I do not have the ‘loop’ node in my palette, so I just read through the code JSON and picked out the settings - which seem to suggest start at 1 and count 2.

The JSONata construct [a..b] I used builds an array of integers between a and b. Whilst computers count from 0, personally I like to count from 1, so I set this to [1..2] which generates [1, 2] or 2 passes, so runs the service call nodes twice. Certainly [0..2] or [1..3] will run it three times. You could even use a parameter to make it a variable number of passes as [1..payload] where input payload contained an integer value for the number of passes required.

That all said, I don’t have your scene and switch-bots to play with, but I do have a scene and some smart plugs, and yes they all toggle three times in a row, so I guess the code is all working nicely. If you continue to have issues with the number of times the end device operates, then this must be with the integration / hardware and perhaps a longer delay between each pass is required.

Okay, let me experiment with the delay and see what happens. Thank you for the help.

Thinking about this, I suspect that a delay between the your two call service nodes is required too - it is probably too much to expect an integration to process two service calls in succession.

That makes sense, I’ll give that a shot.