I'm trying to cycle through 4 different lights from sunset to sunrise.
I'm sure there is a better/cleaner approach to this, looking for someone to point me in the right direction.
I think you need to give a bit more detail. Just took a quick look at your flow... are you trying to turn just one of the four lights on for 5 seconds every hour in a sequence, or ALL the lights on together??
Last question... what are the name of the nodes shown in your flow??
Sorry I'm not familiar with Home Assistant - but I'm sure someone else will jump in to help.
Just thinking off the top of my head... I would do something like using BigTimer or Cron-Plus to determine the period between sunset and sunrise and use this fact to set a variable to act as a 'gate'. Then trigger a counter every hour that counts 0,1,2,3 and resets. Then decode the value of the counter to determine which light to operate.
I'm busy at the moment, but as soon as I get some spare time I'll cobble a flow together.
Can I ask what is the purpose of this flow? Are the lights embedded in some kind of display? Also should the sequence cycle all day until the sun is below_horizon?
There are 4 lights in my patio, which I want them on from sunset to sunrise. Didnt need all 4 to be on as it would be too bright, so came up with the idea of cycling through them to keep the usage of them equal.
Are they on dimmer control or just a binary relay (on/off)?
They are on a binary relay - On/Off
Just had a few spare minutes to knock-up a flow for you to try. You will need to edit the function nodes so the flow 'talks' to Home Assistant and enter your Lat/Lon values so sunset/sunrise are correct for your locality. It's not the most efficient flow as I wrote it so it would be easy to understand what's going on.
four_lights.json (11.2 KB)
[{"id":"2d6215b8.ac8242","type":"function","z":"77ce1e39d14f8570","name":"Pass on if Timer is ON","func":"var timer = flow.get(\"timer\");\n\nif (timer == \"on\") {\n msg.payload = 1;\n node.status({ fill: \"green\", shape: \"dot\", text: \"Pass is ON\" });\n return msg;\n}\nelse {\n node.status({ fill: \"red\", shape: \"dot\", text: \"Pass is OFF\" });\n return null;\n}\n","outputs":"1","noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":300,"wires":[["a21c12f206b98026"]]},{"id":"d6b184e3.01de58","type":"function","z":"77ce1e39d14f8570","name":"Timer On/Off","func":"if (msg.payload == 1)\n {\n flow.set(\"timer\",\"on\");\n node.status({fill:\"green\",shape:\"dot\",text:\"Timer is ON\"});\n }\nelse if (msg.payload === 0)\n {\n flow.set(\"timer\",\"off\");\n flow.set(\"counter\",0);\n node.status({fill:\"red\",shape:\"dot\",text:\"Timer is OFF\"});\n }","outputs":"0","noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":200,"wires":[]},{"id":"9c07f928.96aca8","type":"bigtimer","z":"77ce1e39d14f8570","outtopic":"","outpayload1":"","outpayload2":"","name":"Main Timer","comment":"","lat":"51.35","lon":"-0.87","starttime":"5004","endtime":"5003","startoff":"0","endoff":0,"startoff2":"","endoff2":"","offs":0,"outtext1":"","outtext2":"","timeout":" ","sun":true,"mon":true,"tue":true,"wed":true,"thu":true,"fri":true,"sat":true,"jan":true,"feb":true,"mar":true,"apr":true,"may":true,"jun":true,"jul":true,"aug":true,"sep":true,"oct":true,"nov":true,"dec":true,"day1":0,"month1":0,"day2":0,"month2":0,"day3":0,"month3":0,"day4":0,"month4":0,"day5":0,"month5":0,"day6":"","month6":"","day7":"","month7":"","day8":"","month8":"","day9":"","month9":"","day10":"","month10":"","day11":"","month11":"","day12":"","month12":"","d1":0,"w1":0,"d2":0,"w2":0,"d3":0,"w3":0,"d4":0,"w4":0,"d5":0,"w5":0,"d6":"","w6":"","xday1":"","xmonth1":"","xday2":"","xmonth2":"","xday3":"","xmonth3":"","xday4":"","xmonth4":"","xday5":"","xmonth5":"","xday6":"","xmonth6":"","xday7":"","xmonth7":"","xday8":"","xmonth8":"","xday9":"","xmonth9":"","xday10":"","xmonth10":"","xday11":"","xmonth11":"","xday12":"","xmonth12":"","xd1":"","xw1":"","xd2":"","xw2":"","xd3":"","xw3":"","xd4":"","xw4":"","xd5":"","xw5":"","xd6":"","xw6":"","suspend":false,"random":false,"randon1":false,"randoff1":false,"randon2":false,"randoff2":false,"repeat":true,"atstart":true,"odd":false,"even":false,"x":150,"y":200,"wires":[[],["d6b184e3.01de58"],[]]},{"id":"f96c64d6c1127f02","type":"inject","z":"77ce1e39d14f8570","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":"1","topic":"","payload":"1","payloadType":"num","x":150,"y":80,"wires":[["d7b9b40635550468"]]},{"id":"d7b9b40635550468","type":"change","z":"77ce1e39d14f8570","name":"Reset counter to ZERO at start-up","rules":[{"t":"set","p":"counter","pt":"flow","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":80,"wires":[[]]},{"id":"543a79b51818bc87","type":"inject","z":"77ce1e39d14f8570","name":"","props":[{"p":"payload"}],"repeat":"5","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":150,"y":300,"wires":[["2d6215b8.ac8242"]]},{"id":"a21c12f206b98026","type":"function","z":"77ce1e39d14f8570","name":"Increment the counter","func":"let counter = flow.get(\"counter\") || 0\n\nif (counter < 3) {\n counter = counter + 1;\n}\nelse {\n counter = 0\n}\n\nnode.status({ fill: \"red\", shape: \"ring\", text: \"Counter = \"+counter });\n\nflow.set(\"counter\", counter);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":600,"y":300,"wires":[["ffec11c50d660888","47179848709b368f","0bd994fa22b552f9","1689d8b90a2952a8"]]},{"id":"ffec11c50d660888","type":"function","z":"77ce1e39d14f8570","name":"Decode light-0","func":"let counter = flow.get(\"counter\") || 0\n\nif (counter == 0) {\n node.status({ fill: \"green\", shape: \"dot\", text: \"Light is ON\" });\n msg.payload = 1;\n}\nelse {\n node.status({ fill: \"red\", shape: \"dot\", text: \"Light is OFF\" });\n msg.payload = 0;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":840,"y":300,"wires":[["7ac732e436b4bbbb"]]},{"id":"47179848709b368f","type":"function","z":"77ce1e39d14f8570","name":"Decode light-1","func":"let counter = flow.get(\"counter\") || 0\n\nif (counter == 1) {\n node.status({ fill: \"green\", shape: \"dot\", text: \"Light is ON\" });\n msg.payload = 1;\n}\nelse {\n node.status({ fill: \"red\", shape: \"dot\", text: \"Light is OFF\" });\n msg.payload = 0;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":840,"y":380,"wires":[["5c8efed0c3bdc0c5"]]},{"id":"0bd994fa22b552f9","type":"function","z":"77ce1e39d14f8570","name":"Decode light-2","func":"let counter = flow.get(\"counter\") || 0\n\nif (counter == 2) {\n node.status({ fill: \"green\", shape: \"dot\", text: \"Light is ON\" });\n msg.payload = 1;\n}\nelse {\n node.status({ fill: \"red\", shape: \"dot\", text: \"Light is OFF\" });\n msg.payload = 0;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":840,"y":460,"wires":[["142888aea163b5a9"]]},{"id":"1689d8b90a2952a8","type":"function","z":"77ce1e39d14f8570","name":"Decode light-3","func":"let counter = flow.get(\"counter\") || 0\n\nif (counter == 3) {\n node.status({ fill: \"green\", shape: \"dot\", text: \"Light is ON\" });\n msg.payload = 1;\n}\nelse {\n node.status({ fill: \"red\", shape: \"dot\", text: \"Light is OFF\" });\n msg.payload = 0;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":840,"y":540,"wires":[["d054669d3a7e3f95"]]},{"id":"197f0e9d7a72573a","type":"comment","z":"77ce1e39d14f8570","name":"Change this to 1 hr after you have tested it","info":"","x":240,"y":360,"wires":[]},{"id":"7ac732e436b4bbbb","type":"debug","z":"77ce1e39d14f8570","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1050,"y":300,"wires":[]},{"id":"5c8efed0c3bdc0c5","type":"debug","z":"77ce1e39d14f8570","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1050,"y":380,"wires":[]},{"id":"142888aea163b5a9","type":"debug","z":"77ce1e39d14f8570","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1050,"y":460,"wires":[]},{"id":"d054669d3a7e3f95","type":"debug","z":"77ce1e39d14f8570","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1050,"y":540,"wires":[]},{"id":"b325213ad5a97e0b","type":"comment","z":"77ce1e39d14f8570","name":"Need to edit these function nodes to talk to Home Assistant","info":"","x":980,"y":260,"wires":[]},{"id":"106a671b5c7ed4c8","type":"comment","z":"77ce1e39d14f8570","name":"Put YOUR Lat/Lon values in BigTimer","info":"","x":230,"y":140,"wires":[]}]
It's amazing what a few hours sleep will do to refresh the brain!!
The previous flow had some shortcomings which I think are addressed by this new and improved version.
[{"id":"c62f0b4e734bc6ec","type":"function","z":"7c7ea5f95ec78845","name":"Pass on if Timer is ON","func":"var timer = flow.get(\"timer\");\n\nif (timer == \"on\") {\n msg.payload = 1;\n node.status({ fill: \"green\", shape: \"dot\", text: \"Pass is ON\" });\n return msg;\n}\nelse {\n node.status({ fill: \"red\", shape: \"dot\", text: \"Pass is OFF\" });\n return null;\n}\n","outputs":"1","noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":340,"wires":[["a4c1a128402682fe"]]},{"id":"e42bc3cb603110e9","type":"function","z":"7c7ea5f95ec78845","name":"Timer On/Off","func":"if (msg.payload == 1)\n {\n flow.set(\"timer\",\"on\");\n node.status({fill:\"green\",shape:\"dot\",text:\"Timer is ON\"});\n }\nelse if (msg.payload === 0)\n {\n flow.set(\"timer\",\"off\");\n flow.set(\"counter\",0);\n node.status({fill:\"red\",shape:\"dot\",text:\"Timer is OFF\"});\n }","outputs":"0","noerr":0,"initialize":"","finalize":"","libs":[],"x":310,"y":280,"wires":[]},{"id":"8ed7c0fe3ca85a9f","type":"bigtimer","z":"7c7ea5f95ec78845","outtopic":"","outpayload1":"","outpayload2":"","name":"Main Timer","comment":"","lat":"51.35","lon":"0.0","starttime":"5004","endtime":"5003","startoff":"0","endoff":0,"startoff2":"","endoff2":"","offs":0,"outtext1":"","outtext2":"","timeout":" ","sun":true,"mon":true,"tue":true,"wed":true,"thu":true,"fri":true,"sat":true,"jan":true,"feb":true,"mar":true,"apr":true,"may":true,"jun":true,"jul":true,"aug":true,"sep":true,"oct":true,"nov":true,"dec":true,"day1":0,"month1":0,"day2":0,"month2":0,"day3":0,"month3":0,"day4":0,"month4":0,"day5":0,"month5":0,"day6":"","month6":"","day7":"","month7":"","day8":"","month8":"","day9":"","month9":"","day10":"","month10":"","day11":"","month11":"","day12":"","month12":"","d1":0,"w1":0,"d2":0,"w2":0,"d3":0,"w3":0,"d4":0,"w4":0,"d5":0,"w5":0,"d6":"","w6":"","xday1":"","xmonth1":"","xday2":"","xmonth2":"","xday3":"","xmonth3":"","xday4":"","xmonth4":"","xday5":"","xmonth5":"","xday6":"","xmonth6":"","xday7":"","xmonth7":"","xday8":"","xmonth8":"","xday9":"","xmonth9":"","xday10":"","xmonth10":"","xday11":"","xmonth11":"","xday12":"","xmonth12":"","xd1":"","xw1":"","xd2":"","xw2":"","xd3":"","xw3":"","xd4":"","xw4":"","xd5":"","xw5":"","xd6":"","xw6":"","suspend":false,"random":false,"randon1":false,"randoff1":false,"randon2":false,"randoff2":false,"repeat":true,"atstart":true,"odd":false,"even":false,"x":130,"y":240,"wires":[[],["2782e1a93614e5fb","e42bc3cb603110e9"],[]]},{"id":"5192017706220311","type":"inject","z":"7c7ea5f95ec78845","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"1","topic":"reset","payload":"1","payloadType":"num","x":140,"y":120,"wires":[["52153ea8188aa56b","a4c1a128402682fe"]]},{"id":"52153ea8188aa56b","type":"change","z":"7c7ea5f95ec78845","name":"Reset counter to ZERO at start-up","rules":[{"t":"set","p":"counter","pt":"flow","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":120,"wires":[[]]},{"id":"b94989a9a664bc14","type":"inject","z":"7c7ea5f95ec78845","name":"","props":[{"p":"payload"}],"repeat":"5","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":130,"y":340,"wires":[["c62f0b4e734bc6ec"]]},{"id":"a4c1a128402682fe","type":"function","z":"7c7ea5f95ec78845","name":"Increment the counter","func":"let counter = flow.get(\"counter\") || 0\n\nif (msg.topic == \"reset\") {\n counter = 0\n}\n\nelse if (counter < 3) {\n counter = counter + 1;\n}\nelse {\n counter = 0\n}\n\nnode.status({ fill: \"red\", shape: \"dot\", text: \"Counter = \" + counter });\n\nflow.set(\"counter\", counter);\n\nreturn null;","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":580,"y":340,"wires":[]},{"id":"4e20148836494f6d","type":"function","z":"7c7ea5f95ec78845","name":"Decode light-0","func":"let timer = flow.get(\"timer\") || \"off\";\nlet counter = flow.get(\"counter\") || 0\n\nif ((timer == \"on\") && (counter == 0)) {\n node.status({ fill: \"green\", shape: \"dot\", text: \"Light is ON\" });\n msg.payload = 1;\n}\nelse {\n node.status({ fill: \"red\", shape: \"dot\", text: \"Light is OFF\" });\n msg.payload = 0;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":840,"y":240,"wires":[["588ec8aa0e6ee801"]]},{"id":"47b711902ab2816c","type":"function","z":"7c7ea5f95ec78845","name":"Decode light-1","func":"let timer = flow.get(\"timer\") || \"off\";\nlet counter = flow.get(\"counter\") || 0\n\nif ((timer = \"on\") && (counter == 1)) {\n node.status({ fill: \"green\", shape: \"dot\", text: \"Light is ON\" });\n msg.payload = 1;\n}\nelse {\n node.status({ fill: \"red\", shape: \"dot\", text: \"Light is OFF\" });\n msg.payload = 0;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":840,"y":300,"wires":[["477fd5273c7fc2e5"]]},{"id":"b7a55c3511d252bb","type":"function","z":"7c7ea5f95ec78845","name":"Decode light-2","func":"let timer = flow.get(\"timer\") || \"off\";\nlet counter = flow.get(\"counter\") || 0\n\nif ((timer == \"on\") && (counter == 2)) {\n node.status({ fill: \"green\", shape: \"dot\", text: \"Light is ON\" });\n msg.payload = 1;\n}\nelse {\n node.status({ fill: \"red\", shape: \"dot\", text: \"Light is OFF\" });\n msg.payload = 0;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":840,"y":360,"wires":[["e4ea84e1bd622b7d"]]},{"id":"787f1f6e9d5a7a80","type":"function","z":"7c7ea5f95ec78845","name":"Decode light-3","func":"let timer = flow.get(\"timer\") || \"off\";\nlet counter = flow.get(\"counter\") || 0\n\nif ((timer == \"on\") && (counter == 3)) {\n node.status({ fill: \"green\", shape: \"dot\", text: \"Light is ON\" });\n msg.payload = 1;\n}\nelse {\n node.status({ fill: \"red\", shape: \"dot\", text: \"Light is OFF\" });\n msg.payload = 0;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":840,"y":420,"wires":[["05a440d2ad0cf391"]]},{"id":"24e18aa74574188e","type":"comment","z":"7c7ea5f95ec78845","name":"Change this to 1 hr after you have tested it","info":"","x":220,"y":440,"wires":[]},{"id":"588ec8aa0e6ee801","type":"debug","z":"7c7ea5f95ec78845","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1030,"y":240,"wires":[]},{"id":"477fd5273c7fc2e5","type":"debug","z":"7c7ea5f95ec78845","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1030,"y":300,"wires":[]},{"id":"e4ea84e1bd622b7d","type":"debug","z":"7c7ea5f95ec78845","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1030,"y":360,"wires":[]},{"id":"05a440d2ad0cf391","type":"debug","z":"7c7ea5f95ec78845","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1030,"y":420,"wires":[]},{"id":"dae9429f16cb1d5f","type":"comment","z":"7c7ea5f95ec78845","name":"Need to edit these function nodes to talk to Home Assistant","info":"","x":880,"y":200,"wires":[]},{"id":"a6c0ddbf54892119","type":"comment","z":"7c7ea5f95ec78845","name":"Put YOUR Lat/Lon values in BigTimer","info":"","x":210,"y":180,"wires":[]},{"id":"2782e1a93614e5fb","type":"link out","z":"7c7ea5f95ec78845","name":"Main_Clock_OUT","links":["aa8b532d2facc42f"],"x":255,"y":240,"wires":[]},{"id":"aa8b532d2facc42f","type":"link in","z":"7c7ea5f95ec78845","name":"Clk_IN","links":["2782e1a93614e5fb"],"x":675,"y":240,"wires":[["4e20148836494f6d","47b711902ab2816c","b7a55c3511d252bb","787f1f6e9d5a7a80"]]},{"id":"3a153091578c3e34","type":"comment","z":"7c7ea5f95ec78845","name":"For testing, you'll probably need to set this to every 2 minutes","info":"For testing, you'll probably need to set this to every 2 minutes","x":280,"y":400,"wires":[]}]
In the original flow the lights would change every hour - which is what you wanted. The shortcoming was it could take up-to an hour for a light to go off after sunrise - not very nice.
In this version I'm using the 1-minute output from BigTimer to act as a sort of 'system clock'. This is used by the four decode nodes so they perform a check every minute, which means it would only take a minute after sunrise to turn the lights off - neat eh? Also saves electricity, money and the planet.
The other improvement is all lights are forced OFF when the Timer is "off". I think in the original version there may have been a chance that a light remained "on" at sunrise.
You will need to do some tests and see if there are any edge-cases I've missed. I suggest you set the Inject node, below BigTimer, to repeat every 2-minutes during your initial tests.




