There are a number of different approaches. The gotcha is that I think that because you have several time periods a day and those time periods are not necessarily the same day to day complicates matters. So my questions are, how different is one day to the next? Is every day different or is it mainly different for weekdays versus weekends? Should the start or stop of any of these times be relative to sunrise or sunset?
Let’s assume the worst and that each day has four periods and the start or stop time of each period varies from day to day.
I can think of a few ways to do this but I’m not sure how satisfying they will be. My first attempt would probably be to expand the approach I describe here.
The tl;dr version is I would create Swtich Items that represent each of the timer periods (e.g. Morning, Day, Evening, Night). Then I would use rules with cron or Astro based (for sunrise and sunset) triggers to turn on or off the proper switches. Then anything that depends on time either triggers on these switches or checks the state of these switches.
However, that could potentially result in up to 29 rules. Though in practice I think you will find that you probably would only need around 10 rules as most days the time periods would be the same.
Another approach could be to use timers that get set at midnight and on system started to trigger the timer period switches. This approach might be a little more compact code wise and I don’t think it would take any more code than you are already facing trying to set up a data structure. It would be something like:
val morningTimer = null
val dayTimer = null
val eveningTimer = null
val nightTimer = null
// lambda, will help us cut down on lines of code below
val Functions$Function4 setTime = [ State m, State d, State e, State n |
Morning.sendCommand(m)
Day.sendCommand(d)
Evening.sendCommand(e)
Night.sendCommand(n)
]
rule "Create Time of Day Timers"
when
System started or
Timer cron "0 0 0 * * ? *" // a little after midnight
then
// Sunday
if(now.getDayOfWeek == 0) { // NOTE: the DSL's switch statements do NOT fall through like switch statements in C/C++/Java so I just use if statements
morningTimer = createTimer(now.plusMinutes(360), [| setTime.apply(ON, OFF, OFF, OFF) ] // 0600
dayTimer = createTimer(now.plusMinutes(510), [| setTime.apply(OFF, ON, OFF, OFF) ] // 0830
eveningTimer = createTimer(now.plusMinutes(1080), [| setTime.apply(OFF, OFF, ON, OFF) ] // 1800
nightTimer = createTimer(now.plusMinutes(1380), [| setTime.apply(OFF, OFF, OFF, ON) ] // 2300
}
// Monday
else if(now.getDayOfWeek == 1) {
...
Obviously for days that you want the same start times just add ||'s to the if statements rather than duplicating code. now also has a plusHours method. If you want to use the Astro binding to control something (e.g. set evening to start at sunset) you can use the Astro actions instead of now.plus to set the timer.