Design Pattern: Time Of Day

I use the JavaScript library “Ephemeris Time Of Day” by @rlkoshak. It is very great.

There is only one disadvantage: If I have for example next week vacation, I have to enter this in the Ephemeris XML file. So that during my vacation the holiday times are used.

However, I would like to have a switch that I can turn on during my vacation. If the switch is ON, the holiday times should be used for the Time of Day calculation, if the switch is OFF, the default times should be used.

How could something like this be realized?

1 Like

Add a Switch and change the function that determines the type of day too check the switch and return the proper day type when it’s on.

But as I designed it, modifying Ephemeris is how I intended this short of use case to be handled.

@rlkoshak Thanks for all your scripts as usual. I successfully implemented the Java-version of Time Of Day. I aslo followed your guide as how to set the Items with a fixed value.

Having said that, there is something weird going on with my timings:
Item Default_Day should start when astro:sun:home:rise#start event is triggered. When I am in the ‘Items view’ it has a value of 2021-05-25T05:35:00.000+02:00 (sunrise is at 05:35 local today).
Item Default_Morning should start at 6 AM and has a value of 2021-05-21T06:00:00.000+00:00

When I implemented and ran the rule around 11:30 AM, I got Morning returned as TimeOfDay string. It looks like the system is either adding 2hrs to 06:00:00 (and thus 08:00:00 local) or subtracts 2hrs from the rise#start event (and thus 03:35:00). Or is this expected behaviour due to the fact that Morning is now after Sunrise? If the latter is the case, how do I fix this? It was working OK on OH2.5 for me.

My setup uses docker on a synology nas. Nas time is set to Europe/Amsterdam, Openhab is set to Europe/Amsterdam.

Does anybody run into the same issues?

Side note: I am using Morning, Day, Afternoon, Evening and Night as states

As you’ve already found out, Java has it’s own timezone setting as well, and it matters.
Does this problem still persist now you’ve fixed that?

@rossko57 I did find out and now all Items show +02:00 for the timezone. So at least that is correct.

The only thing now is, the rise#start is before the time I set for the Morning to start. So the whole day it shows it is ‘morning’. I know when I was on OH2.5 that the logic/rule was written in such way that it would skip the morning part and jump straight to ‘day’…

I’m not sure that really was the way you’re describing with OH 2.5. I mean, it’s currently doing exactly as it should, triggering events in sequence. How should the logic know that you prefer to have “Morning” skipped if it’s after “Day” unless you tell it to programmatically?

You could, for instance, run a rule every night that checks if Morning is after Day and disable Morning for that day if that returns true.

It was written like this in the .rules file:

switch now {
        case now.isBefore(morning_start):                                   curr = "NIGHT"
        case now.isAfter(morning_start)   && now.isBefore(day_start):       curr = "MORNING"
        case now.isAfter(day_start)       && now.isBefore(afternoon_start): curr = "DAY"
        case now.isAfter(afternoon_start) && now.isBefore(evening_start):   curr = "AFTERNOON"
        case now.isAfter(evening_start)   && now.isBefore(night_start):     curr = "EVENING"
        case now.isAfter(night_start):                                      curr = "NIGHT"
  }

Say it is 06:00 and the rule fires. Morning is set to commence at 06:00 and sunrise is at 05:35.
First case is negative, second case is negative, third case is positive. So from night to day…

Are you going to rewrite it to do what you want?

Maybe in OH2 you had earliest/latest modifiers on your Astro events Things, to influence behaviour.

This is indeed a difference between the Rules DSL version and the Python/JavaScript versions. The reason is, as you show, the isBefore/isAfter comparisons are no longer hard coded. If they were that would kind of break these versions of the rule’s whole reason for being. The point is that they can be wholly configured using Items and Ephemeris without modifying the rule.

In short, it’s going to schedule the times of day in the order of the times the Items carry.

The way to avoid the problem where times of day swap places due to sunrise/sunset changing places is to do as rossko57 suggests and set the earliest/latest on the Astro channels so sunrise never occurs after day_start.

Thanks both for the replies. I now know it is just the way it is. Could have been a bug. I dug into the rule a bit (Java is not my best) and noticed the beauty of it. You could just add or delete as many items as you like without modifying the rule at all :pray: :muscle:

I didn’t use the ‘earliest’ on OH2 because I ever had to. Reason being the Switch - Case situation. I have now configured this (earliest is 06:01 to avoid both items to be at 06:00) and just live with the few weeks of the year where sunsrise is actually a little earlier :grinning:

1 Like
// Weekend day, notice that not all the states are listed, the unlisted states are skipped

Does this mean it would revert to Default or does it mean if the states aren’t there, it will not get to that specific state although it is in the Default?

It’s means that the time off day states for Default and Weekend are completely independent. If it’s not defined in the items for weekend, it didn’t happen on weekends.

I have imported ephemTimeOfDay.yml as the rule, and if i manually run it the ‘TimeOfDay’ changes correctly. How can i make ephemTimeOfDay rule run all the time.

The OP says “Switch back to the design tab and set a “Schedule” tag and the rule will show up in the calendar under Schedule”. I tried to add a schedule tag at the bottom of the rule like the screenshot below, but it doesnt get saved.

How can i make this rule to work in the background?

Ok, i can see from the log that TimeOfDay is changing. However, the schedule comment is above is still not clear.

At midnight TimeOfDay has become ‘Day’. Here is the log,

2021-06-01 00:00:32.412 [INFO ] [openhab.model.script.Rules.TimeOfDay] - Today is a default day.
2021-06-01 00:00:32.529 [INFO ] [openhab.model.script.Rules.TimeOfDay] - Moved Default_Morning to today.
2021-06-01 00:00:32.536 [INFO ] [openhab.model.script.Rules.TimeOfDay] - Moved Default_Bed to today.
2021-06-01 00:00:32.537 [INFO ] [openhab.model.script.Rules.TimeOfDay] - Moved Default_Night to today.
2021-06-01 00:01:02.874 [INFO ] [openhab.model.script.Rules.TimeOfDay] - The current time of day is DAY

This is what TimesOfDay group shows for its members,

Any idea why the rule became Day at midnight when the Default_Day is supposed to start at 05:53am?

No rules run “all the time.” They run in response to the events defined under “When”. In this case it runs when OH first starts up, one minute after midnight, and when any member of TimesOfDay change state.

Once entered you need ot hit <enter>. Then it will show up in the space above where you typed in a blue oval.

Why do the datetimes for Default_Day and Default_Evening appear different from the other three? That could be a clue, particularly if those are being shown as times in a different time zone.

What was the time of day immediately before the rule ran at midnight?

Thanks, that did the trick.

The log doesnt have the TimeOfDay before midnight. The items on their own show the full datetime string with TimeZone, however in a group they show up differently.

The timezone is consistent in the item definitions. The Default_Day item is linked to Astro binding and it doesnt show the timezone.

I will see what happens at midnight today.

There will be a log statement at the last time of day before midnight. Every time the state machine transitions to a new state you’ll see something like “Transitioning time of day from
BED to NIGHT.” Based on your Items that log statement will be around 23:30, 30 minutes before the rule runs a little after midnight to calculate the new timers for the new day.

You have to look at all the logs from the whole day to make sense of what it’s doing, not just the few lines that are around midnight.

Turn up the logging to DEBUG for that rule (either modify the logging level for the rule in log4j.xml or edit the rule and change the log.debug to log.info.

Bindings can supply default state descriptions to linked Items; there’s probably nothing sinister about different display formats for linked against unlinked Items.
If you needed a pretty user-facing UI display, you’d probably set your own Item state descriptions anyway.

I moved my openhab installation from an x86 server to a raspberry pi. I use the backup and restore script to move the files.

Whenever i run the javascript ‘ephemTimeOfDay’ rule, i get warning messages,

2021-06-20 21:16:47.307 [WARN ] [de.jollyday.util.ClassLoadingUtil   ] - Could not load class with current threads context classloader. Using default. Reason: ClassNotFoundException: de.jollyday.impl.DefaultHolidayManager cannot be found by org.apache.aries.jax.rs.whiteboard_1.0.9
2021-06-20 21:16:47.316 [WARN ] [de.jollyday.util.ClassLoadingUtil   ] - Could not load class with current threads context classloader. Using default. Reason: ClassNotFoundException: de.jollyday.datasource.impl.XmlFileDataSource cannot be found by org.apache.aries.jax.rs.whiteboard_1.0.9
2021-06-20 21:16:47.338 [WARN ] [de.jollyday.util.XMLUtil            ] - Could not create JAXB context using the current threads context classloader. Falling back to ObjectFactory class classloader.
2021-06-20 21:16:47.452 [WARN ] [de.jollyday.util.ClassLoadingUtil   ] - Could not load class with current threads context classloader. Using default. Reason: ClassNotFoundException: de.jollyday.parser.impl.FixedParser cannot be found by org.apache.aries.jax.rs.whiteboard_1.0.9
2021-06-20 21:16:47.460 [WARN ] [de.jollyday.util.ClassLoadingUtil   ] - Could not load class with current threads context classloader. Using default. Reason: ClassNotFoundException: de.jollyday.parser.impl.ChristianHolidayParser cannot be found by org.apache.aries.jax.rs.whiteboard_1.0.9
2021-06-20 21:16:47.463 [WARN ] [de.jollyday.util.ClassLoadingUtil   ] - Could not load class with current threads context classloader. Using default. Reason: ClassNotFoundException: de.jollyday.parser.impl.IslamicHolidayParser cannot be found by org.apache.aries.jax.rs.whiteboard_1.0.9
2021-06-20 21:16:47.541 [INFO ] [openhab.model.script.Rules.TimeOfDay] - Today is a default day.
2021-06-20 21:17:18.527 [INFO ] [openhab.model.script.Rules.TimeOfDay] - The current time of day is EVENING
# java --version
openjdk 11.0.11 2021-04-20 LTS
OpenJDK Runtime Environment Zulu11.48+21-CA (build 11.0.11+9-LTS)
OpenJDK Client VM Zulu11.48+21-CA (build 11.0.11+9-LTS, mixed mode)

Any idea what could be the issue?