Trigger: Extend Delay if New Message

This feature doesn't work as I'd expect from the documentation. It does add more time to the currently queued trigger, but not the amount specified in the property. It looks like it adds the amount of time used so far on the the current timer.

Example: Set the trigger to do nothing, then wait for 10 seconds with Extend Delay option checked. If the next message comes 1 second after the first, the total delay will be 11 seconds. If the second message comes 9 seconds after the first, the total delay is 19 seconds. I would expect each subsequent message to add the configured 10 seconds (or msg.delay) to whatever time remained, regardless of when it comes relative to the prior message.

Use Case: I tried to use this feature on a smart relay controlling a bathroom fan. Each push of the button would give 10 minutes of runtime on the fan. So push-push-push would run the fan for 30 minutes. I still only get one output message, as desired, but it only adds about a second or 2 because the subsequent pushes happen so close to the first one.

Any help would be appreciated if I'm misapprehending what this feature is supposed to do.

1 Like

Welcome to the forum @Jimko97

You are right that sending a new message restarts the timer to 10 seconds.
Here is a possible way around this:
image

[{"id":"5e02bbc2aa031dad","type":"inject","z":"db04fd79f3a93d19","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":100,"y":1120,"wires":[["cd6420bb94258882"]]},{"id":"cd6420bb94258882","type":"function","z":"db04fd79f3a93d19","name":"Extend delay","func":"const increment = 2000 // milliseconds?\nconst delay = flow.get(\"delay\") ?? 0\nmsg.delay = delay + increment\nflow.set(\"delay\", msg.delay)\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":250,"y":1120,"wires":[["50a2d2a97101fc33"]]},{"id":"50a2d2a97101fc33","type":"trigger","z":"db04fd79f3a93d19","name":"Trigger","op1":"","op2":"Finished","op1type":"nul","op2type":"str","duration":"250","extend":true,"overrideDelay":true,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":400,"y":1120,"wires":[["4d9ca1c9e7c3249a"]]},{"id":"4d9ca1c9e7c3249a","type":"change","z":"db04fd79f3a93d19","name":"","rules":[{"t":"delete","p":"delay","pt":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":1120,"wires":[["b2031429a0b7651e"]]},{"id":"b2031429a0b7651e","type":"debug","z":"db04fd79f3a93d19","name":"debug 114","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":730,"y":1120,"wires":[]}]

Explanation:
The trigger node can accept a variable delay time as msg.delay. The flow stores the delay as a context variable flow.delay, subsequent injects increase the value.

Note that it's not an ideal solution but should be OK if, as you say, the use is push - push - push and not push - wait 9.5 seconds - push - wait 9.5 seconds - push

Thanks for the tip! I was able to get my flow working as desired with your approach, and all I had to change was to check for isNaN when getting the context variable in case it's not there yet. I can live with the edge cases you noted.

I still think it's weird though. In my mind, extend doesn't mean restart. Would be nice if it could add the increment to whatever time remains on the clock.

You shouldn't need to do that?
The ?? 0 part of const delay = flow.get("delay") ?? 0 provides a default where the context variable does not exist.

I agree with you that the wording is not ideal.
The usual use of the node in this mode is to provide an alert when a regular stream of messages stops arriving. For this purpose, restarting the countdown is the ideal behaviour.

A slightly simpler way to do it would be to use a delay node in rate limit mode to stack up the button presses and release them eg

[{"id":"2a7e7b9904376c43","type":"inject","z":"51335a8bc38f387c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":520,"wires":[["1810e6a885d2a02d"]]},{"id":"1810e6a885d2a02d","type":"delay","z":"51335a8bc38f387c","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"10","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":300,"y":520,"wires":[["ce538d01fc6caa3c"]]},{"id":"ce538d01fc6caa3c","type":"trigger","z":"51335a8bc38f387c","name":"","op1":"iso","op2":"iso","op1type":"date","op2type":"date","duration":"10.1","extend":true,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":470,"y":520,"wires":[["4bab77a352ee5750"]]},{"id":"4bab77a352ee5750","type":"debug","z":"51335a8bc38f387c","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":620,"y":520,"wires":[]}]
3 Likes

That's much better (of course).

I really must stop reaching for functions and context variables!

lol - I never knew about that ?? syntax and assumed you were intending to leave me a // comment to remind me to default to zero but missed the shift key.

In the end, I've had to abandon this approach. The smart relay is properly setting the delay in NR when I push it, but the relay's load is also hard wired to the fan. So it toggles the fan with each push. Oh well. Thanks for your help @jbudd and @dceejay