Design Pattern: Time Of Day

jodatime
designpattern
time
Tags: #<Tag:0x00007f0146325048> #<Tag:0x00007f0146324f08> #<Tag:0x00007f0146324da0>

(trumee) #82

I didnt find any errors in designer, but during one of the restarts i found this

2017-09-02 20:51:51.900 [WARN ] [ome.core.thing.internal.ThingManager] - Initializing handler for thing 'harmonyhub:device:HarmonyHub:39829447' takes more than 5000ms.
2017-09-02 20:51:55.578 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Error during the execution of startup rule 'Calculate time of day state': org.eclipse.smarthome.core.library.types.DateTimeType
2017-09-02 20:51:56.933 [WARN ] [ome.core.thing.internal.ThingManager] - Initializing handler for thing 'harmonyhub:device:HarmonyHub:39829448' takes more than 5000ms.
2017-09-02 20:52:01.943 [WARN ] [ome.core.thing.internal.ThingManager] - Initializing handler for thing 'harmonyhub:device:HarmonyHub:46909196' takes more than 5000ms.
2017-09-02 20:52:03.020 [INFO ] [andler.ZigBeeCoordinatorEmberHandler] - Connecting to serial port [/dev/cuaU1] at 57600
2017-09-02 20:52:04.162 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Error during the execution of startup rule 'Calculate time of day state': sleep interrupted

Some sort of race condition is happening. I have several rule files each of which has a ‘System started’. I guess some sort of race condition is happening killing the astro rule. Can the ‘System started’ not be split up into multiple files?


(trumee) #83

Another restart, and i get a new warning. I did not touch the astro.rules

2017-09-02 21:03:17.825 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'default.items'
2017-09-02 21:03:17.913 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'kodi.items'
2017-09-02 21:03:17.924 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'astro.items'
2017-09-02 21:03:18.237 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'default.persist'
2017-09-02 21:03:21.377 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'astro.rules', using it anyway:
The value of the local variable morning_start is not used
The value of the local variable day_start is not used
-----------------------
2017-09-02 21:04:00.507 [INFO ] [lipse.smarthome.model.script.weather] - Current time of day is now EVENING


(Rich Koshak) #84

Inconsistent behavior like this often points to a failing SD card. I would try installing on a fresh card and see if that makes a difference.

You should be able to have multiple system started rules.


(trumee) #85

Yes, this is a weird issue. By the way this is running on a server and not raspberry pi.

Can Thread::sleep amongst different rules cause interference?


(Rich Koshak) #86

It can in system started roles. There is an open issue on that. But it really is only a problem for long sleeps. And the problem is that other rules don’t execute during the sleep. Your rule is not being loaded and parsed correctly.


(Kim Skatun) #87

Hi @rlkoshak,
So I am living in Norway where sunrise is 3am in the summer and sunset 2am, but in winter its 9am for sunrise and 3pm for sunset…

So for me:

MORNING    06:45              Day (Preheat of flat)
DAY        07.00              Untill no activity for at least 20 min (Lights on, slowly...)
WORK       No activity        Afternoon (reduce heat, all lights off)
AFTERNOON  16.00              Evening(Increase heat)
EVENING    Sunset if >20.00   23:00(dim lights)
BED        23:30              07:00 (Reduce heat, lights 40% and red if switched on during this period)

I will keep you posted on my implementation of this scheme, so as you see i dont use sunrise for anything, what do you use it for?


(Rich Koshak) #88

During the winter sunrise is well after 6:00 am. So I use the MORNING state (when it exists, since sunrise is before 06:00 during the summer) to turn on a light around the time I get up in the morning and turns it off when the sun comes up.

And even if I didn’t have a real use for it, I would have included it in the example above because I think the majority of users will want to do something at sunrise rather than a set time of day.


(Kim Skatun) #89

Hi, Rich
I was wondering if we could make an advanced version of your Design Pattern. I have been using it for a year or so now, and it works superb, but there are some advanced feature I would like to implement.

I would like that TimeOfDay also have the state Sunrise and sunset. Currently I use Night to Morning for my outside night light, however this does not make sense if its gets bright before morning state kicks in

Currently I use this is in a seperate rule, so start of night light is triggered with the night state and then I have a separate rule which does things of sunrise, but it does the exact same thing as when the morning state kicks in, so I just feel that they could have been integrated to one.

I would also like to add the PreHeat Phase 15min before morning

I and probably many others uses alexas, alarm clock etc. So when I go to bed i say “Alexa lights off”, and then Night state should get activated if it is not already it is,

In the morning if the alarm clock goes off before morning then Morning state should be activated. Then I use the same “Alexa light off” To activate at work state.

I also like to have different times at weekends and to disable the modes if I am on holidays.

I currently use your design pattern with other rules, but I got asked the otherday if we could not make this into one state variable instead of having several, making the act upon TimeOfday change at one place, for easier maintaince.

Just an Idea,

and my other rule : https://github.com/skatun/Openhab-CONF/blob/master/rules/lights.rules

rule "turn off all lights"
when
    Item Light_All_Off received command ON
then 
	Scene_LivingRoom1.sendCommand(1)
	Scene_BathRoom.sendCommand(1)
	Scene_MasterBedRoom.sendCommand(1)
	Light_Hallway.sendCommand(OFF)
	if (vTimeOfDay.state.toString=="BED"){
		MoodSelector_LivingRoom.sendCommand(4)
		Scene_LivingRoom1.sendCommand(6)
	}
	
end

(Christoph Wempe) #90

I am not usuing this §Time Of Day" Pattern, yet.

But I think you should differentiate between “Time OF Day” and your "personal state"
Yes, your smart home needs to know if you are sleeping, working or at home during holidays.
But that should be stored in another pattern, I think.


(Rich Koshak) #91

A design pattern is intended to be an example upon which you build. It is not necessarily intended to be a complete solution unto itself. So I do think it is reasonable to expect the users of the design pattern to add to, take away, and otherwise modify the Design Pattern to meet their needs.

That is a trivial addition. You just need to define the start and stop times using Astro or static time. Then just add it to the rule using the other lines in the rule as a guide. Just make sure these new TimeOfDay states do not overlap the existing ones.

Remember, this design pattern is to represent the state of the TimeOfDay, not events. So if you are trying to add in the event of Sunrise or Sunset into vTimeOfDay that really goes against the intent of the design pattern, and it duplicates existing behavior. If you have a Rule that needs to trigger at Sunrise or Sunset, trigger the rule using the Astro events. Because these events would be momentary states inside vTimeOfDay, no rule would ever be able to:

if(vTimeOfDay.state == "SUNRISE")

because vTimeOfDay will never be that state long enough for that statement to evaluate to true.

So, to add a new SUNRISE state:

  • determine the start and stop times or events
  • add a trigger to the rule to run the rule when the new start time occurs (Astro or cron)
  • a new line to calculate val long sunrise_start = ...
  • add a new case to the switch statement to check if now is after sunrise_start and is before the start of the next state (MORNING?) and set curr = "SUNRISE"

This isn’t creating a new advanced example, this is just adding a new state.

So why not just change the MORNING state to start at Sunrise instead of 06:00? There is nothing magic or required about having MORNING start at 06:00. It’s just an example. As I said, a Design Pattern is intended to be modified to meet your needs.

Again, this is just the addition of a new state. See above.

That would require a separate rule, but it is a trivial one where you just vTimeOfDay.sendCommand("NIGHT") when you receive the command from Alexa et al. There is no law that states that the one rule above is the only place that the vTimeOfDay can be changed. I’m not sure this rises to the level or needing a new example.

See above. There is no problem putting this in another rule.

This is the first thing mentioned so far that actually warrants a more advanced example. But even that isn’t going to be that big of a change. Basically one needs to add code to use different start times for the various states based on the value of now.dayOfWeek

  val boolean isWeekend = if(now.dayOfWeek == 6 || now.dayOfWeek == 7) true else false

  val long morning_start = if(isWeekend) now.withTimeAtStartOfDay.plusHours(8) else now.withTimeAtStartOfDay.plusHours(6).millis
  ...

So again, I’m not sure this rises to the level of needing a new example. It does become much more complicated when one wants to add in holidays. In that case I think the correct approach is to use the Time Of Day DP as an example and implement a vHoliday Item that has is calculated the same way as vTimeOfDay, only it is based on specific days instead of times of day. Then you can take it into account in the vTimeOfDay just like the weekends:

val long morning_start = if(isWeekend || vHoliday.state !="NA") now.withTimeAtStartOfDay.plusHours(8) else now.withTimeAtStartOfDay.plusHours(6).millis

You could even combine the weekend and holiday calculation into its own state.

This again goes toward the purpose of a DP which is to show a way to solve a given type of problem. That is why I included the irrigation example above. It is using the DP to solve a completely different problem, but a problem that is of the same type.

So if all of these things are based on non-overlapping states then, as I think I’ve described above, you have no problem putting everything into one state and centralizing logic as discussed above. However, if you need to expand beyond just weekends you will probably need to separate the day calculations from the time of day calculations.

And I believe having the separate rules that get triggered by Alexa et al is appropriate. This is because the Calculate time of day state Rule is going to base its calulations based on the clock time independent of what triggered the Rule.

I completely agree they should be stored in another state Item, but that does not necessarily mean that they require a different DP to calculate them. The main point of a DP is that it applies to lots of different problems that are similar to each other.

So, the tl;dr of it is there might be a good argument for showing another more complex example to show how to integrate weekends and holidays. There definitely would be a case for a new complex example, or perhaps a separate DP to handle overlapping states (e.g. its MORNING and SUNRISE at the same time). But personally, I would recommend against having overlapping states in this way unless you have a really really good reason.

For record, you would just list all the different states and use if(vTimeOfDay.state.contains("MORNING") instead of == in all your other rules that need to test for state.

Having said all of the above, I’m more than willing to help you @skatun if you need it to apply the suggestions I’ve made above.


(lamero) #92

With OpenHab2 version, current time of day is never AFTEROON


(Rich Koshak) #93

If you are on 2.1 there is a known problem with the Astro binding stop working.

If Astro is working then the Things are misconfigured. I’ve been running with the above config since before this do was posted and can confirm that AFTERNOON happens every day.


(lamero) #94

Yes, I’m on openHAB 2.1.0
Where I can find info about this BUG?
Thanks


(Rich Koshak) #95

Search the forum. There were at least half a dozen postings on it.

The only work around is to upgrade to the snapshot where the problem is fixed. Please note that if you are seeing the bug, none of your Astro driven tods will work.


(lamero) #96

I’m on Odroid C2, so i have to wait OH2.2


(Rich Koshak) #97

Why? There should be nothing that prevents you from upgrading unless I missed a posting somewhere. If it will run a compatible Java it should run OH. For that matter, if it runs OH 2.1, if should run the 2.2 snapshot.


(lamero) #98

Because I’am using https://dl.bintray.com/openhab/apt-repo2 repo on Debian and I don’t know how to update it


(Rich Koshak) #99

http://docs.openhab.org/v2.1.0/installation/linux.html


(lamero) #100

Thanks. OH2 updated to 2.2.0 Build #1084 with openHAB’s JFrog Artifactory repo.
I will check if astro bind works


(Jens W.) #101

This thread mentions two important flaws/bugs in the OH2 rule engine concerning timing / cron handling. I wanted to post my thoughts on this here and ask some questions.

The first one being that only one cron per rule is permitted (de facto - as of the time of this writing).

The second one being the very ugly

Thread::sleep

that seems to be necessary to prevent timing issues in rules.

Could someone please tell me if #1 was already reported as a bug? Or is this fixed in the latest snapshots? It’s a trap that every newcomer will fall for, so I think it is an important issue.

Also, is #2 really an issue or was that just a precaution? To me it looks like the result of blood, sweat and tears so I assume it’s the former. :wink: If yes, is there already a bug for this? IMO this is really bad. Time based rules should be guaranteed to operate at or after the time they are set to trigger and not before that.

Speaking of that, what is supposed to happen in the following case:

rule "Some Rule"
when
	Time is midnight
then
	val day = now.getDayOfWeek
end

I realize that it is open for debate whether “00:00” or “24:00” is a point in time in the old day or the new. Having said that, I think it is important in the context of rules that one can assume that this happens in the new day. I guess everything else would mean going down the slippery slope of Thread::sleeps. Does anyone know more about this?

Thanks a lot in advance! :slight_smile: