Need Help with Loop in Node Red

hi so i trying to make an alarm that when you press a button starts and toggles all the lights in my home… but when you press another button it will shut off the alarm… but it wont stop it… its stuck in a loop… so i played with some values… but i cant make it stop it wont read the 2nd input to stop the endless loop and just stop not sure what i need to do

so i making it for my mother… using a shelly button1… she will press the button and that will start the alarm if she needs help. and i want to press a button to deactivate the alarm… to disable the flashing… but so far endless flashing

alarm 3
alarm 2

Some basics on how Node-RED works…

When you inject a message into a flow, that message goes down the flow from node to node until it reaches an end or terminal node. Where there are two (or more) wires out of a single node exit, that duplicates the message to two (or more) messages.

Here is the catch - if you inject a second message into a flow, or create a second message within the flow, then that second message exists entirely and utterly independently to the first one, and it too will go on through the flow until it reaches a termination node or a node without output. Node-RED flows can have many messages, each one progresses independently (in parallel too) and with its own payload. Messages know nothing about each other, so injecting a second message does not have any impact on the already-going-around message.

Loops in Node-RED are, for the best part, to be avoided. They can cause runaway, can be difficult to stop, and they are open to memory leak which can result in NR crashing.

It is possible to set up a circular loop like this with effective control, but this requires either a ‘gateway’ node that can, for example, read an externally set context variable to decide to halt, or by using delay nodes that can be reset to clear the message in the queue and thus prevent it from continuing. The way I control loops is to put a delay in (which probably should be in every loop) and set this with a second inject (or input) that holds msg.reset as ‘true’. The delay node will flush and remove all queued messages when a new message with a ‘reset’ field arrives, thus effectively killing a looping message.

That said, I don’t think you actually need a loop for what you want to do. The underrated ‘trigger’ node does quite a lot of things, including being able to send a message regularly, and being able to stop when sent a reset message or a msg.payload with a defined value.

[{"id":"fe24de63ec295ebb","type":"inject","z":"92ed4c92bf112b10","name":"Start","props":[{"p":"topic","vt":"str"},{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"run","payload":"0","payloadType":"num","x":250,"y":1280,"wires":[["111272bc9d484f37"]]},{"id":"c9fe6849d9f2ce9d","type":"inject","z":"92ed4c92bf112b10","name":"Stop","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"stop","payloadType":"str","x":250,"y":1340,"wires":[["111272bc9d484f37","7d58134874274d42"]]},{"id":"111272bc9d484f37","type":"trigger","z":"92ed4c92bf112b10","name":"Alarm Toggle","op1":"ALARM","op2":"0","op1type":"str","op2type":"str","duration":"-2","extend":false,"overrideDelay":false,"units":"s","reset":"stop","bytopic":"all","topic":"topic","outputs":1,"x":490,"y":1280,"wires":[["1670d1674e671dec"]]},{"id":"7d58134874274d42","type":"debug","z":"92ed4c92bf112b10","name":"Payload Is","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":990,"y":1340,"wires":[]},{"id":"1670d1674e671dec","type":"change","z":"92ed4c92bf112b10","name":"Add time just to show it is working","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload & \" \" & $now()","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":740,"y":1280,"wires":[["7d58134874274d42"]]}]

This flow just starts sending ‘ALARM’, when triggered with the start input, and continues to do so every 2 seconds. This is stopped with the second inject. It should not take too much effort to use something like this with your Toggle service call. I have added a change node with a bit of JSONata code to add the timestamp to the text message, just so you can see that this is working.

Hope this helps!

@Biscuit thanks that worked… i had googled. about the looping and i had tried the counter function but it wasnt working right and i had also crashed node red… i guess it ran out of memory like you mentioned… why does it do it… i was going to try to do it in HA instead… i just liking the Node red and the images easier to see… now i wanna learn notifications in node red as i can do it text base notify in HA in automation just dont know how to do it in Node red…

so i got it to work… so that trigger is a looper … i did notice if you click the stop it does activate the lights once but it doesnt loop it…

but i notice you can use any word to start… but its the word stop to end it… so i made a helper button to be able to stop it… and i made shelly button that has 4 different button presses and i made emergency button presses for my mom to hit from game machines 100mm sized buttons so she can slap it… that will activate the lights… but id like to add the email text notifcation to this i have notification setup in notify.yaml but i dont know how you link it in node red to send a email and a text message… would you happen to know how to do that too? this is what i got so far… which is working well so far
and i appreciate your help… as i was getting frustrated… and google and the videos wasnt helping me with what i wanted

ok i found a bug for bathroom emergency button… i dupicated for the bedroom and office i didnt make those yet… but i found if the esphome goes offline and back online its activating the switch so its activating the flashing so giving a false button press… i also found if i unplug the button… and the button in node red goes unavaliable… it will start the alarm automatically… here is the button info… maybe i got something wrong
so its weird… its activating if it goes offline or not plugged in and is unavailable


Loops in any computer program must be treated with care to avoid non-termination, and memory consumption that is never released. In general, physical loops in Node-RED should be avoided wherever possible!

The ‘trigger’ node can use any msg.payload value in the stop, I just used “stop” as it seemed a good idea. You can also use msg.reset set to any value.

You will need to experiment with the basic turn-on, flash every two seconds, turn-off stuff until it works for you. Node-RED is designed as a rapid prototyping tool, so expect to keep tinkering with stuff until you get what you want. Red-Green-Refactor.

Sending emails is easy - you just need to use the email node, and have access to an email sever. If you also want to send notifications to your phone, if you have HA app on your phone, then you can probably use the Service Call node to run a notification message service call and ping your phone.

Many HA sensors, particularly over WiFi, will go unavailable quite often. The Events: state node will run every time either the entity state or an entity attribute changes - including going from ‘off’ to ‘unavailable’ and back to ‘off’ - and there are settings to deal with this.
You have ‘ignore state change events when’ options. The default is ‘current state equal previous state’ which is a no-brainer. You can also select ‘current state is unknown’ which will ignore when the state goes ‘unknown’.

You can also use the ‘If State’ option, set to ‘is’ and then enter a value. For example, with buttons where the state goes ‘on’ and ‘off’, you can set the conditional test up for
If State is “ON” for 30 seconds.
This will only allow the node to send an output message if the state value is ON for the entire 30 seconds. Note that the state value must be exactly the value provided by your button / sensor device, so check using the Developer - States tool. If this is a string value, then case is important too.

Also, since you are using this for an alarm system, I would like to point out that using HA is not totally reliable and can fail in mission critical situations. The real challenge is to work out how to add redundancy and fail-safe backup to something like this. I have enough problems just trying to get my HA & Node-RED setup to send commands to my Solar inverter without the occasional command failure. What happens when I press a button, but nothing happens? It is quite common for a ‘use only when required’ emergency device/system to fail at the point of first use. A reverse approach would be, perhaps, to require a button to be pressed at least every (say) six hours, which would then reset a timer in Node-RED. If the six hours is up, and no button has been pressed, then send a message. If nine hours is up, and no button has been pressed, then go to ‘alarm’.
An approach now being considered for the care of the elderly is to use power-use monitoring in the home to detect if they have not got out of bed, used the kettle / toaster / turned on a light. You can also use motion sensors (even shelly contact sensors on doors) for much the same approach. Passive monitoring.

Hope this helps - good luck with your project

I am quoting this just to restate the fact given the nature of this automation. I handle loops for lights a little differently. I use something similar to this for my outside security lights, the difference being that the lights are off when I stop the loop. In this case when the flashing stops, I think you’d want all the lights on.

I use a boolean to start the loop, then I use that same boolean in a current state node to stop it. If the boolean is on the loop continues, if the boolean is off, the flow stops.

[{"id":"ea53b47326799ecb","type":"server-state-changed","z":"60f2d2277843c698","name":"alarm boolean","server":"6b1110b5.183a4","version":5,"outputs":2,"exposeAsEntityConfig":"","entityIdType":"exact","outputInitially":false,"stateType":"str","ifState":"on","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":310,"y":940,"wires":[["530da10ecfeeebc4"],[]]},{"id":"5c18114bf920b4ea","type":"api-current-state","z":"60f2d2277843c698","name":"is alarm boolean still on?","server":"6b1110b5.183a4","version":3,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","entity_id":"","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"date"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":790,"y":1060,"wires":[["601612ccf2b1b7e6"],[]]},{"id":"601612ccf2b1b7e6","type":"api-call-service","z":"60f2d2277843c698","name":"turn off light","server":"6b1110b5.183a4","version":5,"debugenabled":false,"domain":"","service":"","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"date"}],"queue":"none","x":510,"y":980,"wires":[["ade1a5c272f7bc43"]]},{"id":"ade1a5c272f7bc43","type":"delay","z":"60f2d2277843c698","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":680,"y":980,"wires":[["530da10ecfeeebc4"]]},{"id":"530da10ecfeeebc4","type":"api-call-service","z":"60f2d2277843c698","name":"turn on light","server":"6b1110b5.183a4","version":5,"debugenabled":false,"domain":"","service":"","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"date"}],"queue":"none","x":870,"y":940,"wires":[["76901d990fd239a2"]]},{"id":"76901d990fd239a2","type":"delay","z":"60f2d2277843c698","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":1040,"y":940,"wires":[["5c18114bf920b4ea"]]},{"id":"6b1110b5.183a4","type":"server","name":"Home Assistant","version":5,"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":"id","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]

If you use a loop, like the one Mikefilla suggested or any other one actually, then check that the size of the msg do not increase with each loop.
If it does then you might need to insert a change node in the loop and delete the attributes that makes it grow.
This will avoid crashes due to memory run-outs.

In that note, if you do use my suggestion but not use the flow provided, the message output is reduced to payload and timestamp only.



ah always learning…ya i kinda have a backup of a fail safe for home assistant i run a 2nd copy of home assistant that does lights… but ya i had mentioned i wishd HA could do fail over if 1 HA fails it flips to another… i did play with 2 copies running of the same as a fail over with pfsense and such i had hit and miss … so i run 2 different setups using remote home assistant… for some things… and it works for some things… but not 100%

and ya i noticed wifi isnt perfect it disconects alot least the esphome and shellys and tplinks at times… what is a better setup i like wired but i cant wire everything… and the blue tooth i dont think can work 100 200 feet outside so reason i went with a shelly button 1 w which i testing and i got the email to work to send a message

i have another qestion … in regular hA i use Set_state a python script to change a Sensor state… now in node red you can change a sensor state if you create the sensor in node red… now i wanted to to use the set_state

run the python script to send a messsage to my displays screens i have this is what i have in my HA automations for Amazon i been trying to get it to work in Node red but i dont know how to get a Json or a Expresson to send a message or inject a change message

          - service: python_script.set_state
              entity_id: sensor.deliveries_alert_message
              state: >-
                Amazon Gifts Been Delivered                Intelcom  {{
                now().strftime('%B %-d, %I:%M %p')  }}

and i appreciate the other guys inputs too… always learning… tooi will check out that code too…

i have a sensor called
i wanna use

so what im trying is so all working now i working on sending to displays i have to a red alart sensor
here is what i trying least the majority is working

i did try the update_entity but i couldnt get that to work well it says it works but it didnt update the sensor lol


Home Assistant entities are created (registered) by the various integrations, and then the state value is updated by that integration. Updating entity states by other means is not seen as a good idea, but if you have a python script service call that works for you…

The Home Assistant service call - update entity will not replace an entity state value with your provided value, it is just there to trigger HA to prompt the owning integration to do what it usually does and thereby cause a refresh of the entity state. This is usually used on template entities that would automatically update on a given time cycle, so that you can force a refresh of the entity state earlier.

Your python script provides a service call, and yes you can use these from Node-RED with the Call Service node. Looking at your picture of your settings I would suggest that your JSONata is back to front. You probably need something more like

{"message": message}

There is lots of documentation on the WebSocket GitHub page, with plenty explaining how to setup service calls, and how JSONata works, and how to use JSONata to construct the Call Service ‘Data’ field.