Loop never exit using node-red-contrib-loop JS condition

I am new to node, so bare with me for the newbe question.
Background: I am using node-red installed on a HomeAssistance box
I am trying to setup Node to execute a loop. I am using node-red-contrib-loop.

On the Loop cycle, I am not able to create a condition to exit properly the loop.

See this example:

  • I start setting the payload to "on" or "off" using two different starting injection node.
  • loop cycle start
  • if injection was "off", the loop does not execute and exit, which is the expected behaviour.
  • if injection started with "on", the loop cycle execute, payload gets changed to "off" though a function after 5 seconds the loop should exit the cycle.

But this never happen and the loop continue without ever stopping.
On the "Loop Status" debug trace you can notice that the paylod gets actualy changed to "off" but the condition on the loop is never valid

Loop node is configured like this:

Function code is simply:

msg.payload = "off";
return msg;

Any suggestion?
This is the code of it

[{"id":"12ff73b357cc048c","type":"debug","z":"88350d16bca26e96","name":"Initial payload","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":360,"y":180,"wires":[]},{"id":"05eca99e83ef171b","type":"delay","z":"88350d16bca26e96","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":420,"y":360,"wires":[["a97bb9f03de6e1a0"]]},{"id":"04df46b06fba53d6","type":"debug","z":"88350d16bca26e96","name":"EndLoop","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":920,"y":340,"wires":[]},{"id":"11868e0005682135","type":"debug","z":"88350d16bca26e96","name":"Loop Status","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":930,"y":400,"wires":[]},{"id":"a97bb9f03de6e1a0","type":"loop","z":"88350d16bca26e96","name":"Loop is Charging","kind":"cond","count":"","initial":"1","step":"1","condition":"msg.payload===\"on\"","conditionType":"js","when":"before","enumeration":"enum","enumerationType":"msg","limit":"","loopPayload":"loop-keep","finalPayload":"final-last","x":710,"y":360,"wires":[["04df46b06fba53d6"],["11868e0005682135","daf1fe87f33cb6af"]]},{"id":"51b60d1515376b14","type":"inject","z":"88350d16bca26e96","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"on","payloadType":"str","x":130,"y":180,"wires":[["12ff73b357cc048c","a97bb9f03de6e1a0"]]},{"id":"daf1fe87f33cb6af","type":"function","z":"88350d16bca26e96","name":"function payload update","func":"msg.payload = \"off\";\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":150,"y":360,"wires":[["05eca99e83ef171b"]]},{"id":"af8fe1c7d6bd86fb","type":"inject","z":"88350d16bca26e96","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"off","payloadType":"str","x":130,"y":220,"wires":[["a97bb9f03de6e1a0","12ff73b357cc048c"]]}]

Welcome to the forum @zu76

A loop is almost never the best way to do things in node red. If you explain what you need to do, at a higher level, then probably we can suggest a better solution.

Not having the loop node installed, as Colin says it is not the best way to do things in node-red (normally).
Saying that reading the nodes read me, have you tried this in the function node

msg.payload = "off";
msg.command = "break";
return msg;

Thank Colin,
the idea is to build a flow to manage a "charge with solar" scenario.
When I want to charge my electric car, I want to start the charge but only use the spare energy flowing from my solar panel, but prioritizing the home usage and the home battery charge first, and then set the car charge Amper to only the still available, managing as well up-and-down of the sun.

I thought approaching though a loop and checking all the different power statuses (which I have available on my homeassistant)

The on or off of the above post, were on behalf of executing a charge or just stop-it.
hope this is more clear.

If you want to repeatedly do something then often the way to do is to use an Inject node firing every second (or whatever rate you want) that runs through determining what to do each time.

You can also take all the inputs and join them, the join can output each time a input comes in. You can then use logic to figure out what to do according to the latest inputs.

This example takes 2 input s charge and power. Every time one changes the following logic example decide what to do.
There are to examples after the join, both do the same thing, one uses jsonata the other switch nodes.

[{"id":"51b60d1515376b14","type":"inject","z":"d1395164b4eec73e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"power","payload":"20","payloadType":"num","x":340,"y":40,"wires":[["cfcdbae43d099d7f"]]},{"id":"cfcdbae43d099d7f","type":"join","z":"d1395164b4eec73e","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":true,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":570,"y":140,"wires":[["647c1c1b662c22b1","e3803f9ebae40877"]]},{"id":"af8fe1c7d6bd86fb","type":"inject","z":"d1395164b4eec73e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"power","payload":"10","payloadType":"num","x":340,"y":80,"wires":[["cfcdbae43d099d7f"]]},{"id":"78c897e15b0037b7","type":"inject","z":"d1395164b4eec73e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"charge","payload":"80","payloadType":"num","x":340,"y":180,"wires":[["cfcdbae43d099d7f"]]},{"id":"59618aa5373f84c6","type":"inject","z":"d1395164b4eec73e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"charge","payload":"10","payloadType":"num","x":340,"y":220,"wires":[["cfcdbae43d099d7f"]]},{"id":"647c1c1b662c22b1","type":"change","z":"d1395164b4eec73e","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$not(false in [$$.payload.power > 10, $$.payload.charge < 80])","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":720,"y":100,"wires":[["fe2276d0e47ac1bc"]]},{"id":"e3803f9ebae40877","type":"switch","z":"d1395164b4eec73e","name":"","property":"payload.power","propertyType":"msg","rules":[{"t":"gt","v":"10","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":690,"y":200,"wires":[["be177d24280f5814"],["71ce5bb82f8f7c2c"]]},{"id":"fe2276d0e47ac1bc","type":"rbe","z":"d1395164b4eec73e","name":"","func":"rbe","gap":"","start":"","inout":"out","septopics":true,"property":"payload","topi":"topic","x":870,"y":100,"wires":[["12ff73b357cc048c"]]},{"id":"be177d24280f5814","type":"switch","z":"d1395164b4eec73e","name":"","property":"payload.charge","propertyType":"msg","rules":[{"t":"lt","v":"80","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":810,"y":200,"wires":[["aae47d2cbf99c2c7"],["71ce5bb82f8f7c2c"]]},{"id":"71ce5bb82f8f7c2c","type":"change","z":"d1395164b4eec73e","name":"false","rules":[{"t":"set","p":"payload","pt":"msg","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":930,"y":220,"wires":[["f456a6ea3d9c39a9"]]},{"id":"12ff73b357cc048c","type":"debug","z":"d1395164b4eec73e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1010,"y":100,"wires":[]},{"id":"aae47d2cbf99c2c7","type":"change","z":"d1395164b4eec73e","name":"true","rules":[{"t":"set","p":"payload","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":930,"y":180,"wires":[["f456a6ea3d9c39a9"]]},{"id":"f456a6ea3d9c39a9","type":"rbe","z":"d1395164b4eec73e","name":"","func":"rbe","gap":"","start":"","inout":"out","septopics":true,"property":"payload","topi":"topic","x":1050,"y":200,"wires":[["eb261bd191267c52"]]},{"id":"eb261bd191267c52","type":"debug","z":"d1395164b4eec73e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1210,"y":220,"wires":[]}]

This way you just have to use HA state change nodes to input the different readings
Hope this helps

Thank you Colin for the support!
I get it, most likely the node-red-contrib-loop can be avoided using the Inject node, as you suggested
p.s now I also understand also why its code has not been updated in the past 3 years :slight_smile:

1 Like

Thank you E1cid!!
well, your code also provide a nice approach for my solution tring to react to the change on the HA state changes.
Also, my original code works by adding msg.command = "break";

Still I don't understand why that loop was not exiting anyway, and needed a breack command, but, as you and Colin showed, this is most likely not the way to go.

Thank you very much!! :+1:

1 Like

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