Design Pattern: Time Of Day

Tags: #<Tag:0x00007f0148faca58> #<Tag:0x00007f0148fac850> #<Tag:0x00007f0148fac710>

(Rich Koshak) #142

I really liked this approach. When I rewrite the op might adopt it. I certainly will do so in my own implementation. I may not above because I often reference this often when helping others with time conversion and comparison problems. I’ll have to think on it.

As far as I’m aware all of those problems have been fixed. I’m usually not in favor of polling in rules and go to great lengths to avoid it. But it does avoid problems in this case when Astro has a bug.

Thanks for posting!

(druciak) #143

Well it happened to me recently, I am currently on January snapshot. Not sure if this is a bug in Astro or OH2, I just want to have it bulletproof, event at cost of running the rule every minute.

(Rich Koshak) #144

If it occurred in a recent snapshot you should file an issue.

(Jeff Haskel) #145

I have been following the threads for Time Of Day adding / removing code from a useful set of periods
yet when I save the rule and let it run, I get the initial messages then nothing no errors just no update
what else can i monitor. is there a way to enable detailed debug/errors from the code you are working on currently

(Rich Koshak) #146

Added lot is logging to your rule and look in events.log to verify that the events that indicate a change from one time period to another are occuring.

(Jeff Haskel) #147

It appears any error created in rules are not being reported and dies silently, I must have turned off errors for
the rule processor if thats possible ?

(Rich Koshak) #148

Unlikely and do you know it is an error? The rule doesn’t do anything if it doesn’t think the time of day had changed.

(nicolas) #149

I have an issue using vTimeOfDay.

2018-07-07 01:16:31.591 [INFO ] [clipse.smarthome.model.script.lights] - Calculating time of day...
2018-07-07 01:16:31.807 [INFO ] [clipse.smarthome.model.script.lights] -  morning_start is 2018-07-07T06:00:00.000-07:00
2018-07-07 01:16:31.820 [INFO ] [clipse.smarthome.model.script.lights] -  night_start is 2018-07-07T23:00:00.000-07:00
2018-07-07 01:16:31.835 [INFO ] [clipse.smarthome.model.script.lights] -  bed_start is 2018-07-07T00:00:00.000-07:00
2018-07-07 01:16:31.840 [INFO ] [clipse.smarthome.model.script.lights] - vSunrise_Time.state is NULL
2018-07-07 01:16:31.858 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Error during the execution of startup rule 'Calculate time of day state': Could not
cast NULL to org.eclipse.smarthome.core.library.types.DateTimeType; line 35, column 33, length 35

The fact that vSunrise_Time.state is NULL makes me think that my binding does not work well.

Any idea of what I can do to progress in my debug?

Thank you by advance.

(Rich Koshak) #150

Do you have the astro building installed? Do you have a Thing defined? Is the right channel from the Thing linked to the Item?

(nicolas) #151

Thank you for your reply.

You asked the good question.


I had home instead of local.

(Hector G) #152

Can anyone post the file that is mentioned in the original post by rlkoshak?

String vTimeOfDay "Current Time of Day [MAP(]" <tod>

Trying to figure out what that map looks like so that I can better follow this DP.

(Vincent Regaud) #153


From:Comprehensive Wunderground using HTTP Binding Example

With a search for in the forum…


# Pressure: Note, if you have uninitialzed Items they may be transformed to "falling"

# Cloudy or not
Light\ Drizzle=true
Heavy\ Drizzle=true

Light\ Rain=true
Heavy\ Rain=true

Light\ Snow=true
Heavy\ Snow=true

Light\ Snow\ Grains=true
Heavy\ Snow\ Grains=true
Snow\ Grains=true

Light\ Ice\ Crystals=true
Heavy\ Ice\ Crystals=true
Ice\ Crystals=true

Light\ Ice\ Pellets=true
Heavy\ Ice\ Pellets=true
Ice\ Pellets=true

Light\ Hail=true
Heavy\ Hail=true

Light\ Mist=true
Heavy\ Mist=true

Light\ Fog=true
Heavy\ Fog=true

Light\ Fog\ Patches=true
Heavy\ Fog\ Patches=true
Fog\ Patches=true

Light\ Smoke=false
Heavy\ Smoke=true

Light\ Volcanic\ Ash=false
Heavy\ Volcanic\ Ash=true
Volcanic\ Ash=true

Light\ Widespread\ Dust=false
Heavy\ Widespread\ Dust=true
Widespread\ Dust=true

Light\ Sand=false
Heavy\ Sand=true

Light\ Haze=false
Heavy\ Haze=true

Light\ Spray=false
Heavy\ Spray=false

Light\ Dust\ Whirls=false
Heavy\ Dust\ Whirls=true
Dust\ Whirls=false

Light\ Sandstorm=false
Heavy\ Sandstorm=true

Light\ Low\ Drifting\ Snow=true
Heavy\ Low\ Drifting\ Snow=true
Low\ Drifting\ Snow= true

Light\ Low\ Drifting\ Widespread\ Dust=true
Heavy\ Low\ Drifting\ Widespread\ Dust=true
Low\ Drifting\ Widespread\ Dust=true

Light\ Low\ Drifting\ Sand=true
Heavy\ Low\ Drifting\ Sand=true
Low\ Drifting\ Sand=true

Light\ Blowing\ Snow=true
Heavy\ Blowing\ Snow=true
Blowing\ Snow=true

Light\ Blowing\ Widespread\ Dust=true
Heavy\ Blowing\ Widespread\ Dust=true
Blowing\ Widespread\ Dust=true

Light\ Blowing\ Sand=true
Heavy\ Blowing\ Sand=true
Blowing\ Sand=true

Light\ Rain\ Mist=true
Heavy\ Rain\ Mist=true
Rain\ Mist=true

Light\ Rain\ Showers=true
Heavy\ Rain\ Showers=true
Rain\ Showers=true

Light\ Snow\ Showers=true
Heavy\ Snow\ Showers=true
Snow\ Showers=true

Light\ Snow\ Blowing\ Snow\ Mist=true
Heavy\ Snow\ Blowing\ Snow\ Mist=true
Snow\ Blowing\ Snow\ Mist=true

Light\ Ice\ Pellet\ Showers=true
Heavy\ Ice\ Pellet\ Showers=true
Ice\ Pellet\ Showers=true

Light\ Hail\ Showers=true
Heavy\ Hail\ Showers=true
Hail\ Showers=true

Light\ Small\ Hail\ Showers=true
Heavy\ Small\ Hail\ Showers=true
Small\ Hail\ Showers=true

Light\ Thunderstorm=true
Heavy\ Thunderstorm=true

Light\ Thunderstorms\ and\ Rain=true
Heavy\ Thunderstorms\ and\ Rain=true
Thunderstorms\ and\ Rain=true

Light\ Thunderstorms\ and\ Snow=true
Heavy\ Thunderstorms\ and\ Snow=true
Thunderstorms\ and\ Snow=true

Light\ Thunderstorms\ and\ Ice\ Pellets=true
Heavy\ Thunderstorms\ and\ Ice\ Pellets=true
Thunderstorms\ and\ Ice\ Pellets=true

Light\ Thunderstorms\ with\ Hail=true
Heavy\ Thunderstorms\ with\ Hail=true
Thunderstorms\ with\ Hail=true

Light\ Thunderstorms\ with\ Small\ Hail=true
Heavy\ Thunderstorms\ with\ Small\ Hail=true
Thunderstorms\ with\ Small\ Hail=true

Light\ Freezing\ Drizzle=true
Heavy\ Freezing\ Drizzle=true
Freezing\ Drizzle=true

Light\ Freezing\ Rain=true
Heavy\ Freezing\ Rain=true
Freezing\ Rain=true

Light\ Freezing\ Fog=true
Heavy\ Freezing\ Fog=true
Freezing\ Fog=true

Patches\ of\ Fog=true
Shallow\ Fog=true
Partial\ Fog=true
Partly\ Cloudy=true
Mostly\ Cloudy=true
Scattered\ Clouds=false
Small\ Hail=true
Funnel\ Cloud=true
Unknown\ Precipitation=true

(Hector G) #154

@vzorglub Thank you, I had tried searching only on this post and didn’t find anything here but didn’t think to check the forum since I assumed the map was specific to the Time Of Day design pattern. I appreciate the quick response though! Thank You

(Rich Koshak) #155

As mentioned in the What is a DP link in the OP, a DP is not necessarily a complete and wholly self contained example. Above all the does is just take the all uppercase states (e.g DAY) and makes them lower case (e.g. day) for the sitemap

(Hector G) #156

Thanks Rick! Working on getting this implemented now. Makes sense.

(Ahmad Yazan Tibi) #157

Thanks for your helpful and informative design patterns,

Here I want to ask why you use .millis in comparison switch:

switch now {
  	case now.isAfter(morning_start.millis)

(Rich Koshak) #158

It’s left over from a time when morning_start et. al. were not Joda DateTime Types. It is not needed and I missed removing them the last time I edited the DP.

I updated the OP. Thanks for pointing out this oversight!

(Scott Rushworth) #159

Here is a version using JSR223-Jython (w/ openhab2-jython modules)…

from org.slf4j import Logger, LoggerFactory
from openhab.triggers import time_triggered
from org.joda.time import DateTime
from org.joda.time import Interval
log = LoggerFactory.getLogger("org.eclipse.smarthome.model.script.Rules")

@time_triggered("0 0 7 * * ?")
@time_triggered("0 0 9 * * ?")
@time_triggered("0 55 17 * * ?")
@time_triggered("0 0 21 * * ?")
@time_triggered("0 0 23 * * ?")
def updateMode():
    #log.debug("JSR223: Update Mode")
    modeIntervals = {
        "Morning" : Interval(,0,0,0),,0,0,0)),
        "Day" : Interval(,0,0,0),,55,0,0)),
        "Evening" : Interval(,55,0,0),,0,0,0)),
        "Night" : Interval(,0,0,0),,0,0,0))
    newMode = "Late Night"
    for mode in list(modeIntervals.keys()):
        if modeIntervals.get(mode).contains(
            newMode = mode
        log.debug("JSR223: Update Mode: interval=[{}], name=[{}]".format(modeIntervals.get(mode),mode))
    if items["Mode"] != StringType(newMode):
        log.debug("JSR223: Update Mode: Mode changed to [{}]".format(newMode))
        log.debug("JSR223: Update Mode: Job ran but Mode did not need to be changed [{}]".format(newMode))

And I add this to the end of the script file so that this runs on startup and when the file is saved, instead of adding a Startup trigger for it…


Jython scripting examples using lucid, an openHAB 2.x jsr223 Jython helper library
(Rich Koshak) #160

Thanks for posting this. A couple of questions to make sure I’m not missing it.

  • I see cron triggers but not Astro event triggers. Are they there and I’m just not good enough with it to recognize them? Is DateTimeType easy to convert to DateTime in JSR223 (e.g. new DateTime(Sunset.state.toString))

  • Mode is the name of the Item? It’s the equivalent of vTimeOfDay in the OP?

  • Does this run at System start/when the file is loaded?

(Scott Rushworth) #161

I don’t have Astro triggers… our time of day intervals are all time driven. Channel triggers can be used too, but there is no decorator setup for them. DateTimeType conversion is the same…

if items["Calendar_Upcoming_Gymnastics"] != UnDefType.UNDEF and Interval(Duration(TimeUnit.DAYS.toMillis(1)),DateTime(items["Calendar_Upcoming_Gymnastics"].zonedDateTime.toInstant().toEpochMilli())).contains(

Yes… something I carried over from ST.

Funny you should ask that. You can make a rule that triggers on startup, but I didn’t see a need… I just added the updateMode() function to the end of the script. I’ll add that to the example. This was the function runs when the file is saved and when OH starts up.