[Deprecated] Design Pattern: Time Of Day

Actually I’m my current version, which I thought I had posted here, I don’t use the DateTime objects at all any more and just use the milliseconds. There is no reason to create objects as now.isBefore etc all can handle epoc as well.

Upon looking back I do see that I posted it but only in the Astro 2.0 section.

I tried to follow what you did in the OH2 section, but the only solution that I found that properly set the variables with the milliseconds was that convoluted mess. When I did

(Astro_Sun_Set_Time.state as DateTimeType).calendar.timeInMillis

without the extra stuff around it, it complained about calendar not having a timeInMillis field that it could find. Does it look okay to you?

Also, love the trick of doing the offset by changing the geolocation!

Was Designer complaining or the oh logs?

If Designer, which version?

For the moment, please use Eclipse SmartHome Designer 0.8.

If in the log in not sure what the issue could be. The code above is copied verbatim from my running config.

Your rule calls now more than once. Although every call will only differ some milliseconds, from a design pattern perspective it would be stricter to declare a val at the top of the rule that calls now once and use that value across the rule instead of now.

1 Like

It would but I would consider that a micro optimization which is something I typically do not worry about unless and until I actually experience performance, logic, or timing problems. For a rule that executes five times over the course of the day and even with all the calls to now ends up only taking a hundred milliseconds or so to run I wouldn’t worry.

One could argue that it might make the rule more clear and easier to understand in which case I would consider the change.

However, in this case I do not see how defining a new variable to replace the calls to now would actually clarify anything.

What is the specific purpose of assigning a value and not use

var curr = NULL

instead?

Because I can’t sendCommand(null). It will generate an error. I could use curr = NULL which would set the state of vTimeOfDay to undefined but that would mean that whereever I check vTimeOfDay for some reason I’d need to check if it is NULL in addition to checking if it is “Evening”, for example. By using the String “UNKNOWN” I can avoid those extra checks and since the “UNKNOWN” state doesn’t drive any behavior it will not negatively impact any of my rules.

Honestly, “UNKNOWN” should never actually be sent to to the vTimeOfDay unless there is an error in the rule. I use it mainly to catch errors without breaking my other rules.

2 Likes

I am testing a rule with the clause

rule MyRule
when
    Item TimeOfDay received command "AFTERNOON"
then
    // do stuff
end

but it doesn’t seem to trigger. I know it is possible to use received command ON for switches. Is it possible at all to use a string after the received command? Or is it only possible to use

rule MyRule
when
    Item TimeOfDay received command
then
    switch(receivedCommand) {
        case "AFTERNOON" : // do some stuff
        case "BED" : // do other stuff
    }
end

I use the second method you mentioned. Something like this:

rule MyRule
when
    Item TimeOfDay received command
then
    if(TimeOfDay.state.toString == "AFTERNOON") {
                                                   //Do some stuff                            
    }
end
1 Like

Hey Robert, that’s sadly not supported: https://github.com/eclipse/smarthome/issues/2826

1 Like

Thanks for the confirmation. I will continue using an additional if statement.

@rlkoshak I tried your example rule and noticed that the Astro event related triggers fire 3 times. (I get 3 logs for the EVENING (sunset) trigger). Do you have any clue why this could be happening?

Maybe related to:

It’s weird, because the cron triggers from the when clause only get triggered once, and the Astro event based once multiple times.

I have created a rule for testing purposes.

rule "TimeOfDay"
when
	System started or
	Channel 'astro:sun:home:rise#event'   triggered START or
	Channel 'astro:sun:home:set#event'    triggered START or
	Channel 'astro:sun:minus30:set#event' triggered START or
	Time cron "0 0 0,6,23 * * ? *" 
then
	val logger = 'rules.test.TimeOfDay'
	val msg    = 'De tijd is nu ' + now
	pushover(msg)
	logInfo(logger, msg)
end

The sun:minus30:set#event sent 3 pushover messages to my phone. So the event triggers the rule 3 times.
Next test will be the sun:home:set#event that will be triggered in half an hour


Update: Yep. That trigger also fired 3 times. Next test: separate rule for sunset event (no or triggers).

rule "TimeOfDay"
when
	Channel 'astro:sun:home:set#event'    triggered START or
then
	val logger = 'rules.test.TimeOfDay'
	val msg    = 'De tijd is nu ' + now
	pushover(msg)
	logInfo(logger, msg)
end

No clue but nothing really changes functionally with the rule as written off it triggers multiple times. It only changes the Time of day when the newly calculated state is different from the current value.

Because I use groups so heavily in rules I almost always try to write them so multiple triggers do not break something.

Here is a link to an expansion of the pattern to include times of year.

Hi Rich,
I like your tutorial, thanks a lot!
I need little assistance for a further time span. I get from my squeezebox the alarm time (like 05:45) as a string. How can I convert it to use it similar to your examples. I need to define a “wakeup time” which starts 15 minutes before alarm time till alarm time.

Kind regards,
Michael

I’m not in a place where I can give you real code.

Look into the joda DateTime classes to figre out how to parse a String into a DateTime object. Once you have that you can use the comparisons and math like above.

You can look at the alarm clock examples (here is a good one) and see about how you can generate an event to trigger the rule at that time.