Resetting a timer with new input

Hi, I'm trying to make a timer using the function node in NodeRED. I've got the basics working, but I'm missing some key functionality that I can't get to work.

This is my flow:
image

I'm injecting number 5 in my function node. The timer starts running and outputs "finished" after 5 seconds. I'm changing the number 5 with a custom number from an input_slider from Home Assistant, so that I'm able to set a light turn off delay in seconds.

My timer will get an input every time my motion sensor detects someone. I'd like to extend the timer with another 5 seconds when that happens. With this timer, the first input results in a turn off call anyway, so it seems that my clearTimeout() function doesn't do its job properly. This is the code I'm using:

var payload = msg.payload;
var MyTimer;

function StopTimer() {
    clearTimeout(MyTimer);
    node.status({fill:"red", shape:"ring", text:' '});
}

function StartTimer() {
    MyTimer = setTimeout(function(){
        node.status({fill:"green", shape:"ring", text:" "});
        msg['payload'] = 'finished';
        node.send(msg);
    }, payload*1000);
}

StopTimer();
StartTimer();
node.status({fill:"blue", shape:"ring", text:' '});

I started with two functions. One to start the timer (StartTimer) and one to reset it (StopTimer). By stopping the previous timer, I'd expect the timer to extend the delay every time it gets input. But it does not.

Could someone help me?

Thanks in advance!

Roy

Have a look at Neil Cherry's MyTimeout Node - it will do what you want in the node rather than resorting to functions

Craig

Assuming msg.payload is an integer coming from HA:

delay = parseInt(msg.payload*1000)
setTimeout(function(){
     msg.payload = 'finished';
    node.send(msg);
}, delay);

That's great! I was looking for such a node. I managed to get it working with the following flow:

[{"id":"b7724cd8.95304","type":"api-call-service","z":"444774fd.bb442c","name":"Overloop uit","server":"8d3f4965.cd7b58","version":1,"debugenabled":true,"service_domain":"homeassistant","service":"turn_off","entityId":"group.verlichting_overloop","data":"","dataType":"json","mergecontext":"","output_location":"payload","output_location_type":"msg","mustacheAltTags":false,"x":2870,"y":1400,"wires":[[]],"inputLabels":["payload.data"]},{"id":"fcdeba97.bcb1a8","type":"api-current-state","z":"444774fd.bb442c","name":"Vertraging slapen?","server":"8d3f4965.cd7b58","version":1,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"input_number.verlichting_overloop_slapen_vertraging","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":1910,"y":1440,"wires":[["44f43ad.c7904c4","6132da91.8eed04"]]},{"id":"5f18fdb8.1f3524","type":"api-current-state","z":"444774fd.bb442c","name":"Vertraging thuis?","server":"8d3f4965.cd7b58","version":1,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"input_number.verlichting_overloop_thuis_vertraging","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":1910,"y":1360,"wires":[["44f43ad.c7904c4","81e2632c.6be0b"]]},{"id":"44f43ad.c7904c4","type":"change","z":"444774fd.bb442c","name":"Cancel timer","rules":[{"t":"set","p":"payload","pt":"msg","to":"cancel","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":2130,"y":1400,"wires":[["2c26ad51.639d02"]]},{"id":"2c26ad51.639d02","type":"mytimeout","z":"444774fd.bb442c","name":"Timer","outtopic":"","outsafe":"","outwarning":"","outunsafe":"stop","warning":"0","timer":"600","debug":false,"ndebug":false,"ignoreCase":false,"repeat":false,"again":false,"x":2690,"y":1400,"wires":[["b7724cd8.95304"],[]]},{"id":"81e2632c.6be0b","type":"delay","z":"444774fd.bb442c","name":"","pauseType":"delay","timeout":"10","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":2130,"y":1360,"wires":[["4eb16cc8.dfdc64"]]},{"id":"6132da91.8eed04","type":"delay","z":"444774fd.bb442c","name":"","pauseType":"delay","timeout":"10","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":2130,"y":1440,"wires":[["4eb16cc8.dfdc64"]]},{"id":"ae164646.58d598","type":"template","z":"444774fd.bb442c","name":"","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"{\"payload\":\"on\",\"timeout\":{{payload}},\"warning\":0}","output":"str","x":2520,"y":1360,"wires":[["2c26ad51.639d02"]]},{"id":"4eb16cc8.dfdc64","type":"function","z":"444774fd.bb442c","name":"Convert time","func":"var time = msg.payload*60;\nmsg['payload'] = time;\nnode.send(msg);\n    ","outputs":1,"noerr":0,"x":2330,"y":1360,"wires":[["ae164646.58d598"]]},{"id":"8d3f4965.cd7b58","type":"server","z":"","name":"Home Assistant","legacy":false,"hassio":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true}]

Thanks a lot!

no worries - glad to help - Neil is a frequent visitor on here - throw out a thanks to him as well

Craig

@ncherry Thank you! :smiley:

Your Welcome (thanks Colin) :blush:

Was looking how to do this via function. Was able to achieve it by utilizing flow variable (or global, up to u).
Basically, OP's code is spot on. It is just that he did not save the variable into flow context. Therefore a new variable is created everytime the function is called.

[{"id":"4810cf31.a718e","type":"inject","z":"da9fb98c.8e03e8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":180,"wires":[["6b496c59.2ac0ec"]]},{"id":"6b496c59.2ac0ec","type":"change","z":"da9fb98c.8e03e8","name":"Set isDetecting","rules":[{"t":"set","p":"isDetecting","pt":"flow","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":180,"wires":[["c728974e.101138"]]},{"id":"dbfd5f7d.ade148","type":"change","z":"da9fb98c.8e03e8","name":"Set isDetecting","rules":[{"t":"set","p":"isDetecting","pt":"flow","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":360,"wires":[["4546c516.834d1c"]]},{"id":"4546c516.834d1c","type":"debug","z":"da9fb98c.8e03e8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":360,"y":420,"wires":[]},{"id":"c728974e.101138","type":"function","z":"da9fb98c.8e03e8","name":"","func":"var MyTimer = flow.get('detectTimer');\n\nfunction StopTimer() {\n    clearTimeout(MyTimer);\n}\n\nfunction StartTimer() {\n    MyTimer = setTimeout(function(){\n        msg['payload'] = 'finished';\n        node.send(msg);\n    }, 5000);\n    flow.set(\"detectTimer\", MyTimer)\n}\n\nStopTimer();\nStartTimer();","outputs":1,"noerr":0,"initialize":"","finalize":"","x":370,"y":280,"wires":[["dbfd5f7d.ade148"]]}]