Counter decrement not working

I have a flow where I decrement the brightness of lights starting from 100% and decrementing every 2mins by 1%. The flow stops at 0% when “countLowerLimitReached” is true.

When I deploy the flow everything works as it should. But the next day when the flow is triggered again it immediately stops because the count = 0 and countLowerLimitReached is true

I have tried everything I can think of, even changing the message after the trigger and explicitly removing the count and countLowerLimitReached, but as soon as the message leaves the counter for the first time they are back in the message at 0 and true.

I’m out of ideas, it must be simple but I don’t see it. Looks like state is remembered somewhere, but no idea why.

This is my flow

[{"id":"516088b10958505d","type":"http request","z":"2b5ce9b1350c8a99","name":"Set Brightness L","method":"POST","ret":"txt","paytoqs":"ignore","url":"http://192.168.1.45/rpc","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":1500,"y":780,"wires":[[]]},{"id":"a6288b4e8a48812e","type":"function","z":"2b5ce9b1350c8a99","name":"Configure Brightness","func":"msg.payload = {\n    \"id\": 1,\n    \"method\": \"Light.Set\",\n    \"params\": {\n        \"id\": 0,\n        \"on\": true,\n        \"brightness\": msg.count\n    }\n};\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1240,"y":880,"wires":[["516088b10958505d"]]},{"id":"a4c06de862e61610","type":"counter","z":"2b5ce9b1350c8a99","name":"Brightness Decrement","init":"100","step":"1","lower":"0","upper":"100","mode":"decrement","outputs":1,"x":820,"y":1020,"wires":[["6d1e01f53e015ae7","30efe11ea8b6da48"]]},{"id":"6d1e01f53e015ae7","type":"switch","z":"2b5ce9b1350c8a99","name":"Stop @ Minimum Brightness","property":"countLowerLimitReached","propertyType":"msg","rules":[{"t":"null"}],"checkall":"false","repair":false,"outputs":1,"x":1200,"y":1020,"wires":[["a5046f513e456237"]]},{"id":"a5046f513e456237","type":"stoptimer","z":"2b5ce9b1350c8a99","duration":"2","units":"Minute","payloadtype":"num","payloadval":"0","name":"Brightness Decrement Transition","x":910,"y":920,"wires":[["a4c06de862e61610","a6288b4e8a48812e"],[]]},{"id":"059faf7525b3b57b","type":"inject","z":"2b5ce9b1350c8a99","name":"Start DecrementTrigger","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":140,"y":960,"wires":[["a4c06de862e61610"]]},{"id":"bddf8c676e16a24c","type":"cronplus","z":"2b5ce9b1350c8a99","name":"Lights L Timer","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"fanOut","defaultLocation":"","defaultLocationType":"default","outputs":4,"options":[{"name":"Brightness Decrement 17h30","topic":"topic3","payloadType":"default","payload":"","expressionType":"cron","expression":"0 30 17 * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"},{"name":"Off 21h","topic":"topic4","payloadType":"default","payload":"","expressionType":"cron","expression":"0 0 21 * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":120,"y":880,"wires":[["a4c06de862e61610"],["ba446755e6952e8b"],[],[]]},{"id":"ba446755e6952e8b","type":"http request","z":"2b5ce9b1350c8a99","name":"Set Lights L Off","method":"GET","ret":"txt","paytoqs":"ignore","url":"http://192.168.1.7/rpc/Switch.Set?id=0&on=false","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":540,"y":1120,"wires":[[]]},{"id":"f132dc7ffc5cbdeb","type":"inject","z":"2b5ce9b1350c8a99","name":"Stop Lights Trigger","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":1020,"wires":[["ba446755e6952e8b"]]},{"id":"30efe11ea8b6da48","type":"debug","z":"2b5ce9b1350c8a99","name":"Debug Decrement","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":420,"y":1320,"wires":[]}]

And this is the message which leaves the counter node

20 Jun 17:30:00 - [info] [debug:Debug Decrement] 
{
  topic: 'topic3',
  scheduledEvent: true,
  payload: {
    triggerTimestamp: 1718897400000,
    status: {
      type: 'static',
      modified: false,
      isRunning: true,
      count: 2,
      limit: 0,
      nextDescription: 'in 23 hours 59 minutes 59 seconds',
      nextDate: 2024-06-21T15:30:00.000Z,
      nextDateTZ: 'Jun 21, 2024, 17:30:00 GMT+2',
      timeZone: 'Europe/Brussels',
      serverTime: 2024-06-20T15:30:00.023Z,
      serverTimeZone: 'Europe/Brussels',
      description: 'At 17:30'
    },
    config: {
      topic: 'topic3',
      name: 'Brightness Decrement 17h30',
      index: 0,
      payloadType: 'default',
      payload: '',
      limit: null,
      expressionType: 'cron',
      expression: '0 30 17 * * * *'
    }
  },
  _msgid: '3b2449f6bcd15793',
  count: 0,
  countLowerLimitReached: true
}

This is one of those trick exam questions, where once you have removed all the extra information, the real question is very easy to answer.

Question: why does the counter node keep the msg.count value between use?
Answer: because, like the delay node, it keeps its own data in memory, and this is only cleared on a flow redeploy. Nodes like this need to keep values in memory between the times the message passes through the node. How does it know when to forget that information?

So, how do I re-use the counter node, and get it to start at the initial count value, the next time I use it?
Answer: you reset the node. Like the delay node, counter accepts msg.reset as any value (it exists) so as to clear the node’s own stored values and start from scratch.

Problem: using msg.reset on starting the counter node will start it from scratch. However having msg.reset in the message for the remaining flow could also reset other nodes (msg.reset is a standard ‘please reset’ field)

Answer: start the counter node with msg.reset, then immediately delete msg.reset from the message.

Problem solved.

Example flow included in answer for extra marks.

[{"id":"a4c06de862e61610","type":"counter","z":"96f853bca7c085c7","name":"Brightness Decrement","init":"10","step":"1","lower":"0","upper":"10","mode":"decrement","outputs":1,"x":420,"y":640,"wires":[["88fc2261113c34ec"]]},{"id":"6d1e01f53e015ae7","type":"switch","z":"96f853bca7c085c7","name":"Stop @ Minimum Brightness","property":"countLowerLimitReached","propertyType":"msg","rules":[{"t":"null"}],"checkall":"false","repair":false,"outputs":1,"x":900,"y":640,"wires":[["5079e01277ea5d1e","225b3484d7260bbc"]]},{"id":"059faf7525b3b57b","type":"inject","z":"96f853bca7c085c7","name":"Start DecrementTrigger","props":[{"p":"reset","v":"true","vt":"bool"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":160,"y":640,"wires":[["a4c06de862e61610"]]},{"id":"225b3484d7260bbc","type":"delay","z":"96f853bca7c085c7","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":400,"y":580,"wires":[["a4c06de862e61610"]]},{"id":"5079e01277ea5d1e","type":"debug","z":"96f853bca7c085c7","name":"Debug Decrement","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"count","targetType":"msg","statusVal":"count","statusType":"auto","x":930,"y":680,"wires":[]},{"id":"88fc2261113c34ec","type":"change","z":"96f853bca7c085c7","name":"","rules":[{"t":"delete","p":"reset","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":640,"wires":[["6d1e01f53e015ae7"]]}]
1 Like

So simple! Thx a lot.
I will try it out this weekend and let you know

One of the first problems I had with NR was with the counter node. When I asked about it on the NR forum I was told to build my own with a function node.

55fc537fd0f196a1ae9e160393efed548e0cddcd

[{"id":"d1e7267c.8a21e8","type":"function","z":"89aa4a33.4c3098","name":"counter","func":"var count = context.get(\"count\") || 0;\n\nif(msg.topic == \"reset\" || msg.reset == true) {\n    count = 0;\n} else if (msg.topic == \"set\") {\n    count = msg.payload;\n} else if (msg.topic == \"decrement\" || msg.topic == \"dec\") {\n    count--;\n} else {\n    //assume increment\n    count++;\n}\ncontext.set(\"count\", count); //store it\nnode.status({ text: count });\n\nmsg._count = count; //pass current count in msg._count\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":725,"y":380,"wires":[[]],"icon":"node-red-dashboard/ui_numeric.png","l":false},{"id":"ce9c22d4.90a37","type":"inject","z":"89aa4a33.4c3098","name":"reset","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"reset","payload":"","payloadType":"str","x":570,"y":380,"wires":[["d1e7267c.8a21e8"]]},{"id":"e2bda53.5e40558","type":"inject","z":"89aa4a33.4c3098","name":"inc","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"str","x":570,"y":420,"wires":[["d1e7267c.8a21e8"]]},{"id":"6cf4ceb6.efbac","type":"inject","z":"89aa4a33.4c3098","name":"dec","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"dec","payload":"","payloadType":"str","x":570,"y":460,"wires":[["d1e7267c.8a21e8"]]},{"id":"a129a75c.b0e598","type":"inject","z":"89aa4a33.4c3098","name":"set 100","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"set","payload":"100","payloadType":"num","x":570,"y":340,"wires":[["d1e7267c.8a21e8"]]}]

Working perfectly, thx for the help!