Design Pattern: Time Of Day

Tags: #<Tag:0x00007f0146c3d888> #<Tag:0x00007f0146c3d720> #<Tag:0x00007f0146c3d590>

( ) #21

Hey Robert, that’s sadly not supported:

(Robert) #22

Thanks for the confirmation. I will continue using an additional if statement.

(Robert) #23

@rlkoshak I tried your example rule and noticed that the Astro event related triggers fire 3 times. (I get 3 logs for the EVENING (sunset) trigger). Do you have any clue why this could be happening?

(SiHui) #24

Maybe related to:

(Robert) #25

It’s weird, because the cron triggers from the when clause only get triggered once, and the Astro event based once multiple times.

(Robert) #26

I have created a rule for testing purposes.

rule "TimeOfDay"
	System started or
	Channel 'astro:sun:home:rise#event'   triggered START or
	Channel 'astro:sun:home:set#event'    triggered START or
	Channel 'astro:sun:minus30:set#event' triggered START or
	Time cron "0 0 0,6,23 * * ? *" 
	val logger = 'rules.test.TimeOfDay'
	val msg    = 'De tijd is nu ' + now
	logInfo(logger, msg)

The sun:minus30:set#event sent 3 pushover messages to my phone. So the event triggers the rule 3 times.
Next test will be the sun:home:set#event that will be triggered in half an hour

Update: Yep. That trigger also fired 3 times. Next test: separate rule for sunset event (no or triggers).

rule "TimeOfDay"
	Channel 'astro:sun:home:set#event'    triggered START or
	val logger = 'rules.test.TimeOfDay'
	val msg    = 'De tijd is nu ' + now
	logInfo(logger, msg)

(Rich Koshak) #27

No clue but nothing really changes functionally with the rule as written off it triggers multiple times. It only changes the Time of day when the newly calculated state is different from the current value.

Because I use groups so heavily in rules I almost always try to write them so multiple triggers do not break something.

(Rich Koshak) #28

Here is a link to an expansion of the pattern to include times of year.

(Robert) #29

(Michael) #30

Hi Rich,
I like your tutorial, thanks a lot!
I need little assistance for a further time span. I get from my squeezebox the alarm time (like 05:45) as a string. How can I convert it to use it similar to your examples. I need to define a “wakeup time” which starts 15 minutes before alarm time till alarm time.

Kind regards,

(Rich Koshak) #31

I’m not in a place where I can give you real code.

Look into the joda DateTime classes to figre out how to parse a String into a DateTime object. Once you have that you can use the comparisons and math like above.

You can look at the alarm clock examples (here is a good one) and see about how you can generate an event to trigger the rule at that time.

(Michael) #32

For anybody who is interested in converting a string into a DateTime might be interested in this solution.
sq_alarm_time contains the alarm time, which looks like 05:45.

var DateTime alarmtime = parse(year+"-"+month+"-"+day+"T"+sq_alarm_time.state).minusMinutes(5)
var DateTime wakeuptime = alarmtime.minusMinutes(5)

(Ham Wong) #33

Hi @rlkoshak,

I am now using your Astro version of Time rules, It works great and thanks for your sharing, just one thing making me confuse, I thought it should be a typo mistake,

as I set once vTimeOfDay change will send notification to me, I got notification as below
Today at 5:32 PM Current time of day is now AFTERNOON
Today at 6:29 PM Current time of day is now EVENING
as the time of afternoon is so oddly, I look into your code and found you set as

  val long afternoon_start = (vEvening_Time.state as DateTimeType).calendar.timeInMillis

  case now.isAfter(afternoon_start) && now.isBefore(evening_start): curr = "AFTERNOON"

shouldn’t afternoon_stat = now.withTimeAtStartOfDay.plusHours(12).millis?

sorry if there is any misunerstanding :relaxed:

(Rich Koshak) #34

In my setup, which is the basis for the code I posted above (I didn’t spend the time to simplify it) I use the following time periods:

MORNING    06:00                Sunrise
DAY        Sunrise              Sunset - 90 minutes
AFTERNOON  Sunset - 90 minutes  Sunset
EVENING    Sunset               23:00
BED        00:00                06:00

So the name AFTERNOON is a little misleading. It made more sense at one time as it really covered between 13:00 and Sunset-90 but I readjusted my time periods without changing the name of that state. It might more appropriately be called TWILIGHT like I did in the original rule.

You are not misunderstanding, I just had a confusing name for that time period state.

(Ham Wong) #35

Thanks, as for me read the code is really hard,
with the time chart, it more easily to get understand,
now it all make sense, just change the word for afternoon

(Cody Lee) #36

Hi Rich,
I like your tutorial, thanks a lot!

I get this log when startup
"Error during the execution of startup rule ‘Calculate time of day state’: org.eclipse.smarthome.core.library.types.DateTimeType"
How can I fix it.


(Robert) #37

It’s not Astro binding related, so I created an eclipse issue

(Daniel N.) #38

i have one Problem: DateTime is marked in my code and i get the Error Message:
"DateTime cannot be resolved…
Where do I need to define DayTime?

//–> Tagezeit
val logName = "Tageszeit"
rule "Kalkulieren der Tageszeit"
System started or
Time cron “0 0 5,22 * * ? *” or
Item SunriseTime received update ON or
Item SunsetTime received update ON or
Time cron "0 0 12 * * ? *"

val morning = new DateTime(now.withTimeAtStartOfDay.plusHours(6).millis)

val sunrise = new DateTime((SunriseTime.state as DateTimeType).calendar.timeInMillis)
val afternoon = new DateTime(now.withTimeAtStartOfDay.plusHours(12).millis)
val evening = new DateTime((SunsetTime.state as DateTimeType).calendar.timeInMillis)
val night = new DateTime(now.withTimeAtStartOfDay.plusHours(23).millis)

var currPeriod = "ERROR"
if     (now.isAfter(morning)  && now.isBefore(sunrise))  currPeriod = "Morgen"
else if(now.isAfter(sunrise)  && now.isBefore(afternoon)) currPeriod = "Tag"
else if(now.isAfter(afternoon) && now.isBefore(evening))  currPeriod = "Nachmittag"
else if(now.isAfter(evening)  && now.isBefore(night))    currPeriod = "Abend"
else if(now.isAfter(night))                              currPeriod = "Nacht"

if(DayPhase.state.toString != currPeriod) {
logInfo(logName, “Aktuelle Tagesphase ist: " + currPeriod)
sendMail(“Mailadress”,”[openHAB INFO] - Tageszeit wurde aktualisiert!","Die aktuelle Tageszeit ist: " + currPeriod)

(Rich Koshak) #39

What version of openHAB are you running?

If you are running openHAB 1.x you need to add

import org.joda.DateTime

at the top of your .rules file.

If you are running openHAB 2.x it should be imported automatically. However, you can try adding the import and see if that makes a difference.

(Daniel N.) #40

I run Openhab2.
if i add “import org.joda.DateTime” i get the Error: "org.joda.DateTime cannot be resolved to a type"
I use the eclipse Smarthome desinger.

Thanks, now its works :slight_smile: