Is there a simpler way to do sunrise/sunset?

524 views
Skip to first unread message

Maurits van Dueren den Hollander

unread,
Aug 12, 2019, 6:41:33 AM8/12/19
to sonof...@googlegroups.com
Hello all

There must be a simpler way to do turn on a light at night
And yes, I did read the rule example on sunset/sunrise

Only a set of timers do not work, because I do not want the lights on entire night.
Just from SunSet to 22h30 and again from 06h00 to SunRise
Seems simple enough, and the relevant 4 timers are easily made. 

BUT, what if the sun sets after 22h30, like in summer?
then the timer turn off the light at 22h30, and then another timer on again at SunSet, so it stays on all night



I did find a solution. But it seems convoluted and bulky. Surely there must be a simpler method?
It seems such a basic requirement, people must have struggled with this before.
Anyone with a better idea?


My solution so far:

rule1
on Time#Initialized do event chkSun endon
on Clock#Timer do event chkSun endon
on event#chkSun do backlog var1 0; event chkSunrise=%time%; event chkSunset=%time%; event chk06h=%time%; event chk22h=%time%; event setPower endon
on event#chkSunset>=%sunset% do var1 1 endon
on event#chkSunrise<%sunrise% do var1 1 endon
on event#chk06h<360 do var1 0 endon
on event#chk22h>=1350 do var1 0 endon
on event#setPower do power1 %var1% endon


Annotated:

# when device restarts, recalculate if light should be on or off
on Time#Initialized do event chkSun endon

# Timer calls Rule instead of On
on Clock#Timer do event chkSun endon

on event#chkSun do backlog 

#assume off
var1 0; 

#If before sunrise, turn on
event chkSunrise=%time%; 

#If past sunset, turn on
event chkSunset=%time%; 

#but if before 06h00, do not turn on
event chk06h=%time%; 

#or if after 22h30, do not turn on
event chk22h=%time%; 

#perform final on/off state
event setPower endon


Michael Ingraham

unread,
Aug 12, 2019, 7:50:13 AM8/12/19
to Maurits van Dueren den Hollander, SonoffUsers
I'll be stealing leveraging this for the Tasmota wiki ;-)

Mike

Michael Ingraham
Spartanburg, SC


--
You received this message because you are subscribed to the Google Groups "SonoffUsers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sonoffusers...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/sonoffusers/a6d9c74e-8250-4b27-a23e-91b67be1fb42%40googlegroups.com.

Maurits van Dueren den Hollander

unread,
Aug 12, 2019, 8:01:55 AM8/12/19
to SonoffUsers
Well I'm honoured, I guess. 
But I was/am still hoping on a better idea. Currently still tinkering with it myself.

Michael Ingraham

unread,
Aug 12, 2019, 8:38:40 AM8/12/19
to SonoffUsers
For your use case, I don't think you can handle all the scenarios with any simpler a rule set. You could use Sunrise/Sunset timers to trigger the rules that set `var1 1` (`on Clock#Timer=N do var1 1 endon` where N are your sunset and sunrise timers). But, in my opinion, if you place all the "logic" in one place (i.e., the rule set), it is easier to keep track of all the moving parts. Otherwise you have to have commands (or manually configure) to arm the timers, plus you have to set the rules anyway for the rest of the logic. I suppose you could include your Clock#Timer in a rule instead of whatever timer you have now by having an `On Time#Minute==ZZZ` to consolidate everything. With this rule, do you still actually need the Tasmota timer?

Mike

Andreas Bäck

unread,
Aug 29, 2019, 1:54:21 PM8/29/19
to SonoffUsers
I tried to use "Turn On Light Before Dawn and At Dusk" in the cookbook but it will only turn on ligt at reset and sunset as the timers are missing. Need to add 3 lines, but then start to be longer that a Rule can be
Rule1

on Time#Initialized do event chkSun endon
on Time#Minute=%sunset% do event chkSun endon
on Time#Minute=%mem2% do event chkSun endon
on Time#Minute=%sunrise% do event chkSun endon
on Time#Minute=%mem1% do event chkSun endon
on event#chkSun do backlog var1 0; event chkSunrise=%time%; event chkSunset=%time%; event chkmorn=%time%; event chknight=%time%; event setPower endon

on event#chkSunrise<%sunrise% do var1 1 endon
on event#chkSunset>=%sunset% do var1 1 endon
on event#chkmorn<%mem1% do var1 0 endon
on event#chknight>=%mem2% do var1 0 endon

on event#setPower do power1 %var1% endon

Michael Ingraham

unread,
Aug 29, 2019, 2:01:06 PM8/29/19
to SonoffUsers
Rule1
on
Time#Initialized do event chkSun endon
on
Time#Minute=%sunset% do event chkSun endon
on
Time#Minute=%mem2% do event chkSun endon
on
Time#Minute=%sunrise% do event chkSun endon
on
Time#Minute=%mem1% do event chkSun endon
Rule2

on
event#chkSun do backlog var1 0; event chkSunrise=%time%; event chkSunset=%time%; event chkmorn=%time%; event chknight=%time%; event setPower endon
on
event#chkSunrise<%sunrise% do var1 1 endon
on
event#chkSunset>=%sunset% do var1 1 endon
on
event#chkmorn<%mem1% do var1 0 endon
on
event#chknight>=%mem2% do var1 0 endon
on
event#setPower do power1 %var1% endon



Backlog Rule1 1; Rule2 1

Maurits van Dueren den Hollander

unread,
Aug 29, 2019, 3:33:40 PM8/29/19
to SonoffUsers
Yes, definitely a little nicer in variable names and memory.
My ego is still boasting it as 'mine' though...

Laurent Dong

unread,
Sep 16, 2019, 10:21:28 AM9/16/19
to SonoffUsers
You do not need to set any timer. One rule is enough:
rule1
on Time#Initialized do ruletimer1 3 endon
on Rule#Timer=1 do
  backlog
  if (%time% < %sunrise% AND %time% > 360 OR %time% > %sunset% AND %time% < 1350)
     power on
  else
     power off
  endif;
  ruletimer1 300
endon

It will check time every 5 minutes. If you want to do it every minutes, simply change 300 to 60.
Of course, you need to compile your own binary with IF and EXPRESSION support.

Maurits van Dueren den Hollander

unread,
Sep 16, 2019, 1:50:38 PM9/16/19
to sonof...@googlegroups.com
Interesting.  I am very intrigued about that if / and / or statement of yours.
Either I have missed the obvious straightforward solution, or that was not yet possible when I first wrote my code in v6.1


Anyway, on your "every 5 minutes"
One disadvantage is that it does not allow manual overrides.

In my case, I also have a switch next to one of the lights. When I manually turn it on, it stays on till the next scheduled timer.
(and also, by means of KNX all other lights are switched on)
With this "every 5 minute" setup, my manual override would be overwritten every 5 minutes
So depends on what you want.

Anyway, if you do want a every 5 minute situation, this would be even more straightforward:
with your code (but I did not yet test your if statement)

rule1
on Time#Minute|5 do
  backlog
  if (%time% < %sunrise% AND %time% > 360 OR %time% > %sunset% AND %time% < 1350)
     power on
  else
     power off
  endif;
endon


Michael Ingraham

unread,
Sep 16, 2019, 2:00:59 PM9/16/19
to SonoffUsers
FYI IF/ELSE & AND/OR are Rules features added to Tasmota by Laurent only in the past few days.

Maurits van Dueren den Hollander

unread,
Sep 16, 2019, 2:21:24 PM9/16/19
to SonoffUsers
Cool. Checking it out now...

Laurent Dong

unread,
Sep 16, 2019, 2:52:35 PM9/16/19
to sonof...@googlegroups.com
Yes, you are right. Using Time#Minute|5 is more straight than my version. If you still want to keep the current logical of manually switching, you can use your timer to trigger this checking. Or you can add more condition in IF statement like:
IF (%time%<%sunrise% AND %time%>360 AND %time%-360<=5 OR %time%>%sunset% AND %time%<1350 AND %time%-%sunset%<=5)

BTW: BACKLOG before IF statement can be taken out because the whole IF statement (IF ... ENDIF) will be treated as one command.

Maurits van Dueren den Hollander

unread,
Sep 16, 2019, 3:55:21 PM9/16/19
to sonof...@googlegroups.com
Well, when using exact timers, the operators need to be a little more exact in regards to >= versus >
So the core if would becomes like this:

   if (%time% >= 360 and %time% < %sunrise% or %time% >= %sunset% and %time% < 1350)

That could be used for several variants.

- Laurent's "Every 5 (or 1) minutes" variant (very simple)

Rule1
on Time#Minute do if ( %time% >= 360 and %time% < %sunrise% or %time% >= %sunset% and %time% < 1350 )
  power on else power off endif endon

Rule1 1

- Michael's "Timer, but all timer logic in code" variant

Backlog mem1 360; mem2 1350

Rule1
on Time#Initialized do event chkSun endon
on Time#Minute=%mem1% do event chkSun endon
on Time#Minute=%sunrise% do event chkSun endon
on Time#Minute=%sunset% do event chkSun endon
on 
Time#Minute=%mem2% do event chkSun endon

Rule2
on event#chkSun do if ( %time% >= %mem1% and %time% < %sunrise% or %time% >= %sunset% and %time% < %mem2% )
  power on else power off endif endon

Backlog Rule1 1; Rule2 1

BTW: small disclaimer, this still fails when the sun sets after midnight. Roughly in the upper half of Scandinavia or Canada/Alaska.
Lucky my use case is just south of mid-Sweden :)

cybe...@gmail.com

unread,
Oct 29, 2022, 1:20:37 PM10/29/22
to TasmotaUsers
Hi Mike

sorry for awakening this very old post.
After below post by you, my suggestion ended up in the Wiki, and some time later was even improved. I even copied back the improved version
I assume you were involved in this.

However, recently I came up with a completely different method to so this.
It is based on the new %timerN% variables, and has the advantage after you make the rule, you can set and change the times in the Web-UI, for less savvy users

I was wondering if it should also end up in the Wiki, maybe even replace the %mem% based one.
But I have no idea on how and who decides what to put in the documentation

BTW: I also have a version that even works for high up north, in the lands of sunsets past midnight, or even permanent daylight and permanent nighttime.
But that is a little bit more advanced. Below the simple one, works for all cases where midnight is not passed

##################################
# New generation of sun timer, using the new %timerN% variables
#
# Program the schedule timers to turn off/on with the correct time or sun.
# Odd timers 1,3 interpreted by the rules as ON, even timers 2,4 are OFF
# Example times:
#       Timer1 ON  at 06h00   (unless if past timer 2)
#       Timer2 OFF at SunUp   (always)
#       Timer3 ON  at SunDown (unless if past timer 4)
#       Timer4 OFF at 23h00   (always)

Timers 1
Timer1 {"Enable":1,"Mode":0,"Time":"06:00","Window":0,"Days":"1111111","Repeat":1,"Output":2,"Action":3}
Timer2 {"Enable":1,"Mode":1,"Time":"00:00","Window":0,"Days":"1111111","Repeat":1,"Output":2,"Action":3}
Timer3 {"Enable":1,"Mode":2,"Time":"00:00","Window":0,"Days":"1111111","Repeat":1,"Output":2,"Action":3}
Timer4 {"Enable":1,"Mode":0,"Time":"23:00","Window":0,"Days":"1111111","Repeat":1,"Output":2,"Action":3}

Rule1
ON Time#Initialized DO event checktime=%time% ENDON
ON Clock#Timer DO event checktime=%time% ENDON
ON event#checktime DO %var10% 0 ENDON
ON event#checktime>=%timer1% DO var10 1 ENDON
ON event#checktime>=%timer2% DO var10 0 ENDON
ON event#checktime>=%timer3% DO var10 1 ENDON
ON event#checktime>=%timer4% DO var10 0 ENDON
ON event#checktime DO Power1 %var10% ENDON
ON event#debug DO Backlog var10; var10 %timer1%; var10 %timer2%; var10 %timer3%; var10 %timer4%; var10 %var10%; ENDON
Rule1 1
Reply all
Reply to author
Forward
0 new messages