[Deprecated] Design Pattern: Time Of Day

it works for me this way:

import org.joda.DateTime

var DateTime dt = new DateTime()
(without “org.joda.”)

I more or less used the rule @rtvb suggested but my Eclipse SmartHome Designer and latest snapshot complain about the syntax, did the syntax for triggering channels change?

Note that depending on the Channel support the documentation should be updated:

ESHD 0.8.0 came out before Channel rule triggers were implemented. So it doesn’t recognize them and marks then as errors. It also fails to recognize non-core actions.

Yes but it also gives an error when saving, is that also expected.

What gives the error and what is the error? Does ESHD give the error or does OH give the error? If eshd, is there a pop-up or are you just seeing an error in the command prompt it was run from?

Does it still save the file?

Personally, I would not worry about exceptions or errors coming from ESHD unless you are also experiencing errors in OH. Designer is way behind and it doesn’t already anyone is actively working on it.

Real OH error, although not really clear:

2017-06-09 20:24:38.515 [DEBUG] [rg.quartz.core.QuartzSchedulerThread] - batch acquisition of 1 triggers
2017-06-09 20:24:38.527 [DEBUG] [rg.quartz.core.QuartzSchedulerThread] - batch acquisition of 1 triggers
2017-06-09 20:24:39.035 [DEBUG] [er.antlr.AbstractInternalAntlrParser] - Parsing took: 0 ms
2017-06-09 20:24:39.036 [DEBUG] [pse.xtext.util.OnChangeEvictingCache] - Clear 592 cache entries for resource time_of_day.rules after 6481 hits and 592 misses (quota: 91%)
2017-06-09 20:24:39.041 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'time_of_day.rules'
2017-06-09 20:24:39.042 [DEBUG] [er.antlr.AbstractInternalAntlrParser] - Parsing took: 0 ms
2017-06-09 20:24:39.045 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'time_of_day.rules' is either empty or cannot be parsed correctly!
2017-06-09 20:24:39.046 [DEBUG] [e.internal.engine.RuleTriggerManager] - Removed scheduled cron job 'time_of_day.rules#Calculate time of day state#0 0 6,23,0 * * ? *'
2017-06-09 20:24:39.046 [DEBUG] [rg.quartz.core.QuartzSchedulerThread] - batch acquisition of 1 triggers
2017-06-09 20:24:39.050 [DEBUG] [er.antlr.AbstractInternalAntlrParser] - Parsing took: 3 ms
2017-06-09 20:24:39.050 [DEBUG] [.linking.impl.AbstractCleaningLinker] - beforeModelLinked took: 0ms
2017-06-09 20:24:39.057 [DEBUG] [.linking.impl.AbstractCleaningLinker] - doLinkModel took: 7ms
2017-06-09 20:24:39.057 [DEBUG] [.linking.impl.AbstractCleaningLinker] - afterModelLinked took: 0ms
2017-06-09 20:24:39.072 [DEBUG] [pse.xtext.util.OnChangeEvictingCache] - Clear 423 cache entries for resource tmp_time_of_day.rules after 70 hits and 423 misses (quota: 14%)
2017-06-09 20:24:39.089 [DEBUG] [t.linking.impl.DefaultLinkingService] - before getLinkedObjects: node: 'long'
2017-06-09 20:24:39.095 [DEBUG] [t.linking.impl.DefaultLinkingService] - after getLinkedObjects: node: 'long' result: long
2017-06-09 20:24:39.099 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: FLUSH (null,[p=0,l=162,c=32768,r=162],false)@COMMITTED
2017-06-09 20:24:39.099 [DEBUG] [org.eclipse.jetty.io.ChannelEndPoint] - flushed 162 SelectChannelEndPoint@6e00d91d{/192.168.1.191:52632<->5080,Open,in,out,-,W,945/30000,HttpConnection}{io=0,kio=0,kro=1}
2017-06-09 20:24:39.099 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: DONE (null,[p=162,l=162,c=32768,r=0],false)@COMMITTED
2017-06-09 20:24:39.099 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: FLUSH (null,[p=0,l=169,c=32768,r=169],false)@COMMITTED
2017-06-09 20:24:39.100 [DEBUG] [org.eclipse.jetty.io.ChannelEndPoint] - flushed 169 SelectChannelEndPoint@6e00d91d{/192.168.1.191:52632<->5080,Open,in,out,-,W,1/30000,HttpConnection}{io=0,kio=0,kro=1}
2017-06-09 20:24:39.100 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: DONE (null,[p=169,l=169,c=32768,r=0],false)@COMMITTED
2017-06-09 20:24:39.101 [DEBUG] [ntime.internal.engine.RuleEngineImpl] - Executing rule 'Total consumption update'
2017-06-09 20:24:39.102 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: FLUSH (null,[p=0,l=171,c=32768,r=171],false)@COMMITTED
2017-06-09 20:24:39.102 [DEBUG] [org.eclipse.jetty.io.ChannelEndPoint] - flushed 171 SelectChannelEndPoint@6e00d91d{/192.168.1.191:52632<->5080,Open,in,out,-,W,2/30000,HttpConnection}{io=0,kio=0,kro=1}
2017-06-09 20:24:39.102 [DEBUG] [t.linking.impl.DefaultLinkingService] - before getLinkedObjects: node: 'long'
2017-06-09 20:24:39.102 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: DONE (null,[p=171,l=171,c=32768,r=0],false)@COMMITTED
2017-06-09 20:24:39.105 [DEBUG] [ntime.internal.engine.RuleEngineImpl] - Executing rule 'Total consumption update'
2017-06-09 20:24:39.105 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: FLUSH (null,[p=0,l=167,c=32768,r=167],false)@COMMITTED
2017-06-09 20:24:39.105 [DEBUG] [t.linking.impl.DefaultLinkingService] - after getLinkedObjects: node: 'long' result: long
2017-06-09 20:24:39.105 [DEBUG] [org.eclipse.jetty.io.ChannelEndPoint] - flushed 167 SelectChannelEndPoint@6e00d91d{/192.168.1.191:52632<->5080,Open,in,out,-,W,3/30000,HttpConnection}{io=0,kio=0,kro=1}
2017-06-09 20:24:39.105 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: DONE (null,[p=167,l=167,c=32768,r=0],false)@COMMITTED
2017-06-09 20:24:39.105 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: FLUSH (null,[p=0,l=240,c=32768,r=240],false)@COMMITTED
2017-06-09 20:24:39.105 [DEBUG] [org.eclipse.jetty.io.ChannelEndPoint] - flushed 240 SelectChannelEndPoint@6e00d91d{/192.168.1.191:52632<->5080,Open,in,out,-,W,0/30000,HttpConnection}{io=0,kio=0,kro=1}
2017-06-09 20:24:39.105 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: DONE (null,[p=240,l=240,c=32768,r=0],false)@COMMITTED
,W,1/30000,HttpConnection}{io=0,kio=0,kro=1}
2017-06-09 20:24:39.139 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: DONE (null,[p=166,l=166,c=32768,r=0],false)@COMMITTED
2017-06-09 20:24:39.141 [DEBUG] [t.linking.impl.DefaultLinkingService] - before getLinkedObjects: node: 'DateTimeType'
2017-06-09 20:24:39.142 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: FLUSH (null,[p=0,l=161,c=32768,r=161],false)@COMMITTED
2017-06-09 20:24:39.143 [DEBUG] [org.eclipse.jetty.io.ChannelEndPoint] - flushed 161 SelectChannelEndPoint@6e00d91d{/192.168.1.191:52632<->5080,Open,in,out,-,W,4/30000,HttpConnection}{io=0,kio=0,kro=1}
2017-06-09 20:24:39.143 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: DONE (null,[p=161,l=161,c=32768,r=0],false)@COMMITTED
2017-06-09 20:24:39.144 [DEBUG] [t.linking.impl.DefaultLinkingService] - after getLinkedObjects: node: 'DateTimeType' result: DateTimeType
2017-06-09 20:24:39.145 [DEBUG] [t.linking.impl.DefaultLinkingService] - before getLinkedObjects: node: 'long'
2017-06-09 20:24:39.149 [DEBUG] [t.linking.impl.DefaultLinkingService] - after getLinkedObjects: node: 'long' result: long
2017-06-09 20:24:39.154 [DEBUG] [t.linking.impl.DefaultLinkingService] - before getLinkedObjects: node: 'long'
2017-06-09 20:24:39.157 [DEBUG] [t.linking.impl.DefaultLinkingService] - after getLinkedObjects: node: 'long' result: long
2017-06-09 20:24:39.228 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: FLUSH (null,[p=0,l=162,c=32768,r=162],false)@COMMITTED
2017-06-09 20:24:39.228 [DEBUG] [org.eclipse.jetty.io.ChannelEndPoint] - flushed 162 SelectChannelEndPoint@6e00d91d{/192.168.1.191:52632<->5080,Open,in,out,-,W,85/30000,HttpConnection}{io=0,kio=0,kro=1}
2017-06-09 20:24:39.228 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: DONE (null,[p=162,l=162,c=32768,r=0],false)@COMMITTED
2017-06-09 20:24:39.228 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: FLUSH (null,[p=0,l=162,c=32768,r=162],false)@COMMITTED
2017-06-09 20:24:39.228 [DEBUG] [org.eclipse.jetty.io.ChannelEndPoint] - flushed 162 SelectChannelEndPoint@6e00d91d{/192.168.1.191:52632<->5080,Open,in,out,-,W,0/30000,HttpConnection}{io=0,kio=0,kro=1}
2017-06-09 20:24:39.228 [DEBUG] [.eclipse.jetty.server.HttpConnection] - org.eclipse.jetty.server.HttpConnection$SendCallback@5e2c992a[PROCESSING][i=null,cb=Blocker@70c2df64{null}] generate: DONE (null,[p=162,l=162,c=32768,r=0],false)@COMMITTED
2017-06-09 20:24:39.231 [DEBUG] [pse.xtext.util.OnChangeEvictingCache] - Clear 592 cache entries for resource tmp_time_of_day.rules after 2544 hits and 592 misses (quota: 81%)
2017-06-09 20:24:39.232 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'time_of_day.rules'
2017-06-09 20:24:39.234 [DEBUG] [er.antlr.AbstractInternalAntlrParser] - Parsing took: 2 ms
2017-06-09 20:24:39.234 [DEBUG] [.linking.impl.AbstractCleaningLinker] - beforeModelLinked took: 0ms
2017-06-09 20:24:39.237 [DEBUG] [.linking.impl.AbstractCleaningLinker] - doLinkModel took: 3ms
2017-06-09 20:24:39.237 [DEBUG] [.linking.impl.AbstractCleaningLinker] - afterModelLinked took: 0ms
2017-06-09 20:24:39.248 [DEBUG] [pse.xtext.util.OnChangeEvictingCache] - Clear 423 cache entries for resource time_of_day.rules after 70 hits and 423 misses (quota: 14%)

This is everything on debug, the only hints imho are

2017-06-09 20:24:39.042 [DEBUG] [er.antlr.AbstractInternalAntlrParser] - Parsing took: 0 ms
2017-06-09 20:24:39.045 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'time_of_day.rules' is either empty or cannot be parsed correctly!

And the fact that rules do not seem to trigger although strange is the following:

2017-06-09 20:24:39.232 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'time_of_day.rules'
2017-06-09 20:24:39.234 [DEBUG] [er.antlr.AbstractInternalAntlrParser] - Parsing took: 2 ms
2017-06-09 20:24:39.234 [DEBUG] [.linking.impl.AbstractCleaningLinker] - beforeModelLinked took: 0ms
2017-06-09 20:24:39.237 [DEBUG] [.linking.impl.AbstractCleaningLinker] - doLinkModel took: 3ms
2017-06-09 20:24:39.237 [DEBUG] [.linking.impl.AbstractCleaningLinker] - afterModelLinked took: 0ms
2017-06-09 20:24:39.248 [DEBUG] [e.internal.engine.RuleTriggerManager] - Scheduled rule 'Calculate time of day state' with cron expression '0 0 6,23,0 * * ? *'

Maybe it reloads twice one when the editor emptied the file and another time after writing…

But my rule is still not triggered, I will try to add some debug statements later one.

Not sure what it going in here. I don’t really have much to offer.

Np, your rules ehm rule

But as far as you known the Channel syntax is correct that is the most important of it all :slight_smile:

Hi Rich,

Thanks for making such great tutorial.
When i try to use your code on OH2 i get this error in my log:

[ntime.internal.engine.RuleEngineImpl] - Error during the execution of startup rule 'Calculate time of day state': org.eclipse.smarthome.core.library.types.DateTimeType

I tried the rules with:

import org.joda.DateTime

but that doesn’t work either, the error is still showing

In Eclipse SmartHome Designer, when i hover over ‘DateTimeType’ i see:

Note: This element has no attached Javadoc and the Javadoc could not be found in the attached source.

br,
Raymond

I wonder if the rule is trying to execute before the Items are fully initialized. Try adding a sleep at the top of the rule to see if that helps.

The problem isn’t with the data types. You do not need to import joda DateTime.

The warning in Designer can be ignored. It is just telling you the javadocs are not set up which is the case for ESHD 0.8.0.

I couldn’t add a sleep at the top of the file. Maybe i used the wrong syntax (i am new to all this :slight_smile:)
I did comment out ‘System started or’ like below:

val logName = "weather"
rule "Calculate time of day state"
when
  //System started or
  Channel 'astro:sun:local:rise#event' triggered START or
  Channel 'astro:sun:local:set#event' triggered START or
  Channel 'astro:sun:minus90:set#event' triggered START or
  Time cron "0 0 6,23,0 * * ? *" // there is currently a bug where only one cron is triggered per rule so I've combined all three into one
then
  Thread::sleep(1000) // make sure we are a tad past midnight to give Astro a chance to recalculate DateTimes for today

  val long morning_start = now.withTimeAtStartOfDay.plusHours(6).millis
  val long day_start = (vSunrise_Time.state as DateTimeType).calendar.timeInMillis
  val long afternoon_start = (vEvening_Time.state as DateTimeType).calendar.timeInMillis
  val long evening_start = (vSunset_Time.state as DateTimeType).calendar.timeInMillis
  val long night_start = now.withTimeAtStartOfDay.plusHours(23).millis
  val long bed_start = now.withTimeAtStartOfDay.millis

  var curr = "UNKNOWN"

  switch now {
        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"
        case now.isAfter(bed_start) && now.isBefore(morning_start):       curr = "BED"
  }

  if(vTimeOfDay.state.toString != curr) {
    logInfo(logName, "Current time of day is now " + curr)
    vTimeOfDay.sendCommand(curr)
  }

end

Now my log doesn’t show the error anymore, strange isn’t it?
I hope you know what could cause this?
btw, what will be the consequences for commenting out what i did?

EDIT: OH2 uses

'astro:sun:local:set#event'

instead of:

'astro:sun:home:set#event'

br,
Raymond

Sadly my log still does show the error, not when i save the file in designer, but when the rule gets triggered.
Any help is much appreciated,
thanks

br
Raymond

Rich, i think i found whats wrong.
When i comment out my item with:

{ channel="astro:sun:minus90:set#start" }

The rule starts working and i get the following a message in my log, which indicates to me that everything is working:

2017-06-20 13:55:53.018 [INFO ] [lipse.smarthome.model.script.weather] - Current time of day is now DAY

There seems to be a syntax problem with ‘minus90’ but i don’t know how to write it properly, do you perhaps have any clue?
And is this working for you on OH2? because that seems strange to me :slight_smile:
I am on the OH2 snapshots

br
Raymond

Commenting out the System started trigger stops the error because it stops the rule from firing when the system restarts or the rules file loads. This breaks the rule as your TimeOfDay Item won’t have a value, potentially for hours.

My example is a complete example, including the Things. As you see in the op, I define two Things, one named astro:sun:home and one named astro:sun:minus90. The trigger channel must match the names of the Things you have defined. If you did autodiscovery rather than defining your own things like my example you must change the names in the rule trigger to match your Things.

Rich,
i am truly sorry, i assumed (and didn’t read carefully) that my auto detected things were sufficient.
I added the minus 90 thing and for the others i used the auto detected things and everything seems to work now.
Thanks for your patience :slight_smile:

One question i have, you seem to put a “v” infant of, for example: vSunset_Time and vTimeOfDay where on other places those “v”'s are missing, do these “v”'s have a purpose?

thanks,
br
Raymond

To tl;dr the posting sihui is its just a naming convention that I’ve evolved over time. Starts with a:

  • “v” indicates a value or a sensor
  • “a” indicates an actuator (i.e. something you can command)
  • “g” indicates a Group.

When I wrote the original pre-OH 2 version of the design pattern I had not yet adopted this naming convention. And even now I often try to remove them from my postings but I guess I was in a hurry this time and left them in.

For future reference of everyone looking at this Design Pattern, in the OpenHAB 2.0 Astro binding, you can define your offset in the astro.things file without making changes to your lat/long:

// Sunrise/sunset triggered 30 minutes before event
astro:sun:homeOffsetMinus30 [geolocation="1.234567890,-1.234567890",altitude=50,interval=60] {
        Channels:
                Type rangeEvent : rise#event [
                        offset=-30
                ]
                Type rangeEvent : set#event [
                        offset=-30
                ]
}

// Sunrise/sunset triggered 30 minutes after event
astro:sun:homeOffsetPlus30 [geolocation="1.234567890,-1.234567890",altitude=50,interval=60] {
        Channels:
                Type rangeEvent : rise#event [
                        offset=30
                ]
                Type rangeEvent : set#event [
                        offset=30
                ]
}

// Normal sunrise/sunset trigger times
astro:sun:home  [geolocation="1.234567890,-1.234567890",altitude=50,interval=60]
astro:moon:home [geolocation="1.234567890,-1.234567890",interval=60]
1 Like

Double check your geo location, in newer builds the altitude tag has been removed:

astro:sun:home [ geolocation="52.5200066,13.4049540,100", interval=60 ]

http://docs.openhab.org/addons/bindings/astro/readme.html

Good to know, thanks for the tip. Seems to be a later build than the snapshot I’m using. My astro.things still updates fine from a touch.

2017-08-07 23:50:31.320 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'astro.things'
2017-08-07 23:50:31.366 [INFO ] [ding.astro.handler.AstroThingHandler] - Scheduled astro job-daily-sun at midnight for thing astro:sun:homeEarlyOffset30
2017-08-07 23:50:31.379 [INFO ] [thome.binding.astro.internal.job.Job] - Scheduled Astro event-jobs for thing astro:sun:homeEarlyOffset30
2017-08-07 23:50:31.385 [INFO ] [ding.astro.handler.AstroThingHandler] - Scheduled astro job-daily-sun at midnight for thing astro:sun:homeLateOffset30
2017-08-07 23:50:31.398 [INFO ] [thome.binding.astro.internal.job.Job] - Scheduled Astro event-jobs for thing astro:sun:homeLateOffset30
2017-08-07 23:50:31.410 [INFO ] [ding.astro.handler.AstroThingHandler] - Scheduled astro job-daily-sun at midnight for thing astro:sun:home
2017-08-07 23:50:31.420 [INFO ] [thome.binding.astro.internal.job.Job] - Scheduled Astro event-jobs for thing astro:sun:home
2017-08-07 23:50:31.425 [INFO ] [ding.astro.handler.AstroThingHandler] - Scheduled astro job-daily-moon at midnight for thing astro:moon:home
2017-08-07 23:50:31.430 [INFO ] [thome.binding.astro.internal.job.Job] - Scheduled Astro event-jobs for thing astro:moon:home

When OH2.2 comes around, make sure to remove the altitude parameter and add it to the end of geolocation as @sihui indicates.

1 Like