Can I have a delay / sleep inside Function node

I'm pretty certain that the answer is going to be no but can I do something in a function node - wait a bit - do something else?

or do I need to have two function nodes with a Delay node in-between them?

Have a look at the setTimeout() Method.

https://www.w3schools.com/jsref/met_win_settimeout.asp

Thanks

I tried that out using this - it nearly worked - there was a 3 sec delay between status colours but no msg was delivered to the output

setTimeout(function(){
    node.status({fill:"red", shape:"ring", text:" "});
    msg['payload'] = 'finished';
    return msg;
}, 3000);
node.status({fill:"blue", shape:"ring", text:' '});

Replace return msg; by node.send(msg);

2 Likes

That worked perfectly :slight_smile:

setTimeout(function(){
    node.status({fill:"red", shape:"ring", text:" "});
    msg['payload'] = 'finished';
    node.send(msg);
}, 3000);
node.status({fill:"blue", shape:"ring", text:' '});

JFI - I'd come up with this before I read your suggestion - but yours is much simpler :slight_smile:

1 Like

@cflurin JFI - I was trying to get a wait/sleep inside a Blockly node - so your help has led me on this current method of doing so - thanks again :slight_smile:

image

As usual there are more than one solution. If you anyway need a function, that makes sense otherwise I would use the core-nodes or if appropriate a contrib-node.

Good morning.
I'm writing a script to automate the window's blinds and I'm looking for a little sleep in case the user maneuver the front end slider commanding an quick inversion of direction.
The main function node checks the slider status and acts as requested. In case of direction inversion I want do nicely control adding a pause (maybe 100ms).
Could you give me an idea regarding the programming structure of function (or not function) needed nodes?
If you find useful I can send the JSON script (btw I doubt it can help since it's complicate, but of course I'm glad to do that).
Many thanks and best regards, Sergio

To insert a delay inside a function node you can use the javascript setTimeout() function. However it can be tricky to get right and since you had to ask how to do it then you could find it problematic. An alternative is to send a message from your node, put that through a Delay node and then have another node that completes the operation.

BlindSlider_01.txt (9.1 KB)

Hi Colin, thank you, The delay is not my favourite, but it is viable.
Attached the JSON script. I'd like to add a sleep in a IF branch of "Compute" function node ... if you think it is doable.
Additionally I'd like to know (but I might need to open an other thread howto rearrange the architecture to use a callback strategy that i think feets perfectly in this example (async node does not work for me: the "function" edit box is not editable ... I also setup an other RPi from scratch, but same result)
Thank you a lot

The only way of doing it in a function node is to use setTimeout(). You said async (which is what setTimeout is) does not work for you, which is precisely what I said about it being tricky to get right.
If you want to post a flow then paste it here, put a line containing three backtick characters before it and another after. That is better than attaching a file.
I have had a look at your flow and it looks horribly complex. Can you not achieve it by the technique I suggested rather than looping back round, which can be very difficult to get right? So take an output from the first node, delay it and then have another node that does whatever is necessary after the delay.

[{"id":"31a2dd89.3ba412","type":"tab","label":"Flow 6 slider","disabled":false,"info":""},{"id":"1f3592c8.9719bd","type":"inject","z":"31a2dd89.3ba412","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":300,"y":290,"wires":[["9881b989.c06f78"]]},{"id":"9881b989.c06f78","type":"function","z":"31a2dd89.3ba412","name":"Init","func":"// \"msg.payload\" init slider node\nmsg.payload = 0;\n// msg not propagated by slider so \"topic\" is not useful\nmsg.topic = \"sliderInit\";\nvar UnoStates = {Slider:0,Direction:\"UP\",Quiet:true, Increment:-1, wipeOff:false };\nvar UnoCounters = {Interval:0, IntShort:0, CntLimit:28001}; // 26000 misurato\nflow.set(\"UnoStates\",UnoStates);\nflow.set(\"UnoCounters\",UnoCounters);\nreturn msg;","outputs":1,"noerr":0,"x":330,"y":350,"wires":[["14eb8869.be3868"]]},{"id":"34bc84df.85a25c","type":"rpi-gpio out","z":"31a2dd89.3ba412","name":"","pin":"32","set":true,"level":"1","freq":"","out":"out","x":1240,"y":350,"wires":[],"inputLabels":["Window#1"]},{"id":"55dbb258.8692fc","type":"rpi-gpio out","z":"31a2dd89.3ba412","name":"","pin":"36","set":true,"level":"1","freq":"","out":"out","x":1240,"y":398,"wires":[],"inputLabels":["Window#1"]},{"id":"14eb8869.be3868","type":"ui_slider","z":"31a2dd89.3ba412","name":"","label":"TappaUNO","group":"deb628f5.33b0e8","order":0,"width":"7","height":"1","passthru":false,"topic":"slider","min":0,"max":"28","step":"4","x":530,"y":350,"wires":[["f66a2cc8.84a3b"]]},{"id":"f66a2cc8.84a3b","type":"function","z":"31a2dd89.3ba412","name":"Compute","func":"msg111={};\nmsg112={};\nmsg113={};\nmsg114={};\nvar UnoStates = flow.get(\"UnoStates\");\nvar UnoCounters = flow.get(\"UnoCounters\");\n// input messages topics could be \"slider\" or \"lBackTimerShort\"\nswitch (msg.topic)\n{\n    case \"slider\":\n// blind already rolling?\n        if (UnoStates.Quiet === true) {\n// blind is quiet - new slider setup will open or close?\n            if(UnoStates.Slider < msg.payload){\n                UnoCounters.Interval = (msg.payload - UnoStates.Slider) * 1000;\n// just 100ms before time out expiration - check for slider input reached meanwhile \n                UnoCounters.IntShort = UnoCounters.Interval - 100 ;\n                UnoStates.Slider = msg.payload;\n                UnoStates.Direction = \"UP\";\n                UnoStates.Quiet = false;\n                msg111.delay = UnoCounters.IntShort;\n                msg112.delay = UnoCounters.Interval;\n                msg113.payload = 0;\n                msg114.payload = 1;\n                flow.set(\"UnoStates\",UnoStates);\n                flow.set(\"UnoCounters\",UnoCounters);\n                return [ msg111, msg112, msg113, msg114 ];\n// blind will move DOWN/close\n            }else if(UnoStates.Slider > msg.payload){\n                UnoCounters.Interval = (UnoStates.Slider - msg.payload) * 1000;\n                UnoCounters.IntShort = UnoCounters.Interval - 100 ;\n                UnoStates.Slider = msg.payload;\n                UnoStates.Direction = \"DOWN\";\n                UnoStates.Quiet = false;\n                msg111.delay = UnoCounters.IntShort;\n                msg112.delay = UnoCounters.Interval;\n                msg113.payload = 1;\n                msg114.payload = 0;\n                flow.set(\"UnoStates\",UnoStates);\n                flow.set(\"UnoCounters\",UnoCounters);\n                return [ msg111, msg112, msg113, msg114 ];\n            }else{\n// slider moved up+down => setup didn't change - shouldn't happen if blind is quiet \n                flow.set(\"UnoStates\",UnoStates);\n                flow.set(\"UnoCounters\",UnoCounters);\n                return [ null, null, null, null ];\n            }\n        }else { \n// new slider setup  received while blind's moving => set buffer \"Increment\" \n            UnoStates.Increment = msg.payload;\n            flow.set(\"UnoStates\",UnoStates);\n            flow.set(\"UnoCounters\",UnoCounters);\n            return [ null, null, null, null ];\n        }            \n        break;\n// case \"lBackTimerShort\" save Increment buffer and behaves as above\n    case \"lBackTimerShort\": \n        if (UnoStates.Increment !== -1){\n            msg.payload = UnoStates.Increment;\n            UnoStates.Increment = -1;\n// followng block is identical as above in case \"slider\"\n            if(UnoStates.Slider < msg.payload){\n                UnoCounters.Interval = (msg.payload - UnoStates.Slider) * 1000;\n                UnoCounters.IntShort = UnoCounters.Interval - 100 ;\n                UnoStates.Slider = msg.payload;\n                UnoStates.Direction = \"UP\";\n                UnoStates.Quiet = false;\n                msg111.delay = UnoCounters.IntShort;\n                msg112.delay = UnoCounters.Interval;\n                msg113.payload = 0;\n                msg114.payload = 1;\n                flow.set(\"UnoStates\",UnoStates);\n                flow.set(\"UnoCounters\",UnoCounters);\n                return [ msg111, msg112, msg113, msg114 ];\n            }else if(UnoStates.Slider > msg.payload){\n                UnoCounters.Interval = (UnoStates.Slider - msg.payload) * 1000;\n                UnoCounters.IntShort = UnoCounters.Interval - 100 ;\n                UnoStates.Slider = msg.payload;\n                UnoStates.Direction = \"DOWN\";\n                UnoStates.Quiet = false;\n                msg111.delay = UnoCounters.IntShort;\n                msg112.delay = UnoCounters.Interval;\n                msg113.payload = 1;\n                msg114.payload = 0;\n                flow.set(\"UnoStates\",UnoStates);\n                flow.set(\"UnoCounters\",UnoCounters);\n                return [ msg111, msg112, msg113, msg114 ];\n            }else{\n// \"triggerGPIO\" function will manage \n                UnoStates.wipeOff = true;\n                flow.set(\"UnoStates\",UnoStates);\n                flow.set(\"UnoCounters\",UnoCounters);\n//                msg113.payload = 1;\n//                msg114.payload = 0;\n                return [ null, null, null, null ];\n            }\n        }else{\n// \"triggerGPIO\" function will manage \n            UnoStates.wipeOff = true;\n            flow.set(\"UnoStates\",UnoStates);\n            flow.set(\"UnoCounters\",UnoCounters);\n        }    \n    break;\n}\n\n// setTimeout(() => resolve(node.Send ??), 100);\n","outputs":4,"noerr":0,"x":696,"y":350,"wires":[["245d15cc.0c945a"],["7f03ac5a.079554"],["34bc84df.85a25c"],["55dbb258.8692fc"]]},{"id":"7f03ac5a.079554","type":"delay","z":"31a2dd89.3ba412","name":"interval","pauseType":"delayv","timeout":"5","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":870,"y":322,"wires":[["e62f1972.182268"]]},{"id":"e62f1972.182268","type":"function","z":"31a2dd89.3ba412","name":"triggerGPIO","func":"msg121={};\nmsg122={};\nvar UnoStates = flow.get(\"UnoStates\");\nvar UnoCounters = flow.get(\"UnoCounters\");\n// check if the message has been issued by the delay node\nif (msg.delay) {\n// if property wipeOff no incremenal (or === 0) have been reached - re-init buffers \n    if (UnoStates.wipeOff === true) {\n        UnoStates.Concur = false;\n        UnoStates.Quiet = true;\n        UnoStates.wipeOff = false;\n        msg121.payload = 1;\n        msg122.payload = 1;\n        return [ msg121, msg122];\n// bew command from slider => under control of \"lBackTimerShort\" branch \n    }else{\n        return [ null, null];\n    }\n}else{\n// messages receives without 'delay' property are useless\n    return [ null, null];\n}","outputs":2,"noerr":0,"x":1030,"y":323,"wires":[["34bc84df.85a25c"],["55dbb258.8692fc"]]},{"id":"245d15cc.0c945a","type":"delay","z":"31a2dd89.3ba412","name":"intShort","pauseType":"delayv","timeout":"5","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":868,"y":275,"wires":[["cb25ccc5.bf53b"]]},{"id":"cb25ccc5.bf53b","type":"function","z":"31a2dd89.3ba412","name":"CheckConcurr","func":"// add topic to allow \"Compute\" node to select different input \nmsg.topic = \"lBackTimerShort\";\nif (msg.delay){\n    return msg;\n}else{\n    return null;\n}","outputs":1,"noerr":0,"x":690,"y":190,"wires":[["935c4515.4e6478"]]},{"id":"935c4515.4e6478","type":"change","z":"31a2dd89.3ba412","name":"","rules":[{"t":"delete","p":"delay","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":290,"wires":[["f66a2cc8.84a3b"]]},{"id":"deb628f5.33b0e8","type":"ui_group","z":"","name":"Window#11","tab":"7e3910f.9132af","disp":true,"width":"7","collapse":false},{"id":"7e3910f.9132af","type":"ui_tab","z":"","name":"Shutter#1","icon":"dashboard"}]
`

Hi. I posted the code as per your suggestion.
That code works, but I'm definitely looking for a better implementation. I think the callback (and similar constructs) would be the best, because the slider input works asynchronously: the slider iterates every single step between initial and final ones ("initial" and "final" are according to user input). Therefore new input arrives meanwhile the code is executing the former.
Additionally (but this is optional) I do not want the code starts and stops the motor between every single step since that flow might damage it. BTW that the reason why I'm looking for a 100ms sleep between two input forcing seamlessly a direction change (a direction change cannot be seamless!).
I have already coded a solution that replicates the physical button with a gauge that allow for operating from remotely. It's simpler but less intuitive since the user has to predict the final step (feed forward model).
I'm now coding a simpler solution that implements the slider but with a less efficient sequence.
Since I think the asynch model renders much better the reality (different environment integration), to create a template for future implementations, I am looking for "cleaner" solution for the code I just posted.

many thanks & best regards

THis is a perfect case for a DSM - refer to this one

Search for posts by the author of the node on discourse - he has previously provided examples to show the implementation details

Craig

FYI. The latest version of the dashboard slider widget has an option to only send the value when you release the control, so only one value gets sent.

The other option is to look at the trigger node, set to send nothing on first output, extend if more inputs arrive, then send last input after a short delay.

Hi Craig, I enjoyed your tip.
My impression: the DSM node behavior is mostly determined by methods rather than current state. isn't it?
Here the flow to operate a blind with DSM node. I've used only "timeout" function (that works as a callback). So far I could not find useful the version with "timer" method.
I'm wondering howto use "timer" method since I couldn't group statements. I just tries with the "do" construct that accepts only one statement. Therefore I was only able to operate a "resume" redirecting to an other method. Do you have any tips here? Please, let me know if an additional flow could be useful to give you a better idea.

Compare to former flow (w/o DSM node) this one results simpler but I had to cancel the "seamless" feature. Therefore if the user moves the slider in several steps (same direction) then several glitches will affect the motor.
I could mitigate this issue setting "only on release" the "Output" parameter of the slider node (this point answers to Colin as well)
I want to report a possible bug on slider node:
selecting option "If msg arrives on input, pass through to output:" I could detect the slider node output only if I inject the payload type "flow" or "global". But only a number type will initialize the slider node as desired. Unfortunately I do not detect the output for remaining types. Or only randomly if I select the payload type "number". Have I missed something? or just jumped into a bug?

Question: is it possible to get the value of a running "timeout" function? Same question for the "timer" method.

To mitigate the sudden sliding inversion I introduced a 250ms pause.

Ciao

[{"id":"bc4a0c48.3ac56","type":"dsm","z":"10258155.fcd03f","name":"BlindControl","sm_config":"{\n    \"stateOutput\": \"state\",\n    \"currentState\": \"onHalt\",\n    \"states\": {\n        \"onHalt\": {\n            \"power\": \"active\"\n        },\n        \"active\": {\n            \"complRunAndCheck\": \"onHalt\"\n        }\n    },\n    \"data\": {\n        \"temp\": 0,\n        \"current\": 0,\n        \"UP\": 1,\n        \"DOWN\": 1,\n        \"runTime\": 0\n    },\n    \"methods\": {\n        \"temp\": {\n            \"name\": \"setData\"\n        },\n        \"current\": {\n            \"name\": \"setData\"\n        },\n        \"UP\": {\n            \"name\": \"setData\"\n        },\n        \"DOWN\": {\n            \"name\": \"setData\"\n        },\n        \"runTime\": {\n            \"name\": \"setData\"\n        },\n        \"setPoint\": [\n            \"sm.data.temp = msg.payload;\",\n            \"if (sm.currentState === 'active') {\",\n            \"   output = false;\",\n            \"} else {\",            \n            \"   if (msg.payload > sm.data.current) {\",\n            \"       sm.data.UP = 0 ;\",\n            \"       sm.data.DOWN = 1 ;\",\n            \"       sm.direction = 1 ;\",\n            \"       sm.data.runTime = msg.payload - sm.data.current;\",\n            \"       sm.data.current = msg.payload;\",\n            \"       sm.fill = 'green';\",\n            \"       sm.text = 'activeLift';\",\n            \"       resume('power', msg);\",\n            \"       output = true;\",\n            \"   } else if (msg.payload < sm.data.current) {\",\n            \"       sm.data.UP = 1 ;\",\n            \"       sm.data.DOWN = 0 ;\",\n            \"       sm.direction = -1 ;\",\n            \"       sm.data.runTime = sm.data.current - msg.payload;\",\n            \"       sm.data.current = msg.payload;\",\n            \"       sm.fill = 'red';\",\n            \"       sm.text = 'activeLower';\",\n            \"       resume('power', msg);\",\n            \"       output = true;\",\n            \"   } else { \",\n            \"       sm.data.UP = 1 ;\",\n            \"       sm.data.DOWN = 1 ;\",\n            \"       output = true;\",\n            \"   } \",\n            \"} \"\n        ],\n        \"power\": [\n            \"timeout.endRum = setTimeout(function() {\",\n            \"   sm.data.UP = 1;\",\n            \"   sm.data.DOWN = 1;\",\n            \"   sm.fill = 'grey';\",\n            \"   sm.text = 'onHalt';\",\n            \"   resume('complRunAndCheck', msg);\",\n            \"}, sm.data.runTime);\",\n            \"output = false;\"\n            ],\n        \"complRunAndCheck\": [\n            \"if (sm.data.temp < sm.data.current && sm.direction === 1 || sm.data.temp > sm.data.current && sm.direction === -1) {\",\n            \"   timeout.changeDir = setTimeout(function() {\",\n            \"   msg.payload = sm.data.temp;\",\n            \"   resume('setPoint', msg);\",\n            \"   output = false;\",\n            \"   }, 250);\",\n            \"} else if (sm.data.temp != sm.data.current) {\",\n            \"   msg.payload = sm.data.temp;\",\n            \"   resume('setPoint', msg);\",\n            \"   output = false;\",\n            \"} else {\",\n            \"}\"\n            ],\n        \"status\": {\n            \"fill\": {\n                \"get\": \"sm.fill\"\n            },\n            \"shape\": \"dot\",\n            \"text\": {\n                \"get\": \"sm.text\"\n            }\n        }\n    }\n}","x":730,"y":200,"wires":[["667a7c2b.da8254"]]},{"id":"50c67c46.c3ce24","type":"ui_slider","z":"10258155.fcd03f","name":"BlindHeightWidget","label":"{{ value }}","group":"deb628f5.33b0e8","order":1,"width":"6","height":"1","passthru":false,"topic":"setPoint","min":"0","max":"10","step":"1","x":320,"y":200,"wires":[["8f71e891.402e58"]],"outputLabels":["setpoint"]},{"id":"e5865eac.1d9f4","type":"inject","z":"10258155.fcd03f","name":"init","topic":"setPoint","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":260,"wires":[["50c67c46.c3ce24","8a96a614.b89518","8f71e891.402e58"]]},{"id":"8a96a614.b89518","type":"function","z":"10258155.fcd03f","name":"BlindProfile","func":"msg1={};\nmsg2={};\nmsg3={};\nmsg4={};\nmsg5={};\n// var unoProfile = { step:0, max:0 };\nmsg1.topic = \"temp\";\nmsg1.payload = 0;\nmsg2.topic = \"current\";\nmsg2.payload = 0;\nmsg3.topic = \"UP\";\nmsg3.payload = 1;\nmsg3.topic = \"DOWN\";\nmsg3.payload = 1;\nmsg2.topic = \"runTime\";\nmsg2.payload = 0;\nreturn [ msg1, msg2, msg3, msg4, msg5];","outputs":5,"noerr":0,"x":507,"y":260,"wires":[["bc4a0c48.3ac56"],["bc4a0c48.3ac56"],["bc4a0c48.3ac56"],["bc4a0c48.3ac56"],["bc4a0c48.3ac56"]]},{"id":"667a7c2b.da8254","type":"function","z":"10258155.fcd03f","name":"RpiPinDist","func":"msg1={};\nmsg2={};\nmsg1.payload = msg.data.UP;\nmsg2.payload = msg.data.DOWN;\nreturn [ msg1, msg2 ];","outputs":2,"noerr":0,"x":741,"y":280,"wires":[["a826b719.7a8d08"],["8b800e81.bb303"]]},{"id":"a826b719.7a8d08","type":"rpi-gpio out","z":"10258155.fcd03f","name":"","pin":"32","set":true,"level":"1","freq":"","out":"out","x":922,"y":234,"wires":[],"inputLabels":["Window#1"]},{"id":"8b800e81.bb303","type":"rpi-gpio out","z":"10258155.fcd03f","name":"","pin":"36","set":true,"level":"1","freq":"","out":"out","x":930,"y":280,"wires":[],"inputLabels":["Window#1"]},{"id":"8f71e891.402e58","type":"function","z":"10258155.fcd03f","name":"adaptBlindOne","func":"const MAX = 27000\nmsg.payload = msg.payload*MAX/10;\nreturn msg;","outputs":1,"noerr":0,"x":510,"y":100,"wires":[["bc4a0c48.3ac56"]]},{"id":"deb628f5.33b0e8","type":"ui_group","z":"","name":"GO-UNO","tab":"7e3910f.9132af","disp":true,"width":"6","collapse":false},{"id":"7e3910f.9132af","type":"ui_tab","z":"","name":"TheBridgeBlinds","icon":"dashboard"}]
`

Hi again, this flow reduces the risk to let the user changes by mistake the slider setting.
I did not find out howto dim/disable the widget. Does NodeRed allow for that?
I could not be able to hide the single widget but the whole group. Is it possible?
Additionally the web page mixes up every time the text replaces the slider. Does NodeRed allow for a better front end display? How?
thx/ciao, s.

[{"id":"1124b68a.7a4729","type":"change","z":"667bf9ae.4b2b98","name":"SliderMgnt","rules":[{"t":"change","p":"payload","pt":"msg","from":"display","fromt":"str","to":"{\"group\":{\"show\":[\"TheBridgeBlinds_GO-ONE\"]}}","tot":"json"},{"t":"change","p":"payload","pt":"msg","from":"hide","fromt":"str","to":"{\"group\":{\"hide\":[\"TheBridgeBlinds_GO-ONE\"]}}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":810,"y":340,"wires":[["105fdd39.e87d93"]]},{"id":"4a4a64cb.a7e85c","type":"change","z":"667bf9ae.4b2b98","name":"MsgMgnt","rules":[{"t":"change","p":"payload","pt":"msg","from":"display","fromt":"str","to":"{\"group\":{\"show\":[\"TheBridgeBlinds_Msg1\"]}}","tot":"json"},{"t":"change","p":"payload","pt":"msg","from":"hide","fromt":"str","to":"{\"group\":{\"hide\":[\"TheBridgeBlinds_Msg1\"]}}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":800,"y":300,"wires":[["105fdd39.e87d93"]]},{"id":"105fdd39.e87d93","type":"ui_ui_control","z":"667bf9ae.4b2b98","name":"","x":980,"y":300,"wires":[[]]},{"id":"aabdc9bc.4ad2d8","type":"ui_text","z":"667bf9ae.4b2b98","group":"de26add4.024cf","order":0,"width":"6","height":"2","name":"","label":"WORKING !!!!","format":"Wait Please","layout":"col-center","x":377,"y":222,"wires":[]},{"id":"a86217f1.1dca08","type":"dsm","z":"667bf9ae.4b2b98","name":"BlindControl","sm_config":"{\n    \"stateOutput\": \"state\",\n    \"currentState\": \"onHalt\",\n    \"states\": {\n        \"onHalt\": {\n            \"power\": \"active\"\n        },\n        \"active\": {\n            \"complRunAndCheck\": \"onHalt\"\n        }\n    },\n    \"data\": {\n        \"temp\": 0,\n        \"current\": 0,\n        \"UP\": 1,\n        \"DOWN\": 1,\n        \"runTime\": 0\n    },\n    \"methods\": {\n        \"temp\": {\n            \"name\": \"setData\"\n        },\n        \"current\": {\n            \"name\": \"setData\"\n        },\n        \"UP\": {\n            \"name\": \"setData\"\n        },\n        \"DOWN\": {\n            \"name\": \"setData\"\n        },\n        \"runTime\": {\n            \"name\": \"setData\"\n        },\n        \"setPoint\": [\n            \"sm.data.temp = msg.payload;\",\n            \"if (sm.currentState === 'active') {\",\n            \"   output = false;\",\n            \"} else {\",            \n            \"   if (msg.payload > sm.data.current) {\",\n            \"       sm.data.UP = 0 ;\",\n            \"       sm.data.DOWN = 1 ;\",\n            \"       sm.direction = 1 ;\",\n            \"       sm.data.runTime = msg.payload - sm.data.current;\",\n            \"       sm.data.current = msg.payload;\",\n            \"       sm.fill = 'green';\",\n            \"       sm.text = 'activeLift';\",\n            \"       resume('power', msg);\",\n            \"       output = true;\",\n            \"   } else if (msg.payload < sm.data.current) {\",\n            \"       sm.data.UP = 1 ;\",\n            \"       sm.data.DOWN = 0 ;\",\n            \"       sm.direction = -1 ;\",\n            \"       sm.data.runTime = sm.data.current - msg.payload;\",\n            \"       sm.data.current = msg.payload;\",\n            \"       sm.fill = 'red';\",\n            \"       sm.text = 'activeLower';\",\n            \"       resume('power', msg);\",\n            \"       output = true;\",\n            \"   } else { \",\n            \"       sm.data.UP = 1 ;\",\n            \"       sm.data.DOWN = 1 ;\",\n            \"       output = true;\",\n            \"   } \",\n            \"} \"\n        ],\n        \"power\": [\n            \"timeout.endRum = setTimeout(function() {\",\n            \"   sm.data.UP = 1;\",\n            \"   sm.data.DOWN = 1;\",\n            \"   sm.fill = 'grey';\",\n            \"   sm.text = 'onHalt';\",\n            \"   resume('complRunAndCheck', msg);\",\n            \"}, sm.data.runTime);\",\n            \"output = false;\"\n            ],\n        \"complRunAndCheck\": [\n            \"if (sm.data.temp < sm.data.current && sm.direction === 1 || sm.data.temp > sm.data.current && sm.direction === -1) {\",\n            \"   timeout.changeDir = setTimeout(function() {\",\n            \"   msg.payload = sm.data.temp;\",\n            \"   resume('setPoint', msg);\",\n            \"   output = false;\",\n            \"   }, 150);\",\n            \"} else if (sm.data.temp != sm.data.current) {\",\n            \"   msg.payload = sm.data.temp;\",\n            \"   resume('setPoint', msg);\",\n            \"   output = false;\",\n            \"} else {\",\n            \"}\"\n            ],\n        \"status\": {\n            \"fill\": {\n                \"get\": \"sm.fill\"\n            },\n            \"shape\": \"dot\",\n            \"text\": {\n                \"get\": \"sm.text\"\n            }\n        }\n    }\n}","x":636,"y":205,"wires":[["8fa3535.0cd5db"]]},{"id":"2c8e9696.8d47ea","type":"inject","z":"667bf9ae.4b2b98","name":"init","topic":"setPoint","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":166,"y":172,"wires":[["7f1473c1.29567c","8b756896.072b78","c048381b.7710a8"]]},{"id":"7f1473c1.29567c","type":"function","z":"667bf9ae.4b2b98","name":"BlindProfile","func":"msg1={};\nmsg2={};\nmsg3={};\nmsg4={};\nmsg5={};\n// var unoProfile = { step:0, max:0 };\nmsg1.topic = \"temp\";\nmsg1.payload = 0;\nmsg2.topic = \"current\";\nmsg2.payload = 0;\nmsg3.topic = \"UP\";\nmsg3.payload = 1;\nmsg3.topic = \"DOWN\";\nmsg3.payload = 1;\nmsg2.topic = \"runTime\";\nmsg2.payload = 0;\nreturn [ msg1, msg2, msg3, msg4, msg5];","outputs":5,"noerr":0,"x":346,"y":292,"wires":[["a86217f1.1dca08"],["a86217f1.1dca08"],["a86217f1.1dca08"],["a86217f1.1dca08"],["a86217f1.1dca08"]]},{"id":"8fa3535.0cd5db","type":"function","z":"667bf9ae.4b2b98","name":"RpiPinDist","func":"msg1={};\nmsg2={};\nmsg3={};\nmsg4={};\nmsg1.payload = msg.data.UP;\nmsg2.payload = msg.data.DOWN;\nif (msg.data.UP && msg.data.DOWN) {\n    msg3.payload = \"hide\";\n    msg4.payload = \"display\";\n} else {\n    msg3.payload = \"display\";\n    msg4.payload = \"hide\";\n}\nreturn [ msg1, msg2, msg3, msg4 ];","outputs":4,"noerr":0,"x":626,"y":292,"wires":[["afcb2b93.4a87a8"],["69c22286.a3d2ec"],["4a4a64cb.a7e85c"],["1124b68a.7a4729"]]},{"id":"afcb2b93.4a87a8","type":"rpi-gpio out","z":"667bf9ae.4b2b98","name":"","pin":"32","set":true,"level":"1","freq":"","out":"out","x":896,"y":184,"wires":[],"inputLabels":["Window#1"]},{"id":"69c22286.a3d2ec","type":"rpi-gpio out","z":"667bf9ae.4b2b98","name":"","pin":"36","set":true,"level":"1","freq":"","out":"out","x":896,"y":232,"wires":[],"inputLabels":["Window#1"]},{"id":"c048381b.7710a8","type":"function","z":"667bf9ae.4b2b98","name":"adaptBlindOne","func":"const MAX = 27000\nmsg.payload = msg.payload*MAX/10;\nreturn msg;","outputs":1,"noerr":0,"x":516,"y":52,"wires":[["a86217f1.1dca08"]]},{"id":"8b756896.072b78","type":"ui_slider","z":"667bf9ae.4b2b98","name":"BlindHeightWidget","label":"{{ value }}","group":"26bd3a6a.d77a26","order":1,"width":"6","height":"1","passthru":true,"outs":"end","topic":"setPoint","min":0,"max":"10","step":"1","x":382,"y":172,"wires":[["c048381b.7710a8"]],"outputLabels":["setpoint"]},{"id":"4bd10fef.81206","type":"change","z":"667bf9ae.4b2b98","name":"SliderMgnt","rules":[{"t":"change","p":"payload","pt":"msg","from":"display","fromt":"str","to":"{\"group\":{\"show\":[\"TheBridgeBlinds_GO-TWO\"]}}","tot":"json"},{"t":"change","p":"payload","pt":"msg","from":"hide","fromt":"str","to":"{\"group\":{\"hide\":[\"TheBridgeBlinds_GO-TWO\"]}}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":810,"y":694,"wires":[["ddd67ff8.d8d39"]]},{"id":"2f28d9c2.ab69c6","type":"change","z":"667bf9ae.4b2b98","name":"MsgMgnt","rules":[{"t":"change","p":"payload","pt":"msg","from":"display","fromt":"str","to":"{\"group\":{\"show\":[\"TheBridgeBlinds_Msg2\"]}}","tot":"json"},{"t":"change","p":"payload","pt":"msg","from":"hide","fromt":"str","to":"{\"group\":{\"hide\":[\"TheBridgeBlinds_Msg2\"]}}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":800,"y":654,"wires":[["ddd67ff8.d8d39"]]},{"id":"ddd67ff8.d8d39","type":"ui_ui_control","z":"667bf9ae.4b2b98","name":"","x":980,"y":654,"wires":[[]]},{"id":"bed307df.167808","type":"ui_text","z":"667bf9ae.4b2b98","group":"91c8f5ad.bc1668","order":0,"width":"6","height":"2","name":"","label":"WORKING !!!!","format":"Wait Please","layout":"col-center","x":377,"y":576,"wires":[]},{"id":"61b44efc.4e5b","type":"dsm","z":"667bf9ae.4b2b98","name":"BlindControl","sm_config":"{\n    \"stateOutput\": \"state\",\n    \"currentState\": \"onHalt\",\n    \"states\": {\n        \"onHalt\": {\n            \"power\": \"active\"\n        },\n        \"active\": {\n            \"complRunAndCheck\": \"onHalt\"\n        }\n    },\n    \"data\": {\n        \"temp\": 0,\n        \"current\": 0,\n        \"UP\": 1,\n        \"DOWN\": 1,\n        \"runTime\": 0\n    },\n    \"methods\": {\n        \"temp\": {\n            \"name\": \"setData\"\n        },\n        \"current\": {\n            \"name\": \"setData\"\n        },\n        \"UP\": {\n            \"name\": \"setData\"\n        },\n        \"DOWN\": {\n            \"name\": \"setData\"\n        },\n        \"runTime\": {\n            \"name\": \"setData\"\n        },\n        \"setPoint\": [\n            \"sm.data.temp = msg.payload;\",\n            \"if (sm.currentState === 'active') {\",\n            \"   output = false;\",\n            \"} else {\",            \n            \"   if (msg.payload > sm.data.current) {\",\n            \"       sm.data.UP = 0 ;\",\n            \"       sm.data.DOWN = 1 ;\",\n            \"       sm.direction = 1 ;\",\n            \"       sm.data.runTime = msg.payload - sm.data.current;\",\n            \"       sm.data.current = msg.payload;\",\n            \"       sm.fill = 'green';\",\n            \"       sm.text = 'activeLift';\",\n            \"       resume('power', msg);\",\n            \"       output = true;\",\n            \"   } else if (msg.payload < sm.data.current) {\",\n            \"       sm.data.UP = 1 ;\",\n            \"       sm.data.DOWN = 0 ;\",\n            \"       sm.direction = -1 ;\",\n            \"       sm.data.runTime = sm.data.current - msg.payload;\",\n            \"       sm.data.current = msg.payload;\",\n            \"       sm.fill = 'red';\",\n            \"       sm.text = 'activeLower';\",\n            \"       resume('power', msg);\",\n            \"       output = true;\",\n            \"   } else { \",\n            \"       sm.data.UP = 1 ;\",\n            \"       sm.data.DOWN = 1 ;\",\n            \"       output = true;\",\n            \"   } \",\n            \"} \"\n        ],\n        \"power\": [\n            \"timeout.endRum = setTimeout(function() {\",\n            \"   sm.data.UP = 1;\",\n            \"   sm.data.DOWN = 1;\",\n            \"   sm.fill = 'grey';\",\n            \"   sm.text = 'onHalt';\",\n            \"   resume('complRunAndCheck', msg);\",\n            \"}, sm.data.runTime);\",\n            \"output = false;\"\n            ],\n        \"complRunAndCheck\": [\n            \"if (sm.data.temp < sm.data.current && sm.direction === 1 || sm.data.temp > sm.data.current && sm.direction === -1) {\",\n            \"   timeout.changeDir = setTimeout(function() {\",\n            \"   msg.payload = sm.data.temp;\",\n            \"   resume('setPoint', msg);\",\n            \"   output = false;\",\n            \"   }, 150);\",\n            \"} else if (sm.data.temp != sm.data.current) {\",\n            \"   msg.payload = sm.data.temp;\",\n            \"   resume('setPoint', msg);\",\n            \"   output = false;\",\n            \"} else {\",\n            \"}\"\n            ],\n        \"status\": {\n            \"fill\": {\n                \"get\": \"sm.fill\"\n            },\n            \"shape\": \"dot\",\n            \"text\": {\n                \"get\": \"sm.text\"\n            }\n        }\n    }\n}","x":636,"y":559,"wires":[["56ef231d.e7bb8c"]]},{"id":"c1755c3d.93246","type":"inject","z":"667bf9ae.4b2b98","name":"init","topic":"setPoint","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":166,"y":526,"wires":[["47c4c534.356f4c","9ed7d29c.f1a65","7383224f.161dfc"]]},{"id":"47c4c534.356f4c","type":"function","z":"667bf9ae.4b2b98","name":"BlindProfile","func":"msg1={};\nmsg2={};\nmsg3={};\nmsg4={};\nmsg5={};\n// var unoProfile = { step:0, max:0 };\nmsg1.topic = \"temp\";\nmsg1.payload = 0;\nmsg2.topic = \"current\";\nmsg2.payload = 0;\nmsg3.topic = \"UP\";\nmsg3.payload = 1;\nmsg3.topic = \"DOWN\";\nmsg3.payload = 1;\nmsg2.topic = \"runTime\";\nmsg2.payload = 0;\nreturn [ msg1, msg2, msg3, msg4, msg5];","outputs":5,"noerr":0,"x":346,"y":646,"wires":[["61b44efc.4e5b"],["61b44efc.4e5b"],["61b44efc.4e5b"],["61b44efc.4e5b"],["61b44efc.4e5b"]]},{"id":"56ef231d.e7bb8c","type":"function","z":"667bf9ae.4b2b98","name":"RpiPinDist","func":"msg1={};\nmsg2={};\nmsg3={};\nmsg4={};\nmsg1.payload = msg.data.UP;\nmsg2.payload = msg.data.DOWN;\nif (msg.data.UP && msg.data.DOWN) {\n    msg3.payload = \"hide\";\n    msg4.payload = \"display\";\n} else {\n    msg3.payload = \"display\";\n    msg4.payload = \"hide\";\n}\nreturn [ msg1, msg2, msg3, msg4 ];","outputs":4,"noerr":0,"x":626,"y":646,"wires":[["3e36161e.32238a"],["a6a1337c.24591"],["2f28d9c2.ab69c6"],["4bd10fef.81206"]]},{"id":"3e36161e.32238a","type":"rpi-gpio out","z":"667bf9ae.4b2b98","name":"","pin":"7","set":true,"level":"1","freq":"","out":"out","x":896,"y":538,"wires":[],"inputLabels":["Window#1"]},{"id":"a6a1337c.24591","type":"rpi-gpio out","z":"667bf9ae.4b2b98","name":"","pin":"11","set":true,"level":"1","freq":"","out":"out","x":896,"y":586,"wires":[],"inputLabels":["Window#1"]},{"id":"7383224f.161dfc","type":"function","z":"667bf9ae.4b2b98","name":"adaptBlindTwo","func":"const MAX = 19000\nmsg.payload = msg.payload*MAX/10;\nreturn msg;","outputs":1,"noerr":0,"x":516,"y":406,"wires":[["61b44efc.4e5b"]]},{"id":"9ed7d29c.f1a65","type":"ui_slider","z":"667bf9ae.4b2b98","name":"BlindHeightWidget","label":"{{ value }}","group":"78206801.db6798","order":1,"width":"6","height":"1","passthru":true,"outs":"end","topic":"setPoint","min":0,"max":"10","step":"1","x":382,"y":526,"wires":[["7383224f.161dfc"]],"outputLabels":["setpoint"]},{"id":"de26add4.024cf","type":"ui_group","z":"","name":"Msg1","tab":"7e3910f.9132af","disp":true,"width":"6","collapse":false},{"id":"26bd3a6a.d77a26","type":"ui_group","z":"","name":"GO-ONE","tab":"7e3910f.9132af","disp":true,"width":"6","collapse":false},{"id":"91c8f5ad.bc1668","type":"ui_group","z":"","name":"Msg2","tab":"7e3910f.9132af","disp":true,"width":"6","collapse":false},{"id":"78206801.db6798","type":"ui_group","z":"","name":"GO-TWO","tab":"7e3910f.9132af","disp":true,"width":"6","collapse":false},{"id":"7e3910f.9132af","type":"ui_tab","z":"","name":"TheBridgeBlinds","icon":"dashboard"}]
`

yes, the "only on release "mode definitely improves the behavior. Thank you!

Digging up an old topic here.

This works great, and I've learned a lot from it, so thanks!

One additional question: this function delays every incoming message, but is there a way to ignore any additional messages received during the delay period?

Example: an inject node fires a timestamp once per second, the function delays the first incoming timestamp by 5 seconds, and the 4 additional timestamps received during the first delay period would be discarded.

Currently, the function delays each additional timestamp by 5 seconds, so after 5 seconds, they arrive once per second as if the function wasn't doing anything.

Look at the delay node in rate limit mode

That would work beautifully, but I’m trying to set the delay time to a value I have stored in global context.