Design Pattern: Time Of Day

Tags: #<Tag:0x00007f01486830f8> #<Tag:0x00007f0148682f90> #<Tag:0x00007f0148682d10>

(Rich Koshak) #202

Your Astro Thing IDs match?

Note there are two Things, one names astro:sun:home and astro:sun:minus90. By default I think OH creates a Thing names astro:sun:local so you need to create these two Things.

What version of OH are you running? If you are not seeing at least “Calculating time of day…” in the log then the Rule isn’t triggering which means the System started trigger is not working.

(Kris K) #203

Hi Rich

Im using 2.4.0-SNAPSHOT
Build #1341

Ill check the thing ID

(Kris K) #204

See attached…looks like they match

(Rich Koshak) #205

It might work when one of the times in the tirggers occurs, but the fact that it isn’t triggering on System started is a problem and not one I’ll be able to help with. I think I saw a posting that yesterday’s build broke System started triggers but I might be mistaken.

Do you have any other System started rules? Do you have any Thread::sleeps in any of them? These used to cause problems.

But ultimately vTimeOfDay isn’t getting set because the Rule is never running.

(Kris K) #206

HI Rich

I dont use systemstarted in any rule. Nor threadsleeps in those… ill add a time cron for 10am and see if it updates. Its 9.49am here so we will see.

(Kris K) #207

Hi Rich…

See log after adding a cron timer for 10am

10:00:47.262 [ERROR] [untime.internal.engine.RuleEngineImpl] - Error during the execution of startup rule 'Calculate time of day state': Invalid format: "NULL"

(Kris K) #209

OK, issue fixed.

Rich, you need to update your OP because its missing the THING definition, your post assumes manual creation of things but provides no examples of how to create them.

Here is the THING definition you require to make this work:

astro:sun:home [ geolocation="-33.8798767,151.2081442", interval=60 ]
astro:moon:home [ geolocation="-33.8798767,151.2081442", interval=60 ]
astro:sun:minus90 [ geolocation="-33.8798767,151.2081442", interval=60 ]

You also should update it to say you MUST create a things file, because auto discovery using the Binding does not work.

10:40:49.430 [INFO ] [del.core.internal.ModelRepositoryImpl] - Refreshing model 'timeofday.things'
10:40:57.032 [INFO ] [se.smarthome.model.script.Time Of Day] - Calculating time of day...
10:40:57.042 [INFO ] [se.smarthome.model.script.Time of Day] - Calculated time of day is DAY
10:40:57.045 [INFO ] [smarthome.event.ItemCommandEvent     ] - Item 'vTimeOfDay' received command DAY
10:40:57.047 [INFO ] [smarthome.event.ItemStateChangedEvent] - vTimeOfDay changed from NULL to DAY

(Rich Koshak) #210

As it says in Design Pattern: What is a Design Pattern and How Do I Use Them, which the very first line of thisv and all my DPs asks you to read first,

a DP is not a comprehensive example. They are a template that one can follow to solve a given class of problems one may encounter while developing Rules.

The example code that is included with the DPs may not be fully explained. The purpose of the example code is to illustrate the DP only. But since the DPs are only templates and not complete in and of themselves, the example code will necessarily include additional code.

Fully documenting the Astro binding, how to create Astro Things, how to link Channels to Items, etc is documented elsewhere and out of scope for a DP. I can’t fully document every single teeny tiny detail or else I’d be reproducing half the official docs on every post and reach past would be dozens of pages long.

Consequently, and as it also says in that link

Because a DP is not a complete solution, the reader needs to possess a few skills in order to apply them to their situation:

  • the basics of how to define Items and use them in Rules code
  • Rule syntax
  • the ability to follow a block of Rules code and understand at a basic level what the code does
  • the ability to recognize and deal with code in a block that is not fully explained or defined in the DP text (e.g. reference to Items not defined in the current DP)
  • the ability to generalize an example to multiple situations

I suppose in the case I can add how to create and use Things for the relevant bindings.

You don’t have to create a .things file. You can create Astro Things manually through PaperUI.

(Kris K) #211

When I did auto discovery, it would add the things but then your custom minus90 channel had issues. It wasnt clear how to add a channel into a thing that was discovered automatically.

The key to fixing it was the minus90

Anyway, just writing about my experience. Im not very experienced with OH2 so hopefully someone can learn from my post :slight_smile: as I did from yours

(Kristof Rado) #212

After updating to 2.4 M6 the Time Of Day calculation got messed up (maybe it’s because the change in the ‘now’ API? However if I’m right, these are reverted because of the problems…).
So it seems that every value is correct, but in the switch, it won’t select the right case.
For example: Now it should be BED (after midnight), but it shows AFTERNOON.

Bed start:2018-11-21T00:00:00.000+01:00 
Afternoon start: 2018-11-20T14:31:00.000+01:100 
Evening start: 2018-11-21T16:00:00.000+01:00

As you can see, the values are calculated correctly. Any suggestions?

Ps.: I have wrote a proxy if case with the ‘BED’ case, it works there. What can be the problem? Also added a default case to switch, but that was not the problem (that it can’t switch to any case…)

(Rich Koshak) #213

You would see errors in the logs if that were the case. I think those changes to now were added and reverted after M6, but could be wrong.

I’m running on a snapshot more recent than M6 and I’m not seeing problems but you clearly are.

Afternoon and Evening, a least in the OP, is populated by an Astro event, not now but bed is based on now. It is really odd that just these three are wrong and not either all of them being wrong or only one type of time (Astro or now).

Can you post the top part of the Rule where all the start variables are created?

(Kristof Rado) #214

I didn’t had time to test it, but it seems that it always stays on AFTERNOON.

var String filename = "DayState.rules"

rule "Calculate time of day state" 
  System started or // run at system start in case the time changed when OH was offline
  Channel 'astro:sun:local:rise#event'    triggered START or
  Channel 'astro:sun:local:set#event'     triggered START or
  Channel 'astro:sun:d4cd4cd0:set#event'  triggered START or
  Item Debug_Switch received command ON or
  Time cron "10 1 0 * * ? *" or // one minute after midnight so give Astro time to calculate the new day's times
  Time cron "0 0 6 * * ? *" or
  Time cron "0 0 23 * * ? *"


  logInfo(filename, "Calculating time of day...")

  // Calculate the times for the static tods and populate the associated Items
  // Update when changing static times
  // Jump to tomorrow and subtract to avoid problems at the change over to/from DST
  val morning_start = now.withTimeAtStartOfDay.plusDays(1).minusHours(18)

  val night_start = now.withTimeAtStartOfDay.plusDays(1).minusHours(1)

  val bed_start = now.withTimeAtStartOfDay

  // Convert the Astro Items to Joda DateTime
  val day_start = new DateTime((vSunrise_Time.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli) 
  val evening_start = new DateTime((vSunset_Time.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli)
  val afternoon_start = new DateTime((vEvening_Time.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli)

  // Calculate the current time of day
  var curr = "UNKNOWN"
  switch now {
  	case now.isAfter(morning_start.millis)   && now.isBefore(day_start.millis) : curr = "MORNING"
  	case now.isAfter(day_start.millis)       && now.isBefore(afternoon_start.millis) : curr = "DAY"
  	case now.isAfter(afternoon_start.millis) && now.isBefore(evening_start.millis) : curr = "AFTERNOON"
  	case now.isAfter(evening_start.millis)   && now.isBefore(night_start.millis) : curr = "EVENING"
  	case now.isAfter(night_start.millis) : curr = "NIGHT"
  	case now.isAfter(bed_start.millis)       && now.isBefore(morning_start.millis) : curr = "BED"
    default : curr = "Unknown"

  // Publish the current state
  logInfo(filename, "Calculated time of day is " + curr)


Ps.: I have just seen that rule in the original post changed… I have changed to that (removed EpochiMilli), but the same problem occurs.

(Patrickse) #215

I´ve had the same… “always afternoon” problem. I just added a cron to trigger the rule more often. I think every 10 minutes. That fixed the problem for me… (at least for now)

(Kristof Rado) #216

I have a switch to manually run the rule, but that doesn’t help either… I can run as many time as I can, it will only return afternoon.

(Rich Koshak) #217

Now that you have changed the code a bit, are you still seeing the DateTimes being populated correctly?

In particular is evening_start being populated correctly?

It might be the case that Astro is the root of the problem.

(Kristof Rado) #218

I haven’t checked that yet, but it is like back to normal. It has changed to EVENING when it should. I don’t know what happened, I haven’t changed anything…
I’ll keep watching that it is correct or not… if not I will debug the whole rule…

(Rich Koshak) #219

Look in your logs around midnight for statements from the Astro binding indicating that it is calculating the new times for the new day. If you don’t see those then Astro isn’t calculating the times and this will definitely break the Rule. There was a bug along these lines in Astro awhile back. I thought it got fixed but I am not certain of that.

(Kristof Rado) #220

So it has worked for a day, after posting my previous comment. Now I have changed nothing (just rebooted my server) and the problem is back.

I can see Astro events at midnight, but just these two lines (and that the rule has ran):

2018-11-23 00:00:30.133 [INFO ] [thome.binding.astro.internal.job.Job] - Scheduled Astro event-jobs for thing astro:moon:local
2018-11-23 00:00:30.177 [INFO ] [thome.binding.astro.internal.job.Job] - Scheduled Astro event-jobs for thing astro:sun:local
2018-11-23 00:01:10.015 [INFO ] [marthome.model.script.DayState.rules] - Calculating time of day...
2018-11-23 00:01:10.076 [INFO ] [marthome.model.script.DayState.rules] - Calculated time of day is AFTERNOON

But I also have another Astro Thing which stores the offset times (like Afternoon time). I couldn’t see it there.
Searching through the log for the Thing it seems that the previous day that Thing also got ‘Scheduled events’, today not. So it’s like something brakes that Thing, but only that one. Is that somehow possible?
What should I try? Anyway, if it didn’t calculate the new times, shouldn’t the rule use the previous (last) calculated value? Why this can break the rule?


(Rich Koshak) #221

This was a reported problem but I thought it got fixed. Perhaps not. I can’t find the thread where this was discussed. It was exactly this behavior though. Some Astro Things would update but not all of them. Sometimes all would get updated. I wish I could find it again. @Dim, I have a vague recollection that you saw this problem. If so, do you remember if we found a work around?

(Angelos) #222

(I think that) I found the thread: Astro binding does not trigger: has no future executions anymore

Trying to find the PR that fixed the issue… this is old though. @rkrisi is on OH 2.4.0 M6… this shouldn’t happen

and maybe: