Timer function with UI input

Hello there!

I am completely new to this fascinating area about node-red and using a raspberry pi.
Also I am new to programming in any languages like java etc.

My first project i'd like to make is controlling our heating system with a raspberry pi.
So far so good everything worked, but basically i used the "light scheduler" node to set a schedule when the heating system has to run.
To make it easier i wanted to define the time, when it should run on the dashboard ui.
But i've got several problems which i cannot solve, after couple hours of researching and googling i can't find my problems.
And i could't find anyone who tries to do exact the same

First thing which is not working properly, whenever i put in a time in my dashboard, the output msg adds always +1 hour to the set time.
What am i doing wrong here?

Second thing are the times i'm writing to a flow.string and reading them then in my compare function, but this is also not working properly. If i set the times "manually" in my code everything works properly..
As i said, i have not much idea about java script, i compared the strings "manually" which seems to work, and the time inputs are also giving a string as an output so thats what confuses me.

I hope some of you can tell me what i'm doing wrong.

Thank you in advance!

Code:

 [{"id":"47fcdd53.dcf394","type":"tab","label":"Test Zeiteingabe","disabled":false,"info":""},{"id":"1bfe100c.ca8d","type":"ui_text_input","z":"47fcdd53.dcf394","name":"","label":"Time OFF","group":"ea875bd4.ac4f08","order":7,"width":"3","height":"1","passthru":true,"mode":"time","delay":300,"topic":"","x":160,"y":220,"wires":[["ce4046af.e8c638"]]},{"id":"fd3a21d1.8d0d4","type":"ui_text_input","z":"47fcdd53.dcf394","name":"","label":"Time On","group":"ea875bd4.ac4f08","order":6,"width":"3","height":"1","passthru":true,"mode":"time","delay":300,"topic":"","x":160,"y":160,"wires":[["ff361051.c8748"]]},{"id":"d4194210.ce03a","type":"debug","z":"47fcdd53.dcf394","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":850,"y":160,"wires":[]},{"id":"ff361051.c8748","type":"function","z":"47fcdd53.dcf394","name":"format time","func":"var now     = new Date(msg.payload); \nvar hour    = now.getHours();\nvar minute  = now.getMinutes();\n \nif(hour.toString().length == 1) {\nvar hour = '0'+hour;\n}\nif(minute.toString().length == 1) {\nvar minute = '0'+minute;\n}\n\nmsg.payload = hour+':'+minute;\n\nreturn msg;","outputs":1,"noerr":0,"x":390,"y":160,"wires":[["a2ede4b3.9032b8"]]},{"id":"ce4046af.e8c638","type":"function","z":"47fcdd53.dcf394","name":"format time","func":"var now     = new Date(msg.payload); \nvar hour    = now.getHours();\nvar minute  = now.getMinutes();\n \nif(hour.toString().length == 1) {\nvar hour = '0'+hour;\n}\nif(minute.toString().length == 1) {\nvar minute = '0'+minute;\n}\n\nmsg.payload = hour+':'+minute;\n\nreturn msg;","outputs":1,"noerr":0,"x":390,"y":220,"wires":[["a68ce92e.4b7a28"]]},{"id":"58fd256.cb744dc","type":"debug","z":"47fcdd53.dcf394","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":850,"y":220,"wires":[]},{"id":"a2ede4b3.9032b8","type":"function","z":"47fcdd53.dcf394","name":"Flow Set","func":"var newMsg = { payload: msg.payload};\nflow.set('timeOn',newMsg);\nreturn newMsg;","outputs":1,"noerr":0,"x":640,"y":160,"wires":[["d4194210.ce03a"]]},{"id":"a68ce92e.4b7a28","type":"function","z":"47fcdd53.dcf394","name":"Flow Set","func":"var newMsg = { payload: msg.payload};\nflow.set('timeOff',newMsg);\nreturn newMsg;","outputs":1,"noerr":0,"x":640,"y":220,"wires":[["58fd256.cb744dc"]]},{"id":"711b1aaa.362e74","type":"function","z":"47fcdd53.dcf394","name":"in time?","func":"var timeActive = flow.get('timeActive');\nvar timeOn = flow.get('timeOn');\nvar timeOff = flow.get('timeOff');\n    \n    \n    //Just for testing\n   // var timeActive = \"true\";\n   // var timeOn = \"15:33\";\n   // var timeOff = \"18:00\";\n\n  if(timeActive == \"true\")\n   {\n        a = new Date();\n        b = a.getHours();\n        c = a.getMinutes();\n       time = b+':'+c;       \n    \n    if(time>=timeOn && time<=timeOff)\n\t\t{\n\t\t\t msg.payload = \"true\";\n\t\t}\n    else\n        {\n\t\t\tmsg.payload = \"false\";\n\t\t}\n    \n   }\n\t\n\treturn msg;","outputs":1,"noerr":0,"x":380,"y":280,"wires":[["7e6e4988.8aa918"]]},{"id":"7e6e4988.8aa918","type":"debug","z":"47fcdd53.dcf394","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":850,"y":280,"wires":[]},{"id":"e504ec54.dab96","type":"inject","z":"47fcdd53.dcf394","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":160,"y":280,"wires":[["711b1aaa.362e74"]]},{"id":"e9f2cd29.0fa2a","type":"ui_switch","z":"47fcdd53.dcf394","name":"","label":"Timer active","group":"ea875bd4.ac4f08","order":5,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","x":170,"y":100,"wires":[["239b6118.b9025e"]]},{"id":"239b6118.b9025e","type":"function","z":"47fcdd53.dcf394","name":"Time active","func":"var newMsg = { payload: msg.payload};\nflow.set('timeActive',newMsg);\nreturn newMsg;","outputs":1,"noerr":0,"x":390,"y":100,"wires":[[]]},{"id":"ea875bd4.ac4f08","type":"ui_group","z":"","name":"Test","tab":"59584b8c.4dd124","disp":true,"width":"6","collapse":false},{"id":"59584b8c.4dd124","type":"ui_tab","z":"","name":"Home","icon":"dashboard"}]
1 Like

The time input node appears to assume you are entering a time in your local timezone but passes on a time in UTC, as milliseconds since midnight UTC. I assume from this that your local time is UTC-1.
I haven't studied your time comparison code to see what is going wrong, I suggest that you keep the times in milliseconds since midnight and compare those, why mess about converting them to strings when it just causes problems? Doing it this way the fact that the times are in UTC shouldn't matter either. When doing the compare don't forget to consider whether you ever need the On time to be in the evening and the Off time in the morning (so Off time will be less than On time).

1 Like

Thank you very much Colin for your quick reply!

You are right, it makes no sense to change the time values, i stay with the milliseconds.
I changed the functions, so that i get millliseconds to compare. And also fixed the problem with the UTC timezone, (whyever this appears because i thought it is just an input node?)

But i still got some problems with my compare function.
I tried some stuff, by putting in the values manually by hand in my code and it worked, but as soon as i try to get the values from my flow.timeOn/Off or even the flow.timeActive for my if state is not working properly.
Is there anything to take care of if i want to use the flow. function?
For me it seems that the function cannot work with any value/string which comes from the flow. whatever.

Thank you for your consideration, but i won't let the heating system run during night, only during day so that should not be a problem for me.

Here is the new node:

[{"id":"1bfe100c.ca8d","type":"ui_text_input","z":"47fcdd53.dcf394","name":"","label":"Time OFF","group":"ea875bd4.ac4f08","order":7,"width":"3","height":"1","passthru":true,"mode":"time","delay":300,"topic":"","x":160,"y":220,"wires":[["ce4046af.e8c638"]]},{"id":"fd3a21d1.8d0d4","type":"ui_text_input","z":"47fcdd53.dcf394","name":"","label":"Time On","group":"ea875bd4.ac4f08","order":6,"width":"3","height":"1","passthru":true,"mode":"time","delay":300,"topic":"","x":160,"y":160,"wires":[["ff361051.c8748"]]},{"id":"d4194210.ce03a","type":"debug","z":"47fcdd53.dcf394","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":850,"y":160,"wires":[]},{"id":"ff361051.c8748","type":"function","z":"47fcdd53.dcf394","name":"format time","func":"var timeUTC = msg.payload\nvar time =   timeUTC - 3600000\n\nmsg.payload = time\n\nreturn msg;","outputs":1,"noerr":0,"x":390,"y":160,"wires":[["a2ede4b3.9032b8"]]},{"id":"ce4046af.e8c638","type":"function","z":"47fcdd53.dcf394","name":"format time","func":"var timeUTC = msg.payload\nvar time =   timeUTC - 3600000\n\nmsg.payload = time\n\nreturn msg;","outputs":1,"noerr":0,"x":390,"y":220,"wires":[["a68ce92e.4b7a28"]]},{"id":"58fd256.cb744dc","type":"debug","z":"47fcdd53.dcf394","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":850,"y":220,"wires":[]},{"id":"a2ede4b3.9032b8","type":"function","z":"47fcdd53.dcf394","name":"Flow Set","func":"var newMsg = { payload: msg.payload};\nflow.set('timeOn',newMsg);\nreturn newMsg;","outputs":1,"noerr":0,"x":620,"y":160,"wires":[["d4194210.ce03a"]]},{"id":"a68ce92e.4b7a28","type":"function","z":"47fcdd53.dcf394","name":"Flow Set","func":"var newMsg = { payload: msg.payload};\nflow.set('timeOff',newMsg);\nreturn newMsg;","outputs":1,"noerr":0,"x":620,"y":220,"wires":[["58fd256.cb744dc"]]},{"id":"711b1aaa.362e74","type":"function","z":"47fcdd53.dcf394","name":"in time?","func":"var timeActive = flow.get('timeActive');\nvar timeOn = flow.get('timeOn');\nvar timeOff = flow.get('timeOff');\n    \n    \n    //Just for testing\n   // var timeActive = \"true\";\n   // var timeOn = \"36000000\";\n   // var timeOff = \"432000000\";\n\n  if(timeActive == \"true\")\n   {\n        var d = new Date(), e = new Date(d);\n        var msSinceMidnight = e - d.setHours(0,0,0,0);\n\n    time = msSinceMidnight       \n    \n    if(time>=timeOn && time<=timeOff)\n\t\t{\n\t\t\t msg.payload = \"true\";\n\t\t}\n    else\n        {\n\t\t\tmsg.payload = \"false\";\n\t\t}\n    \n   }\n\t\n\treturn msg;","outputs":1,"noerr":0,"x":380,"y":280,"wires":[["7e6e4988.8aa918"]]},{"id":"7e6e4988.8aa918","type":"debug","z":"47fcdd53.dcf394","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":850,"y":280,"wires":[]},{"id":"e504ec54.dab96","type":"inject","z":"47fcdd53.dcf394","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":160,"y":280,"wires":[["711b1aaa.362e74"]]},{"id":"e9f2cd29.0fa2a","type":"ui_switch","z":"47fcdd53.dcf394","name":"","label":"Timer active","group":"ea875bd4.ac4f08","order":5,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","x":170,"y":100,"wires":[["239b6118.b9025e"]]},{"id":"239b6118.b9025e","type":"function","z":"47fcdd53.dcf394","name":"Time active","func":"var newMsg = { payload: msg.payload};\nflow.set('timeActive',newMsg);\nreturn newMsg;","outputs":1,"noerr":0,"x":390,"y":100,"wires":[[]]},{"id":"ea875bd4.ac4f08","type":"ui_group","z":"","name":"Test","tab":"8cbc2256.d237e","disp":true,"width":"6","collapse":false},{"id":"8cbc2256.d237e","type":"ui_tab","z":"","name":"Home","icon":"home"}]

A simple way to debug functions is to use node.warn. So for example, after the line
var timeOn = flow.get('timeOn');
if you add
node.warn("timeOn: " + timeOn);
then it will display that in the debug window. However you might want to look closely at what you are saving with flow.set.

Can i suggest to you - you might want to look at Peter Scargills Big Timer node - it looks like it will do everything you want in terms of on/off logic and will also let you set override times etc.

An alternative to this would be @ncherry and his fantastic mytimeout node - which is aimed at a slightly different use scenario

Craig