Button Push vs Hold without Time Difference Calculations
In this flow, I am simulating the push and release of a button with the injection nodes but it could easily be replaced by a GPIO node. The flow is expecting 0 for press and 1 when the button is released. It consists of only two nodes, a function node and a delay node. When the button is pressed, the held message is sent to the delay node to wait for the delay it is set for. If the timer runs out before the button is released, the hold msg is sent. If the button is released before the timer, the push msg is sent instead, by canceling the delay node. Because we are not calculating the time between two events, this means that you do not need to hold the button extra long. The hold msg will be sent as soon as the timeout is reached. No more holding the button for 5 seconds to make sure you've gone over the hold time.
To adjust the timeout, just change the delay node to whatever you want. I prefer 1200 ms myself.
These nodes are setting msg.command to either "push" or "hold" but you could easily change that to be whatever you needed. There will be a message output from the delay node for the hold message and from the function node's bottom output (labeled push) for the push message.
Note: Do not modify msg.payload until after the delay node unless you adjust the function node. The output from the delay node back to the function node is required for resetting the context data. So, it would be easiest to modify payload after the delay node of the push output of the function node, not within the function node.
[{"id":"ba97d22d.3df94","type":"tab","label":"Button Press vs. Hold","disabled":false,"info":""},{"id":"53b73bc.78f9cc4","type":"inject","z":"ba97d22d.3df94","name":"Push","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":250,"y":220,"wires":[["d749ce99.e49e4"]]},{"id":"180cf874.13daa8","type":"inject","z":"ba97d22d.3df94","name":"Release","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":240,"y":260,"wires":[["d749ce99.e49e4"]]},{"id":"d749ce99.e49e4","type":"function","z":"ba97d22d.3df94","name":"Press/Hold","func":"var pending = context.get(\"pending\");\nif(msg.payload === 0){\n if(pending){\n context.set(\"pending\", false);\n }else{\n context.set(\"pending\",true);\n msg.command = \"hold\";\n return [msg,null];\n }\n}else if (msg.payload ===1){\n if(pending){\n msg.reset = true;\n msg.command = \"push\";\n context.set(\"pending\",false);\n return [msg,msg];\n }\n}","outputs":2,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is deployed.\ncontext.set(\"pending\", false)","finalize":"","x":410,"y":240,"wires":[["ef66a17e.ec72"],["2a6988a6.ef4c48"]],"outputLabels":["Hold","Push"]},{"id":"ef66a17e.ec72","type":"delay","z":"ba97d22d.3df94","name":"","pauseType":"delay","timeout":"1200","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":580,"y":200,"wires":[["2a6988a6.ef4c48","d749ce99.e49e4"]]},{"id":"2a6988a6.ef4c48","type":"debug","z":"ba97d22d.3df94","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":770,"y":240,"wires":[]}]