A timed button routine/code with abort option

This is a little flow I wrote to use if ever you want to start something to happen for a time then stop.

Very basic things sent with this code.

Note!

0 is to signal START and 1 is to signal STOP

I know it is the wrong way around for most uses, but my needs made it that 0 was what was needed to get things going and 1 was .... optional (could have been anything else too) but to keep it easy, I used that..... used to signal the end of the time.

You can also abort the timer. But this doesn't just stop things. This code sends the END signal.
I needed this to restore things to how they were before the timer was invoked.

The button's colour and font colour can be changed to indicate things are active.
With a bit of effort, you could even change the text.
(Not needed for my case, so I didn't do it.)

I hope it is helpful.

Oh, P.S.
The flow as is uses a CSS button. I mention in the code I can't remember where I defined the button and now after I posted the code, I remember (not where I defined the button) but you could use the standard dashboard button node and just edit it's properties to accept the different colours for the different parts.
(and also the text if you read the stuff in the flow)

[{"id":"7f3c8997.07fde8","type":"function","z":"68e3655f.b606b4","name":"Button colour **","func":"////////////////////////\n//  `0` = on `1` = off\n////////////////////////\n\nvar msg1 = {};\nvar state = context.get(\"state\") || 0;\nvar x = msg.payload;\n\nif (msg.topic == \"BOOT\")\n{\n    //  This sets buttons to default (OFF) colours.\n    x = 1;\n}\n\n\n\nif (x == 0)\n{\n    //  On\n    //  More work needed to toggle when second press.\n    if (state == 0)\n    {\n        //\n        msg1.colour = \"#333333\";\n        msg1.font = \"teal\";\n        context.set(\"state\",1);\n        return [msg,msg1];\n    } else\n    if (state == 1)\n    {\n        //\n        msg1.colour = \"#3d3d3d\";\n        msg1.font = \"white\";\n        context.set(\"state\",0);\n        msg.reset = true;\n        return [msg,msg1];\n    }\n} else\nif (x == 1)\n{\n    //  Off\n    msg1.colour = \"#3d3d3d\";\n    msg1.font = \"white\";\n    return [null,msg1];\n}\n\n","outputs":2,"noerr":0,"initialize":"","finalize":"","x":1990,"y":1900,"wires":[["d13d3ce1.7a4bd8"],["ce38b73f.6cfc78","90e01568.d65ff"]]},{"id":"d13d3ce1.7a4bd8","type":"trigger","z":"68e3655f.b606b4","name":"Read me *","op1":"0","op2":"1","op1type":"num","op2type":"num","duration":"20","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":2180,"y":1900,"wires":[["3e1fb8ad.8048a","a387f499.105be"]],"info":"This is set to the time you want the event to happen."},{"id":"ce38b73f.6cfc78","type":"link out","z":"68e3655f.b606b4","name":"","links":["372a3c0c.210fc4"],"x":2125,"y":1980,"wires":[]},{"id":"372a3c0c.210fc4","type":"link in","z":"68e3655f.b606b4","name":"","links":["ce38b73f.6cfc78","e8f200e6.1ae12"],"x":1675,"y":1900,"wires":[["4916df76.8e9ea8"]]},{"id":"48dae6ff.964be","type":"inject","z":"68e3655f.b606b4","name":"Setup (Default) *","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"3","topic":"","payload":"1","payloadType":"num","x":1780,"y":1860,"wires":[["7f3c8997.07fde8"]],"info":"This sets the button and style to what it is when OFF"},{"id":"f22b14a8.ee5738","type":"link out","z":"68e3655f.b606b4","name":"","links":["7c71406f.caca28"],"x":2325,"y":1940,"wires":[]},{"id":"7c71406f.caca28","type":"link in","z":"68e3655f.b606b4","name":"","links":["f22b14a8.ee5738"],"x":1855,"y":1940,"wires":[["7f3c8997.07fde8"]]},{"id":"3e1fb8ad.8048a","type":"switch","z":"68e3655f.b606b4","name":"OFF","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"1","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":2275,"y":1940,"wires":[["f22b14a8.ee5738"]],"l":false},{"id":"90e01568.d65ff","type":"switch","z":"68e3655f.b606b4","name":"","property":"colour","propertyType":"msg","rules":[{"t":"eq","v":"#3d3d3d","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":2125,"y":1940,"wires":[["4ebe1da6.55a39c"]],"l":false},{"id":"4ebe1da6.55a39c","type":"change","z":"68e3655f.b606b4","name":"1","rules":[{"t":"set","p":"payload","pt":"msg","to":"1","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":2175,"y":1940,"wires":[["a387f499.105be"]],"l":false},{"id":"4916df76.8e9ea8","type":"ui_template","z":"68e3655f.b606b4","group":"e8caef27.9a3db8","name":"Some button *","order":5,"width":"3","height":1,"format":"<div id=\"SomeButtonName\">\n   <md-button style=\"background-color:{{msg.colour}}; color:{{msg.font}}\" class=\"md-button program-names bigger\"\n    data-topic=\"1\">Something\n   </md-button>\n</div>\n\n<script>\n\n(function($scope) {\n\n$('#SomeButtonName').on('click', function(e) {\n    e.preventDefault(); //prevent default behavior\n    $scope.send({\"topic\":\"momentary_regular\",\"payload\": 0});\n});\n    \n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":false,"resendOnRefresh":false,"templateScope":"local","x":1790,"y":1900,"wires":[["7f3c8997.07fde8"]],"info":"This is THE button used.\nIts style is set at boot.\nIf pressed the `OUTPUT` will get a `0` for a given time.\nThe button's style will change.\nAfter a given time (see `trigger` node) the `OUTPUT` will get a `1` and the button's style will be put back to what it was.\nIf you want to abort the waiting: press the button again and all will be reset."},{"id":"a387f499.105be","type":"function","z":"68e3655f.b606b4","name":"Output *","func":"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":2380,"y":1900,"wires":[[]],"info":"This is only here to give ONE output from the code."},{"id":"8849d305.2a68a8","type":"comment","z":"68e3655f.b606b4","name":"READ ME *","info":"2021 01 15.\n\nThis is a bit of code to give you a button to start a timed event, and allow the abortion of waiting.\n\nAll nodes with a `*` in their name have things to be read in the comments page.\n\nI am not a CSS expert, but you will need to set up the button class.\nSorry I didn't include that part.  I honestly forget where I did it.","x":2050,"y":1850,"wires":[]},{"id":"e8caef27.9a3db8","type":"ui_group","name":"Movie Mode","tab":"1099d9d9.3bb04e","order":4,"disp":true,"width":"7","collapse":false},{"id":"1099d9d9.3bb04e","type":"ui_tab","name":"Schedule","icon":"dashboard","order":11,"disabled":false,"hidden":false}]