Flow to activate switch between certain hours

I have a Node-MCU ESP8266 filled with a DS18B20 temperature sensor that measures the temperature in my home office.
This temperature reading goes through the switch node to set upper and lower temperature values that in turn trigger a Sonoff POW that turns on my electric heater.

At night and over weekends, I do not mind the temperature goes lower than the set value.

I need some help on how to add another set of criteria that will only switch on the heater say between 09h00 and 17h00 on weekdays and 09h00 to 12h00 on Saturdays.

I added "BigTimer" node in the hope that I can use that, but I just cannot get my head around the concept of using two sets of "switches".

Your help will greatly be appreciated.



Lots of ways to do this but i would use a FSM. Have a look at the Xstate FSM that has been recently posted up here - there is a very good example of feeding a cat on there that demonstrates a FSM in action - this would be almost exactly what you want (in terms of concepts)

The author has a good blog and is active on Github


Hello Frits,

For event driven application it is normal to pass multiple switches as every switch is an decision. You can use for example light scheduler to fill a flow or global variable, for example "autotemp" . You can call that variable in a switch node in your flow! Good luck.

I'm using myself a weekly scheduler like this https://flows.nodered.org/node/node-red-contrib-light-scheduler for those kind of jobs.

1 Like


I think I am just too thick-headed to get my head around how to use it.
I just need some help to understand how the two validations are used simultaneously .

I had a look at the site and it seems like it will do what I want, but I do not understand where to introduce (place) the "weekly scheduler" function.

Would it be possible that you either copy an existing flow and attach it here, OR create a flow for me so I can restore it on my environment and then figure out how to use it - please.

I supposed you refer to this node:

I had a look at it and it made my head spin. I think I need more brain cells to get my head around this solution

Thanks for your help, but I have no idea where to start with this one.
Perhaps an example and brief explanation so I can analyse it and try to figure it out.

Have a look at this:
It is a subflow i made which can be used like a normal node. It does exactly what you want. It routes a payload based on time of day and day of week.
The schedule on which it routes can either be configured through the node ui or with a msg.
Just drop it into your flow and all messages within the timeframe get routed to output one and outside of your configured timerange to output 2.
Maybe this helps, Johannes

I made an example flow for you:

you need to install light scheduler:

npm install node-red-contrib-light-scheduler

and here is the flow:

[{"id":"d71ab4cf.33b788","type":"light-scheduler","z":"d4309735.750d98","settings":"dfde8d7a.fd213","events":"[{\"start\":{\"dow\":1,\"mod\":1020},\"end\":{\"dow\":2,\"mod\":0}},{\"start\":{\"dow\":2,\"mod\":1020},\"end\":{\"dow\":3,\"mod\":0}},{\"start\":{\"dow\":3,\"mod\":1020},\"end\":{\"dow\":4,\"mod\":0}},{\"start\":{\"dow\":4,\"mod\":1020},\"end\":{\"dow\":5,\"mod\":0}},{\"start\":{\"dow\":5,\"mod\":1035},\"end\":{\"dow\":6,\"mod\":0}},{\"start\":{\"dow\":6,\"mod\":1020},\"end\":{\"dow\":0,\"mod\":0}},{\"start\":{\"dow\":0,\"mod\":1035},\"end\":{\"dow\":1,\"mod\":285}},{\"start\":{\"dow\":3,\"mod\":0},\"end\":{\"dow\":3,\"mod\":315}},{\"start\":{\"dow\":4,\"mod\":0},\"end\":{\"dow\":4,\"mod\":315}},{\"start\":{\"dow\":5,\"mod\":0},\"end\":{\"dow\":5,\"mod\":315}},{\"start\":{\"dow\":0,\"mod\":0},\"end\":{\"dow\":0,\"mod\":315}},{\"start\":{\"dow\":0,\"mod\":1425},\"end\":{\"dow\":1,\"mod\":315}},{\"start\":{\"dow\":2,\"mod\":0},\"end\":{\"dow\":2,\"mod\":315}},{\"start\":{\"dow\":6,\"mod\":0},\"end\":{\"dow\":6,\"mod\":315}}]","topic":"","name":"","onPayload":"true","onPayloadType":"bool","offPayload":"false","offPayloadType":"bool","onlyWhenDark":false,"scheduleRndMax":0,"sunElevationThreshold":6,"sunShowElevationInStatus":false,"outputfreq":"output.statechange.startup","x":320,"y":2720,"wires":[["67fa65b9.30bdbc"]]},{"id":"67fa65b9.30bdbc","type":"change","z":"d4309735.750d98","name":"","rules":[{"t":"set","p":"autotemp","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":2720,"wires":[["a0f8b914.2f6ef8"]]},{"id":"c31bb75.fbb2a48","type":"switch","z":"d4309735.750d98","name":"","property":"payload","propertyType":"msg","rules":[{"t":"lt","v":"18","vt":"num"},{"t":"btwn","v":"19","vt":"num","v2":"21","v2t":"num"},{"t":"lt","v":"21","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":550,"y":2880,"wires":[["a438777c.d82548"],[],["f4c75ca1.4a41e"]]},{"id":"e6d34802.163a68","type":"switch","z":"d4309735.750d98","name":"","property":"payload","propertyType":"flow","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":410,"y":2880,"wires":[["c31bb75.fbb2a48"]]},{"id":"492a5ca3.45a384","type":"inject","z":"d4309735.750d98","name":"Replace with sensor","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":220,"y":2880,"wires":[["e6d34802.163a68"]]},{"id":"a438777c.d82548","type":"template","z":"d4309735.750d98","name":"ON","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"ON","output":"str","x":710,"y":2860,"wires":[[]]},{"id":"f4c75ca1.4a41e","type":"template","z":"d4309735.750d98","name":"OFF","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"OFF","output":"str","x":710,"y":2900,"wires":[[]]},{"id":"a0f8b914.2f6ef8","type":"switch","z":"d4309735.750d98","name":"","property":"payload","propertyType":"msg","rules":[{"t":"false"}],"checkall":"true","repair":false,"outputs":1,"x":710,"y":2720,"wires":[["f4c75ca1.4a41e"]]},{"id":"dfde8d7a.fd213","type":"light-scheduler-settings","z":"","name":"my settings","latitude":"53.123204","longitude":"6.206810"}]

this flow will make sure that you have an automation only running during the periods that you want and also switching the heater off outside those windows.


I am completely clueless about what to do.

Attached the workflow I tried to test how it works.

It is 15h20 so I edited the properties of the subflow to include 15h00 to 16h00, but the toggle did not pass the validation

Flow.txt (3.4 KB)

I tried to test it by sending a payload and wanted to accept it based on time OR ignore it.

Could you please help me out.



It should look like this:

[{"id":"ba560387.ab5f58","type":"subflow","name":"timerange","info":"Lets through or blocks a payload\nbased on a time range. This can\neither be configured through the\nenviroment variables in the node ui\nor as described below with a message\nthat has an override topic.\nIf in range the msg will be passed\nto the first output and otherwise\nto the second.\nThe start and stop time needs\nto be defined in an hh:mm format.\nThere is also a week array. The week\nstarts on monday so 4 for example is\nThursday. Payload will only be passed\non days that are in the array.\nOut of time range payloads will\nbe redirected to the second output.\nThe schedule can be overriden by injecting\na message with the topic of \"override\"\nthat contains a ```msg.payload``` object with the\nkeys of \"start\",\"stop\",\"days\" like\nthis:\n```\n{\n    \"start\": \"10:00\",\n    \"stop\": \"14:00\",\n    \"days\": [\n        1,\n        2,\n        3,\n        4,\n        5,\n        6,\n        7\n    ]\n}\n```\nStart and stop need to be strings in the hh:mm\nformat and days an array of numbers as\ndescribed above.\nThe override can be deleted by injecting a\nmsg.payload string \"reset\".","category":"","in":[{"x":100,"y":100,"wires":[{"id":"dffc7695.523d9"}]}],"out":[{"x":620,"y":60,"wires":[{"id":"262fc2bc.80defe","port":0}]},{"x":620,"y":140,"wires":[{"id":"262fc2bc.80defe","port":1}]}],"env":[{"name":"start","type":"str","value":"00:00","ui":{"icon":"font-awesome/fa-arrow-right","label":{"en-US":"from hh:mm"},"type":"input","opts":{"types":["str"]}}},{"name":"stop","type":"str","value":"00:00","ui":{"icon":"font-awesome/fa-circle","label":{"en-US":"until hh:mm"},"type":"input","opts":{"types":["str"]}}},{"name":"days","type":"json","value":"[1,2,3,4,5,6,7]","ui":{"icon":"font-awesome/fa-calendar","label":{"en-US":"days"},"type":"input","opts":{"types":["json"]}}}],"color":"#C7E9C0","inputLabels":["payload input"],"outputLabels":["in time range","out of time range"],"icon":"node-red/switch.svg","status":{"x":480,"y":200,"wires":[{"id":"935a8f78.31a528","port":0}]}},{"id":"262fc2bc.80defe","type":"function","z":"ba560387.ab5f58","name":"is in range?","func":"const schedule = flow.get(\"schedule\");\nlet start = env.get(\"start\");\nlet stop = env.get(\"stop\");\nlet days = env.get(\"days\");\nif(schedule !== undefined){\n    start = schedule.start;\n    stop = schedule.stop;\n    days = schedule.days;\n}\nconst time = new Date();\nlet day = time.getDay();\nif(day === 0) day = 7;\nlet hour = String(time.getHours());\nlet minute = String(time.getMinutes());\nif(hour.length == 1) hour = \"0\" + hour;\nif(minute.length == 1) minute = \"0\" + minute;\nconst hmtime = hour + \":\" + minute;\nif(days.includes(day)){\n    if(start == stop){\n        return [msg, null];\n    } else if(start > stop){\n        if(hmtime >= start || hmtime < stop){\n            return [msg, null];\n        } else {\n            return [null, msg];\n        }\n    } else if(hmtime >= start && hmtime < stop){\n        return [msg, null];\n    } else {\n        return [null, msg];\n    }\n} else {\n    return null;\n}","outputs":2,"noerr":0,"x":450,"y":100,"wires":[[],[]]},{"id":"8d9145c9.1c5d38","type":"inject","z":"ba560387.ab5f58","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":170,"y":200,"wires":[["935a8f78.31a528"]]},{"id":"935a8f78.31a528","type":"function","z":"ba560387.ab5f58","name":"display rule","func":"const schedule = flow.get(\"schedule\");\nif(typeof schedule == \"object\"){\n    const start = schedule.start;\n    const stop = schedule.stop;\n    const days = String(schedule.days);\n    msg.payload = \"override: \" + start + \"-\" + stop + \"/\" + days;\n} else {\n    const start = env.get(\"start\");\n    const stop = env.get(\"stop\");\n    const days = String(env.get(\"days\"));\n    const override = false;\n    msg.payload = start + \"-\" + stop + \"/\" + days;\n}\nreturn msg;","outputs":1,"noerr":0,"x":350,"y":200,"wires":[[]]},{"id":"dffc7695.523d9","type":"function","z":"ba560387.ab5f58","name":"check for override","func":"if(msg.topic == \"override\"){\n    flow.set(\"schedule\",msg.payload);\n    return [null, msg];\n} else if (msg.payload == \"reset\"){\n    let reset;\n    flow.set(\"schedule\",reset);\n    return [null, msg];\n} else {\n    return [msg, null];\n}","outputs":2,"noerr":0,"x":250,"y":100,"wires":[["262fc2bc.80defe"],["935a8f78.31a528"]]},{"id":"83c9b1eb.9d86f","type":"http request","z":"fdf1e896.b0783","name":"SOnoOff 160","method":"POST","ret":"txt","paytoqs":false,"url":" toggle","tls":"","persist":false,"proxy":"","authType":"","x":1130,"y":280,"wires":[["40d35633.1cfc78"]]},{"id":"bc86ddd1.9aaed","type":"inject","z":"fdf1e896.b0783","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":660,"y":320,"wires":[["7d4cfb7e.fa6c64"]]},{"id":"40d35633.1cfc78","type":"debug","z":"fdf1e896.b0783","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":1310,"y":280,"wires":[]},{"id":"997f988b.b10608","type":"debug","z":"fdf1e896.b0783","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":1130,"y":380,"wires":[]},{"id":"7d4cfb7e.fa6c64","type":"subflow:ba560387.ab5f58","z":"fdf1e896.b0783","name":"","env":[{"name":"start","value":"15:00","type":"str"},{"name":"stop","value":"16:00","type":"str"},{"name":"days","value":"[1,2,3,4,5]","type":"json"}],"x":880,"y":320,"wires":[["83c9b1eb.9d86f","7b3b5904.e1119"],["997f988b.b10608"]]},{"id":"7b3b5904.e1119","type":"debug","z":"fdf1e896.b0783","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":1130,"y":180,"wires":[]}]

Import this and have a look.
Dont edit inside the subfow. It works just like a node. Copy the code from the link and import it. You than have the timerange node in the subflow category of your palette on the left. Drag it into your workspace and click on it and you can configure time and days in the ui.
In the info tab on the right you find all informations about what you can do with it.
the functions will not work outside the subflow as they try to access environmental context of the subflow and set its status.

1 Like

Hi Johannes,

The more I read and try the less I understand.

I have attached a word doc with some screenshots and text to explain what I do not understand.
Perhaps I am just doing something very wrong.

Could you please have a look at it and help me to get this to work?


FritsNeed help.pdf (608.5 KB)

Which version of nodered are you running?

I just imported the flow i posted into three different instances of nodered i have running that have versions ranging from 1.0.3 to 1.0.5 and it works perfectly :frowning_face:
But if you run anything prior to 1.0 like 0.20 it will not work @fritserasmus i am afraid.
I did some reading and indeed the features i use werent added till 1.0.
see here https://nodered.org/blog/2019/09/30/version-1-0-released#subflow-instance-property-ui
I will have to add that to the info page.

Thanks Johannes.
Yes you are correct.
Node-RED version: v0.18.7
Node.js version: v4.2.6
Linux 4.4.0-139-generic ia32 LE
Dashboard version 2.9.4 started at /ui

Then some warnings too and two errors.

Ubuntu 16.04.4 LTS

So I read through some upgrade documentation and I am too cared to just run the updates as it appears potentially I can break a lot things.

Hi Johannes,

I finally got it to work.

Lets say I have the following complex timerange that I would like the auto power on and of to operate.
How would be the best to specify it in the subflow properties timerange?

Mon - Friday 07h00 - 18h00
Saturday 08h00 - 12h00
Sunday 09h00 - 10h00 and 15h00 to 16h00

just put four of the timerange switches in parallel. Each for one range. Or you use something more complex like https://flows.nodered.org/node/node-red-contrib-cron-plus which
to set a flow variable and than use a switch node to check that flow variable.

Thanks for all the help Johannes - I am a happy man!!


This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.