Time Based State Machine [4.0.0.0;4.9.9.9]

This is the line

    { 'type': 'dayset',  'times' : getItemsOfType('dayset').filter(item => actions.Ephemeris.isInDayset(items.getMetadata()[NAMESPACE].configuration['set'])) },

I changed the code based on your suggestion and it appears to work.

2023-10-05 14:00:31.175 [DEBUG] [omation.rules_tools.TimeStateMachine] - All tsm Items are configured correctly
2023-10-05 14:00:31.175 [DEBUG] [omation.rules_tools.TimeStateMachine] - Cancelling existing timers
2023-10-05 14:00:31.176 [DEBUG] [omation.rules_tools.TimeStateMachine] - Acquiring today's state start times
2023-10-05 14:00:31.997 [INFO ] [omation.rules_tools.TimeStateMachine] - Today is a default day.
2023-10-05 14:00:31.999 [DEBUG] [omation.rules_tools.TimeStateMachine] - Creating timers for times that have not already passed
2023-10-05 14:00:32.572 [DEBUG] [omation.rules_tools.TimeStateMachine] - Creating timer for Evening at 2023-10-05T16:43-04:00
2023-10-05 14:00:32.673 [DEBUG] [omation.rules_tools.TimeStateMachine] - Creating timer for Night at 2023-10-05T18:42-04:00
2023-10-05 14:00:32.740 [DEBUG] [omation.rules_tools.TimeStateMachine] - Creating timer for Bed at 2023-10-05T22:00-04:00
2023-10-05 14:00:32.847 [INFO ] [omation.rules_tools.TimeStateMachine] - The current state is Afternoon

1 Like

Thanks for your help

Hi @rlkoshak ,

Upgrade to 4.1M2 from 4.1M1 reverts a problem we discussed in March, Time Based State Machine gives the error:

2023-10-09 23:06:36.576 [WARN ] [omation.rules_tools.TimeStateMachine] - require TimerMgr instead of timerMgr and use TimerMgr() instead of new timerMgr.TimerMgr().
2023-10-09 23:06:36.595 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: Error: "2023-10-09T23:06:46.582+02:00[SYSTEM]" is an unsupported type for conversion to time.ZonedDateTime

With 4.1M1 there is no error and downgrade from 4.1M2 resolves the issue for me.
Additionally, there is a warning in both releases in the first line above but I don’t expect it’s crucial to the error.
I don’t know if the warning appeared after upgrade or existed before and I wasn’t aware of it.
The warning remains after downgrade but your rule runs with no error.
I tried to resolve the issue by upgrading openhab_rules_tools so maybe this caused the warning to appear.

I use rule template from marketplace.
I’ve upgraded and downgraded OH several times to confirm.

1 Like

The first warning is what I would expect to see. I changed how the TimerMgr is imported in the latest version of OHRT. You can ignore that warning.

Please post the full stack trace so I can confirm which lines are throwing the error. Also please post that line and the lines around it so I can confirm it’s running with the latest version of the template.

Please confirm your JS Scripting add-on settings and version. From a scratchpad script run:

var {helpers} = require('openhab_rules_tools');
console.info('openhab-js version: ' + utils.OPENHAB_JS_VERSION);
console.info('OHRT version: ' + helpers.OHRT_VERSION);

Watch the logs and report what versions of the library you are running.

Thanks for quick reply.
I’ve resolved the error in the meantime by reinstalling JavaScripting and TSM rule so above code gives following logs:

2023-10-10 19:08:10.293 [INFO ] [nhab.automation.script.ui.scratchpad] - openhab-js version: 4.5.1
2023-10-10 19:08:10.294 [INFO ] [nhab.automation.script.ui.scratchpad] - OHRT version: 2.0.3

Now I have no error or warning so sorry for false alert.

I have some problems with Add-ons UI, featured add-ons in the Store Automation group are doubled. In case of JavaScripting one of the doubled is installed and second is for adding. If I try to remove this installed, Install pop-up appear and do something but don’t remove anything or reinstall suppose. The second add-on remains for adding state even after install. I tried different browsers so I don’t think that is cache related problem. 4.1M1 behaves the same.

Thanks and have good one

Good because I just upgraded to 4.1 M2 myself and the rule worked without error with those versions of the library. I was going to be at a loss for what to do.

It’s probably worth opening a new thread to explore that one.

Have you cleared the cache of OH: Clear the Cache

Yes, I cleared the cache exactly following this topic.

Hi @rlkoshak,
first of all, thanks for your amazing rule template(s), they really make things a lot easier.
However, I noticed some minor issue lately.

I’m not sure, if this works correctly. I noticed last week, that for items which are set to a static time only via timepicker widget (and thus have a state like 1970-01-01T22:00:00.000+0100) were off an hour since not transformed to current date/time. So I had to re-implement your to_today rule to fix times. This seems to be an issue with daylight saving time (which was switched this weekend in Austria, so it is again working correctly now).

And one more thing: would you consider adding to more day types, one for days before weekend or holidays and one for the last weekend day/holiday before a workday? This would make it more flexible for days with “morning times” treated like weekends/holidays and “evening/night times” like weekdays. I think this is similar to what @LukaNoah requested above.
Should be as easy as adding preworkay and predayoff (naming can be discussed):

          // type.
          const startTimes = [
            { 'type': 'custom',  'times' : getItemsOfType('custom').filter(item => actions.Ephemeris.isBankHoliday(0, item.getMetadata()[NAMESPACE].configuration['file'])) },
            { 'type': 'preworkday', 'times' : (!(actions.Ephemeris.isBankHoliday(1) || actions.Ephemeris.isWeekend(1)) && (actions.Ephemeris.isBankHoliday() || actions.Ephemeris.isWeekend())) ? getItemsOfType('preworkday') : [] },
            { 'type': 'holiday', 'times' : (actions.Ephemeris.isBankHoliday()) ? getItemsOfType('holiday') : [] },
            { 'type': 'dayset',  'times' : getItemsOfType('dayset').filter(item => actions.Ephemeris.isInDayset(items.getMetadata()[NAMESPACE].configuration['set'])) },
            { 'type': 'weekend', 'times' : (actions.Ephemeris.isWeekend()) ? getItemsOfType('weekend') : [] },
            { 'type': 'predayoff', 'times' : (actions.Ephemeris.isBankHoliday(1) || actions.Ephemeris.isWeekend(1)) ? getItemsOfType('predayoff') : [] },
            { 'type': 'weekday', 'times' : (!actions.Ephemeris.isWeekend()) ? getItemsOfType('weekday') : [] },
            { 'type': 'default', 'times' : getItemsOfType('default') }
          ];

and

var DAY_TYPES   = ['custom', 'preworkday', 'holiday', 'dayset', 'weekend', 'predayoff', 'weekday', 'default'];

BR Hans

1 Like

If there is a problem, it’s going to be in core and an issue should be filed. But I’m guessing that the problem is it’s using ISO8601 format instead of RFC format (i.e. +0100 instead of Europe/Vienna).

At least in rules, the RFC format is used but maybe not for DateTimeTypes.

The proper fix for this would be to fix this in OH core to make sure that it handles the DST change over properly. The fact that a problem occurred with this rule template is just symptom of a wider problem. It will be a problem for anyone using a Time is <item> triggered rule.

But in the mean time, something like To Today can be a work around, though it doesn’t need to run every day. Just on the DST changeover dates.

I’ll also look to see if it’s feasible to call toToday in getItemsOfType as a work around. In the Helper Library, toToday was monkey patched onto ZonedDateTime so time.toZDT(items.MyDateTimeItem).toToday() should handle DST changeovers. But I’ve not tested toToday with an Item like that yet.

I’m already calling toToday on the date times, so apparently that isn’t working right.

If you want to have more day types, you can configure them through Ephemeris: see Actions | openHAB. You have full control over defining day types and holidays. Define a predayoff dayset in Ephemeris and use dayset as the type for recurring days (i.e. days that occur every week) and a custom Ephemeris XML file and custom as the type.

Stuff like this is the whole reason I included the dayset and custom day types.

Also, as I showed above, handling those time of day states that are slightly different outside this rule template is almost always going to be simpler to implement and/or configure and use. Using the example from above, it’s easier to set up a separate rule for BEDTIME than it would be to set up two or more sets of separate DateTime Items just to handle the case where BEDTIME is different the night before the weekend or a holiday.

I’m not certain it is that easy. For example, I’d have to think about how that will work for those who, for example, do not have every holiday off work.

{ 'type': 'preworkday', 'times' : (!(actions.Ephemeris.isBankHoliday(1) || actions.Ephemeris.isWeekend(1)) && (actions.Ephemeris.isBankHoliday() || actions.Ephemeris.isWeekend())) ? getItemsOfType('preworkday') : [] },

I don’t think this condition is correct. Shouldn’t the ! be on the second clause? We want this to match if today is a workday (i.e. not a weekend or holiday) and tomorrow is a weekend or a holiday.

I’m not sure predayoff is needed. It seems highly unlikely and relatively rare that one would need a whole different set of times of day if it’s already a day off and tomorrow is a day off too.

Logically, I think preworkday would best be put between weekend and weekday. It doesn’t actually change how it works functionally, but it makes sense to put it close to weekday since it’s a special type of weekday.

Not sure what you mean with the issue being in core and I have to admit that I’m not really looking through the different time formats and conversions. I just noticed that the conversion to local time didn’t work correctly for the time-based states, but did when manually running your to_today rule (had to adapt it a bit to get items by group membership instead of tag). So I guessed the conversion in your rule didn’t work correctly.
Therefore, I wouldn’t even know how to describe the issue with regard to core.

Would have hoped so, but I don’t get how to define daysets on such conditional rules…

Of course this can’t cover all cases and probably the naming could be improved. But with your argument the whole differentiation between holidays, weekend and weekdays would be mostly obsolete.

Maybe I’m missing something but seems correct to me:

(TOMORROW is NOT a holiday OR weekend day) AND (TODAY IS a holiday OR weekend day)

But it actually represents a day that is NOT a day off but next day is. And that’s actually the tricky part as, for example, I can’t set it to Friday (as the last workday) as it would need to be Thursday if Friday was a holiday.

According to this comment in the code:

// Go through startTimes in order and choose the first one that has a non-empty list of Items

I was thinking that the first matching type is used. Therefore, preworkday would always match holiday or weekend first. But maybe I was misinterpreting something…

If there is an easy way to add these conditional daysets through ephemeris directly. I’m absolutely fine with that, and actually I can also live with not having them available. I just thought it would be a nice, easy and non-breaking addition that could be of general use. (And unfortunately it seems to be not possible to have rule templates without adding them to the marketplace, which I’d consider improper and confusing for every minor deviation from the original.)

Java, upon which OH is built, supports both ISO8601 formatting which has a fixed timezone of + or - hours from GMT. That format does not handle DST. Something needs to go in and adjust that timezone offset when DST changes.

However, Java also supports RFC formatting which uses region/city for the timezone. When that formatting is used, I think that handling the DST change is automatic.

The problem is in core because this problem affects more than just this rule template. It impacts all Time is item triggered rules and anything else that uses the state of DateTime Items but only look at the time.

End users should not have to go and adjust all their DateTime Items every time DST changes. OH should handle that for us.

Unfortunately there isn’t a way to do this through the UI yet. But it’s pretty simple.

Let’s say you want a different set of times for Friday. Then create the file $OH_CONF/services/ephemeris.cfg with the following contents:

country=de
region=nw
dayset-workday=[MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY]
dayset-weekend=[SATURDAY,SUNDAY]
dayset-preweekend=[FRIDAY]

Replace the country and region’s value with what ever is appropriate for you. And if your workday and weekend are different you can change those values there as well.

Then in the metadata for the DateTime Items you’d use “dayset” for the type and “preweekend” for the “set”.

value: MORNING
config:
  type: dayset
  set: preweekend

For holidays you’ll need to create an XML file following the example here with the pre-holiday days defined. Then the metadata for the DateTime Items would be type “custom” and file the full path to the XML file. For example:

value: MORNING
config:
  type: custom
  file: /etc/openhab/preholiday.xml

I think I was misunderstanding the purposes of the types. The order and conditions are correct I think. preworkday needs to be before holiday and it needs to check that today is a holiday or weekend and tomorrow is a workday. And predayoff needs to check that today is a workday and tomorrow is a holiday or weekend.

I’m not sure though now whether dayset should be before holiday or not. Ideally custom stuff should take precedence over built in stuff.

I’ve created an issue and commented on relevant issues and PRs to make it so it’s possible to create rule templates locally.

But based on the rules of the marketplace having separate entries for minor updates to an already published template are not allowed.

All-things-considered, there are a lot of combinations to consider which need to be considered to make sure we don’t break too many use cases.

And unfortunately rather limited… I was aware of these opportunities for configuration, but setting fixed days (or dates) is far from the proposed dynamic determination based on current and next day (as outlined above: if Friday is a holiday, preweekend or predayoff, respectively, would be on Thursday already).
Looking at the XSD that defines the structures of the XML it may be possible to build a custom XML file, which is based on relative dates, but I don’t think I’m able to do that.

It depends on how the holidays are defined.

If I took Thanksgiving in the US which is the fourth Thursday in November, I’d use the following in my custom XML file:

<tns:FixedWeekday which="FOURTH" weekday="WEDNESDAY" month="NOVEMBER" descriptionPropertiesKey="Day Before Thanksgiving"/>

The days around Easter are a bit more challenging but there is a RelativeToEasterSunday element, and most of the week before Easter has it’s own holiday entry anyway.

Looking at the Austria holidays list I don’t see anything tricky where you’d need anything more than Fixed and RelativeToEasterSunday.

For example, I would expect your entry for the day before Ascension Day would be something like:

<tns:RelativeToEasterSunday descriptionPropertiesKey="Day Before Ascension Day">
  <tns:chronology>GREGORIAN</tns:chronology>
  <tns:days>39</tns:days>
</tns:RelativeToEasterSunday

Going through this also raises a concern. I wonder how many people actually get off for all of the holidays listed in Jolly Day. I certainly don’t. I don’t get half of them off.

Hello everybody,
I’ve been using the old ToD State Machine on OH3 for years and just loved it.
I tried to switch to this new state machine and need a little startup help.

I’m running OH 4.0.3 - Release Build
I installed JS scripting and openhab_rules_tools (I don’t know how to check the versions but folders are present)

I created a Group (gTimesOfDay) that hold two DateTime items to start with. Both have the following meta data:

value: BED
config:
  type: default

value: MORNING
config:
  type: default

Namespace is tsm

I also have a String item TimeOfDay

The I tried to install the “Time Based State Machine” Template from market place. But nothing happend. I guess there should some script or something else after installation. But I can’t find anything. What is supposed to happen?
How can I debug this?
Do I need more DateTime items to start with?
Are there any other prerequisites?

Thanks in advance!!

Martin

Run a script (Scratchpad from the Developer Sidebar is a good place to do this) with the following:

console.info('openhab-js version: ' + utils.OPENHAB_JS_VERSION);
console.info('OHRT version: ' + helpers.OHRT_VERSION);

That will log out the versions of both to openhab.log.

If you just installed both you are almost certainly running recently enough versions of both.

See https://www.openhab.org/docs/concepts/rules.html#rule-templates and https://www.openhab.org/docs/tutorial/rules_basic.html#rule-templates.

Once the rule template is installed, you have to instantiate one or more rules based on the template and configure it with the required properties. The template is just that, a template. It’s not a rule unto itself.

Once instantiated, running a rule generated from any of my templates manually will test the configuration and generate logs if there are errors.

Thanks a lot.

It’s working

Hi,

Don’t know if I should post this here or start a new topic, but I’ll go with this :slight_smile:

I just upgraded to OH stable 4.1 and after that I get an error when I run the Time Based State Machine rule (there are a lot more text in the log if that’s interesting). It was working fine before the upgrade. I upgraded via apt-get so got other Linux packages updated at the same time. I didn’t take any snapshot before upgrading (I know that I’ve should’ve) so can’t roll back.

[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'd6e4539529' failed: org.graalvm.polyglot.PolyglotException: Error: "2024-01-04T20:29:13.804+01:00[SYSTEM]" is an unsupported type for conversion to time.ZonedDateTime

Where does the “[SYSTEM]” part of the datetime come from?

I’m running OH on a Promox Debian Container (Bookworm), don’t know if that has something to do with it since I can’t find anyone else on the forum with this error when searching.

From the Item. When you update a DateTime Item and don’t provide the timezone, [SYSTEM] means use the default timezone of the system.

Do you have the helper library installed separately or are you using the built in library? This looks like an old bug in the helper library that has been fixed.

Updating OH will not update the helper library if you’ve installed it separately.

The error is almost certainly coming from this line:

              var mapped = startTimes.map(i => { return { 'state': i.getMetadata()[NAMESPACE].value,
                                                          'time' : time.toZDT(i.state).toToday() } });

You can try changing that to just time.toZDT(i).toToday() but that too had a bug in older versions of the helper library.

thanks for your very quick reply!

I feel a bit stupid because I just noticed that this exact issue was in the second post of this thread :man_facepalming:

If you by “helper library” mean Openhab rules tool then I’m pretty sure I installed it manually, seems like I was running version 2.02 and now I’ve updated to 2.03, but without any luck.

However, then I found that I was running version 0.2 of the template so created a new rule on 0.5 and now it works. Thanks for your help Rich!

No, there are two libraries involved: openhab_rules_tools, and openhab. I’ve referring to the latter. This either comes with the add-on or can be installed separately. If installed separately it’s up to you to keep it up to date.

Unfortunately there is no automated mechanism to update a rule template. That’s why I started adding a comment with the version in a comment to the top of the Script Action of all my rules. I haven’t found any place to add it more prominently that doesn’t cause other problems.

The rule templates now also test the versions of the helper library and OHRT to ensure the minimum versions are met and throws an error if they are not.

There is a lot to track and I try to make it as easy as I can.