OH3->OH4 just one hurdle left ... ephemTimeOfDay JS script fails

Took the OH4.0.0 M2 leap yesterday only to find out when I went to bed that it was still EVENING and not BED.
Turned out the ephemTimeOfDay JS script had stopped working.

2023-05-24 19:23:09.315 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'b6c5df081b' failed: org.graalvm.polyglot.PolyglotException: ReferenceError: "scriptExtension" is not defined

I think I have read in the forum at one point abaout some community version of the script below, but my search have come up empty. Could someone please point me in the right direction here? @rlkoshak perhaps?

// Imports
var logger = Java.type("org.slf4j.LoggerFactory").getLogger("org.openhab.model.script.Rules.TimeOfDay");
scriptExtension.importPreset("default");
this.Ephemeris = (this.Ephemeris === undefined) ? Java.type("org.openhab.core.model.script.actions.Ephemeris") : this.Ephemeris;
this.ZonedDateTime = (this.ZonedDateTime === undefined) ? Java.type("java.time.ZonedDateTime") : this.ZonedDateTime;

//   Get Metadata query stuff
this.FrameworkUtil = (this.FrameworkUtil === undefined) ? Java.type("org.osgi.framework.FrameworkUtil") : this.FrameworkUtil;
this._bundle = (this._bundle === undefined) ? FrameworkUtil.getBundle(scriptExtension.class) : this._bundle;
this.bundle_context = (this.bundle_context === undefined) ? this._bundle.getBundleContext() : this.bundle_context;
this._bundle =  this._bundle;
this.bundle_context = this.bundle_context;
this.MetadataRegistry_Ref = (this.MetadataRegistry_Ref === undefined) ? bundle_context.getServiceReference("org.openhab.core.items.MetadataRegistry") : this.MetadataRegistry_Ref;
this.MetadataRegistry = (this.MetadataRegistry === undefined) ? bundle_context.getService(MetadataRegistry_Ref) : this.MetadataRegistry;
this.Metadata = (this.Metadata === undefined) ? Java.type("org.openhab.core.items.Metadata") : this.Metadata;
this.MetadataKey = (this.MetadataKey === undefined) ? Java.type("org.openhab.core.items.MetadataKey") : this.MetadataKey;

// Constants
var ETOD_ITEM = "TimeOfDay";
var ETOD_GROUP = "TimesOfDay";
var DAY_TYPES = ["default", "weekday", "weekend", "dayset", "holiday", "custom"];
var EXPECTED = "Invalid metadata for Item! "
             + "Expected metadata in the form of etod=\"STATE\"[type=\"daytype\", set=\"dayset\", file=\"uri\"] "
             + "where set is required if type is dayset and file is required if type is custom.";
var ETOD_NAMESPACE = "etod";

// Load TimerMgr
this.OPENHAB_CONF = (this.OPENHAB_CONF === undefined) ? java.lang.System.getenv("OPENHAB_CONF") : this.OPENHAB_CONF;
load(OPENHAB_CONF+'/automation/lib/javascript/community/timerMgr.js');
load(OPENHAB_CONF+'/automation/lib/javascript/community/timeUtils.js');

/**
 * Return the value or a key value from the Item's metadata
 * @param {string} item name of the item
 * @param {string} namespace metadata namespace to pull
 * @param {string} key index into the configuration dict for the value
 * @return {string} value assocaited with key or null if it doesn't exist.
 */
var getValue = function(item, namespace, key) {
  var md = MetadataRegistry.get(new MetadataKey(namespace, item));
  if(md === null || md === undefined) {
    return null;
  }
  else if(key === undefined) {
    return md.value;
  }
  else {
    return md.configuration[key];
  }
}

/**
 * Verify Item and Item metadata
 * @param {string} item name of the Item
 * return {string} error string or null if the metadata checks out
 */
var verifyMetadata = function(item) {
  if(items[item].class == UnDefType.class) {
    return item +"'s state is " + items[items];
  }
  if(getValue(item, ETOD_NAMESPACE) === null) {
    return item + " lacks metadata or metadata value.";
  }
  var type = getValue(item, ETOD_NAMESPACE, "type");
  if(type === null) {
    return item + " lacks a type key."
  }
  
  if(DAY_TYPES.indexOf(type) < 0) {
    return item + " has " + type + " which is not a valid day type, expected one of " + DAY_TYPES + ".";
  }
  
  if(type == "dayset" && getValue(item, ETOD_NAMESPACE, "set") === null) {
    return item + " has type " + type + " which requires a 'set' value to be defined.";
  }
  
  if(type == "custom" && getValue(item, ETOD_NAMESPACE, "file") === null ) {
    return item + " has type " + type + " which requires a 'file' value to be defined.";
  }
  
  return null;
}

/**
 * Get a list of all the Items that have ephem metadata with type
 * @param {java.util.List} etodItems collection of all the ETOD Items
 * @param {string} type the type of day 
 * @return {java.util.List} those Items with a type metadata matching type
 */
var getType = function(etodItems, type){
  return etodItems.stream()
                  .filter(function(item){ 
                      return getValue(item.name, ETOD_NAMESPACE, "type") == type;
                   })
                  .toArray();
}

/**
 * Pull the set of Items for today based on Ephemeris
 * @param {java.util.List} etodItems collection of all ETOD Items
 * @return {java.util.List} only those Items defined for today's daytype
 */
var getTodayItems = function(etodItems) {
  /** 
  Get the Items for today. Hierarchy is:
    - custom
    - holiday
    - dayset
    - weekend
    - weekday
    - default
  */
  var startTimes = {"default": getType(etodItems, "default"),
                    /*"weekday": (!Ephemeris.isWeekend()) ? getType(etodItems, "weekday") : [],
                    "weekend": (Ephemeris.isWeekend()) ? getType(etodItems, "weekend") : [],*/
                    /*"dayset": etodItems.stream()
                                       .filter(function(item) {
                                          return getValue(item.name, ETOD_NAMESPACE, "type") == "dayset"
                                                 && Ephemeris.isInDayset(getValue(item.name, ETOD_NAMESPACE, "set"));
                                       })
                                       .toArray()*/
                    /*"holiday": (Ephemeris.isBankHoliday()) ? getType(etodItems, "holiday") : [],
                    "custom": etodItems.stream()
                                       .filter(function(item) {
                                          return getValue(item.name, ETOD_NAMESPACE, "type") == "custom"
                                                 && Ephemeris.isBankHoliday(0, getValue(item.name, ETOD_NAMESPACE, "file"));
                                       })
                                       .toArray()*/
                   };

  var dayType = null;
  /*if(startTimes["custom"].length > 0) {
    dayType = "custom";
  }
  else if(startTimes["holiday"].length > 0) {
    dayType = "holiday";
  }
  else if(startTimes["dayset"].length > 0) {
    dayType = "dayset";
  }
  else if(startTimes["weekend"].length > 0) {
    dayType = "weekend";
  }
  else if(startTimes["weekday"].length > 0) {
    dayType = "weekday";
  }
  else*/ if(startTimes["default"].length > 0) {
    dayType = "default";
  }

  logger.info("Today is a " + dayType + " day.");
  return (dayType === null) ? null : startTimes[dayType];










  
}

/**
 * Update Items to today
 * @param {java.util.List} times list of all the ETOD Items for today
 */
var moveTimes = function(times) {
  var now = ZonedDateTime.now();
  for each(var time in times) {
    if(time.state.zonedDateTime.isBefore(now.withHour(0).withMinute(0).withSecond(0))) {
      events.postUpdate(time.name, toToday(items[time.name]).toString());
      logger.info("Moved " + time.name + " to today.");
    }
  }
}

/**
 * Create timers for all Items with a time in the future
 * @param {java.util.List} times list of all the ETOD Items for todayu
 */
var createTimersGenerator = function(times, timers) {
  return function() {
    var now = ZonedDateTime.now();
    var mostRecentTime = now.minusDays(1);
    var mostRecentState = items[ETOD_ITEM];

    logger.debug("Cancelling any existing timers");
    timers.cancelAll();
    logger.debug("Existing timers have been cancelled");
    for each (var time in times) {
      var name = time.name;
      var dt = time.state.zonedDateTime
      var state = getValue(name, ETOD_NAMESPACE);

      if(dt.isBefore(now) && dt.isAfter(mostRecentTime)) {
        logger.debug("NOW:    " + state + " start time " + dt + " is in the past " 
                     + " after " + mostRecentTime);
        mostRecentTime = dt;
        mostRecentState = state;
      }

      else if(dt.isAfter(now)) {
        logger.debug("FUTURE: " + state + " scheduleing timer for " + dt);
        timers.check(state, dt, etodTransitionGenerator(state));
      }

      else {
        logger.debug("PAST  : " + state + " start time of " + dt + " is before " 
                     + now + " and before " + mostRecentState + " " + mostRecentTime);

      }
    }

    logger.debug("Created " + (Object.keys(timers.timers).length - 1) + " time of day timers");
    logger.info("The current time of day is " + mostRecentState);
    if(items[ETOD_ITEM] != mostRecentState) {
      events.sendCommand(ETOD_ITEM, mostRecentState);
    }
  }
}

/**
 * Transition to a new Time of Day
 * @TODO look into moving this to another rule we can call so it shows up in schedule
 * @param {string} state the new time of day state
 */
var etodTransitionGenerator = function(state) {
  return function() {
    logger.info("Transitioning Time of Day from " + items[ETOD_ITEM] + " to " + state);
    events.sendCommand(ETOD_ITEM, state);
  }
}

//--------------------------------------------
// Main body of rule
if(this.timers === undefined){
  logger.debug("Creating timer manager");
}
this.timers = (this.timers === undefined) ? new TimerMgr() : this.timers;

// Skip if we have a flapping timer set
if(!this.timers.hasTimer("ephem_tod_rule")) {

  // Check that all the required Items and Groups exist
  if(items[ETOD_ITEM] === undefined) {
    throw "The " + ETOD_ITEM + " Item is not defined!";
  }
  if(items[ETOD_GROUP] === undefined) {
    throw "The " + ETOD_GROUP + " Group is not defined!";
  }

  var etodItems = ir.getItem("TimesOfDay").getMembers();
  
  if(etodItems.size() == 0) {
    throw ETOD_GROUP + " has no members!";
  }

  // Check the metadata for all the relevant Items
  for each (var item in etodItems) {
    var verify = verifyMetadata(item.name);
    if(verify !== null) {
      throw verify + "\n" + EXPECTED;
    }
  }

  // Get the time Items for today
  var times = getTodayItems(etodItems);
  if(times === null){
    throw "No set of date times were found for today! Do you have a default set of date times?";
  }
  
  // Update the Items to today
  moveTimes(times);

  // Schedule a timer to wait for all the Items to update before creating the Timers.
  this.timers.check("ephem_tod_rule", 
                    "30s", 
                    createTimersGenerator(times, this.timers), 
                    true, 
                    function() { logger.info("Flapping timer, waiting before creating timers for time of day"); });

}

All of my rule templates have been rewritten for OH 4. Remove the old template under Settings → Automation, reload the page (just in case) and re add the template. Then create a new version of the rule using the new template.

Manually trigger it at least once and watch the logs. It will check all your Items and verify that everything is configured correctly. The same Items and Item metadata will work with the new template.

The specific problem is that the 3.4 rule template was written in Nashorn JS which used application/javascript as the language type. But in OH 4, GraalVM JS now uses application/javascript and that code is not compatible with GraalVM JS.

There is one other snag, you’ll have to install Announcing the initial release of openhab_rules_tools. But it’s just a quick npm install openhab-rules-tools from the $OH_CONF/automation/js folder.

Note, the rule template is located at Time Based State Machine [4.0.0.0;4.1.0.0).

1 Like

Thanks for your prompt reply!
I never used a template.
Where do I find it? (There is no Show All as hinted in the ReadMe)


Installed the openhab_rules_tools …

Tried pasting from here into a new ECMA2021 rule, but it failed.
https://raw.githubusercontent.com/rkoshak/openhab-rules-tools/main/rule-templates/ephemToD/time_state_machine.yaml

2023-05-24 21:50:39.739 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: Error: "2023-05-24T21:50:49.581+02:00[SYSTEM]" is an unsupported type for conversion to time.ZonedDateTime
        at <js>.R(/node_modules/openhab.js:2) ~[?:?]
        at <js>.check(/etc/openhab/automation/js/node_modules/openhab_rules_tools/timerMgr.js:46) ~[?:?]
        at <js>.:program(<eval>:279) ~[?:?]
        at org.graalvm.polyglot.Context.eval(Context.java:399) ~[?:?]
        at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:458) ~[?:?]

Edit: looks like I’m hit with this Time Based State Machine [4.0.0.0;4.1.0.0) - #13 by rlkoshak
Will try that workaround …

Came a bit further, but still at a loss.
Since I cannot find any template references, I paste the Code into the Rule Script.
When I run the script, I get this exception:

2023-05-24 23:08:51.186 [WARN ] [ore.internal.scheduler.SchedulerImpl] - Scheduled job 'ui.b6c5df081b.debounce' failed and stopped
org.graalvm.polyglot.PolyglotException: ID segment '{{namespace}}' contains invalid characters. Each segment of the ID must match the pattern [\w-]*.
        at org.openhab.core.common.AbstractUID.validateSegment(AbstractUID.java:101) ~[?:?]
        at org.openhab.core.common.AbstractUID.<init>(AbstractUID.java:76) ~[?:?]
        at org.openhab.core.common.AbstractUID.<init>(AbstractUID.java:59) ~[?:?]
        at org.openhab.core.items.MetadataKey.<init>(MetadataKey.java:42) ~[?:?]
        at <js>._getSingleItemMetadata(/etc/openhab/automation/js/node_modules/openhab/items/metadata/metadata.js:75) ~[?:?]
        at <js>.getMetadata(/etc/openhab/automation/js/node_modules/openhab/items/metadata/metadata.js:99) ~[?:?]
        at <js>.getMetadata(/etc/openhab/automation/js/node_modules/openhab/items/items.js:223) ~[?:?]
        at <js>.:=>(/etc/openhab/automation/js/node_modules/openhab_rules_tools/helpers.js:50) ~[?:?]
        at <js>.checkGrpAndMetadata(/etc/openhab/automation/js/node_modules/openhab_rules_tools/helpers.js:50) ~[?:?]
        at <js>.validateAllConfigs(<eval>:108) ~[?:?]

I have the following defintions in my .items file:

Group:DateTime TimesOfDay
String TimeOfDay "Current time of day [%s]" <time>

// Default day, initialization for JavaScript should be done thgrough MainUI. See https://community.openhab.org/t/oh-3-examples-how-to-boot-strap-the-state-of-an-item/108234
DateTime Default_Morning "MORNING [%s]" <time> (TimesOfDay) { etod="MORNING"[type="default"] }
DateTime Default_Day "DAY [%s]" <time> (TimesOfDay) { etod="DAY"[type="default"] }
DateTime Default_Evening "EVENING [%s]"<time> (TimesOfDay) { etod="EVENING"[type="default"] }
DateTime Default_Night "NIGHT [%s]" <time> (TimesOfDay) { etod="NIGHT"[type="default"] }
DateTime Default_Bed "BED [%s]" <time> (TimesOfDay) { etod="BED"[type="default"] }

And I tuned the script to those item names:

var STATE_ITEM  = "{{TimeOfDay}}";
var DT_GROUP    = "{{TimesOfDay}}";

Even made a namspace item that I sent the command “etod” to:
String namespace “etod”

Seems like the script cannot get to the .items definitions …

Noticed this in my log. Could be why I’m not seeing the Community templates?

2023-05-24 23:42:57.106 [ERROR] [ity.CommunityMarketplaceAddonService] - bundle org.openhab.core.addon.marketplace:4.0.0.M2 (151)[org.openhab.core.addon.marketplace.internal.community.CommunityMarketplaceAddonService(49)] : Error during instantiation of the implementation object
java.lang.reflect.InvocationTargetException: null
        at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:?]
        at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77) ~[?:?]
        at jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:?]
        at java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) ~[?:?]

You might need to enable it. I can’t remember if it’s enabled by default. Settings → Community Marketplace and toggle on “Enable Community Marketplace” and you’ll see rule templates listed under the add-ons.

Upgrade to OH 4 M3 which should include the fix in openhab-js that will fix this problem. IIRC it was released before M3. If not you can install openhab-js by running npm install openhab from the $OH_CONF/automation/js folder and setting the add-on to not use the built in library under Settings → JavaScript Scripting.

There was a bug in the library that parses Date Time Strings which has since been fixed.

I just tested it on snapshot #3477 and can confirm that the fix exists in at least that version.

That’s not going to work. Mainly it’s not going to understand what to do with the properties and it’s not going to to the parameter substitution ( the stuff in {{ }} gets replaced with the value selected for that given parameter when the rule is instantiated from the template).

You could modify things manually but it’s better to install the template from the marketplace. Then you will create a new rule and select the template to create the rule from. You’ll have some properties to fill in and then the rule will be instantiated.

It has always been enabled.

Guess this is my problem:

2023-05-24 23:42:57.106 [ERROR] [ity.CommunityMarketplaceAddonService] - bundle org.openhab.core.addon.marketplace:4.0.0.M2 (151)[org.openhab.core.addon.marketplace.internal.community.CommunityMarketplaceAddonService(49)] : Error during instantiation of the implementation object
java.lang.reflect.InvocationTargetException: null
        at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:?]
        at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77) ~[?:?]
        at jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:?]
        at java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) ~[?:?]

But in Karaf, the bundle is listed as active. Trying to restart it logs nothing:

openhab> list | grep -i community
152 │ Active  │  80 │ 4.0.0.M2               │ openHAB Core :: Bundles :: Community Marketplace Add-on Service :: Karaf

This is the only thing a search for time gives me …

When you upgraded did you do anything to any of the marketplace files in $OH_USERDATA/jsondb? There is a formatting change between OH 3 and OH 4 that requires these files to be regenerated on OH 4. I don’t know if the new upgrade tool that has been released in M3 handles this or not.

Stop OH, move any file with “marketplace” in the name out of the jsondb folder and any backup for those files in the jsondb/backup folder also. If you miss the backups OH will just move to use those instead.

I think only the org.openhab.marketplace.json needs to be deleted but you may as well be thorough. But if you are worried you can just start with that file and see what happens.

1 Like

You were right!
There was one org.openhab.marketplace.json and 4 variations in backups all from 7. April. Stopped OH, deleted them, restarted OH, and Viola.
I’m back:

2023-05-25 19:28:18.003 [INFO ] [omation.rules_tools.TimeStateMachine] - All etod Items are configured correctly
2023-05-25 19:28:18.789 [INFO ] [omation.rules_tools.TimeStateMachine] - Today is a default day.
2023-05-25 19:28:19.017 [INFO ] [omation.rules_tools.TimeStateMachine] - The current state is EVENING
^

Final question: the old rule (now deleted) had a schedule associated with it.
Still needed?

I’m not sure what you mean by a schedule. Do you mean it appeared in the Schedule rules screen? That’s just a different view of rules. It shows those rules with a “Schedule” tag which have time based triggers. But this latest version of the rule doesn’t have a time based trigger so it wouldn’t show up there even if it had the “Schedule” tag.

IC. It was a leftover from a few years back then.
Looks good now.
My system discussed so far was x86_64 Ubuntu server, but when logging in to my remote home, running a Rpi4 Bullseye 32, OH apt installed, I had to do the exact same thing minus the marketplace.

For others coming here, there are several solutions

Thanks for your support @rlkoshak :slight_smile:

And this one is only required for versions of OH 4 older than M3.

Ah, just my luck landing on M2. :slight_smile:

And after updating to M3 I get: (nothing else changed)

2023-05-25 21:34:11.680 [WARN ] [omation.rules_tools.TimeStateMachine] - Time Based State Machine Usage:
All date times must be a member of TimesOfDay.
Each member of the Group must have etod Item metadata of the following format:
  .items file: etod="STATE"[type="daytype", set="dayset", file="uri"]
  UI YAML: use 'etod' for the namespace and metadata format:
    value: STATE
    config:
      type: daytype
      set: dayset
      file: uri
Where "STATE" is the state machine state that begins at the time stored in that Item, "daytype" is one of "default", "weekday", "weekend", "dayset", "holiday", or "custom". If "dayset" is chosen for the type, the "set" property is required indicating the name of the custom dayset configured in Ephemeris. If "custom" is chosen as the type, the "file" property is required and should be the fully qualified path the the Ephemeris XML file with the custom holidays defined. The "set" and "file" properties are invalid when choosing any of the other "types".
2023-05-25 21:34:12.121 [WARN ] [omation.rules_tools.TimeStateMachine] - The config is not valid, cannot proceed!

There should be one or more line above that that starts with something like"Item X’s configuration is invalid:" with a message for what’s wrong with it.

Ah, silly me …

2023-05-25 22:17:29.412 [WARN ] [omation.rules_tools.TimeStateMachine] - Item Weekend_Bed's configuration is invalid:
Weekend_Bed is not initialized!: NULL
2023-05-25 22:17:29.422 [WARN ] [omation.rules_tools.TimeStateMachine] - Item Default_Evening's configuration is invalid:
Default_Evening is not initialized!: UNDEF
2023-05-25 22:17:29.429 [WARN ] [omation.rules_tools.TimeStateMachine] - Item Default_Morning's configuration is invalid:
Default_Morning is not initialized!: NULL
2023-05-25 22:17:29.434 [WARN ] [omation.rules_tools.TimeStateMachine] - Item Default_Night's configuration is invalid:
Default_Night is not initialized!: NULL
2023-05-25 22:17:29.444 [WARN ] [omation.rules_tools.TimeStateMachine] - The following Items have an invalid configuration: Weekend_Bed,Default_Evening,Default_Morning,Default_Night

Group:DateTime TimesOfDay
String TimeOfDay "Current time of day [%s]" <time> 

// Default day, initialization for JavaScript should be done thgrough MainUI. See https://community.openhab.org/t/oh-3-examples-how-to-boot-strap-the-state-of-an-item/108234
DateTime Default_Morning "MORNING [%s]" <time> (TimesOfDay) { etod="MORNING"[type="default"] }
DateTime Default_Day "DAY [%s]" <time> (TimesOfDay) { etod="DAY"[type="default"] }
DateTime Default_Evening "EVENING [%s]"<time> (TimesOfDay) { etod="EVENING"[type="default"] }
DateTime Default_Night "NIGHT [%s]" <time> (TimesOfDay) { etod="NIGHT"[type="default"] }
DateTime Default_Bed "BED [%s]" <time> (TimesOfDay) { etod="BED"[type="default"] }

// Weekend day, notice that not all the states are listed, the unlisted states are skipped
DateTime Weekend_Day "WEEKEND DAY [%s]" <time> (TimesOfDay) { channel="astro:sun:home:rise#start", etod="DAY"[type="weekend"] }
DateTime Weekend_Evening "WEEKEND DAY [%s]" <time> (TimesOfDay) { channel="astro:sun:home:set#start", etod="EVENING"[type="weekend"] }
DateTime Weekend_Bed "WEEKEND BED [%s]" <time> (TimesOfDay) { etod="BED"[type="weekend"] }

But this worked on M2. I also tried deleting and recreating the rule. Same error.

Well the error should be pretty clear. The states of those Items-- are NULL. The rule requires all the members of the Group TimesOfDay to have a valid state. They can’t be NULL. They can’t be UNDEF.

Something happened during the upgrade that caused those Items to not restoreOnStartup or something is about all I can guess.

Yes, population from influx probably failed. Plan a separate thread for that. It times out. Probably because I have a lot of history. Seems OK after a while, as I get historical values in my sitemap graphs.

Repopulated and now it is OK. How did you see they were NULL/UNDEF?
Log just said ‘invalid configuration’, not invalid value …

        Default_Evening.sendCommand("18:00:00")
        Default_Morning.sendCommand("06:00:00")
        Default_Day.sendCommand("09:00:00")
        Default_Night.sendCommand("23:00:00")
        Default_Bed.sendCommand("23:59:59")
        Weekend_Bed.sendCommand("23:59:59")

Ah, never mind, now I see the log messages. Line breaks tricked me … :slight_smile:

M3 did not turn out well for me …
No rules were executed! Tried rebooting several times. Could control items, but no rules triggered.
Downgraded to M2 and all was well again, but when the ephemTOD script startet at 00:05 it threw this:

2023-05-26 00:05:14.987 [INFO ] [omation.rules_tools.TimeStateMachine] - All etod Items are configured correctly
2023-05-26 00:05:15.256 [INFO ] [omation.rules_tools.TimeStateMachine] - Today is a default day.
2023-05-26 00:05:15.346 [WARN ] [omation.rules_tools.TimeStateMachine] - There is no date time for today before now, we can't know what the current state is.

Same on my 2nd site:

2023-05-26 00:05:10.794 [INFO ] [omation.rules_tools.TimeStateMachine] - All etod Items are configured correctly
2023-05-26 00:05:10.955 [INFO ] [omation.rules_tools.TimeStateMachine] - Today is a default day.
2023-05-26 00:05:11.056 [WARN ] [omation.rules_tools.TimeStateMachine] - There is no date time for today before now, we can't know what the current state is.

Seems like it started working on the MORNING trigger:

2023-05-26 01:29:20.262 [WARN ] [omation.rules_tools.TimeStateMachine] - There is no date time for today before now, we can't know what the current state is.
2023-05-26 01:35:56.265 [INFO ] [omation.rules_tools.TimeStateMachine] - All etod Items are configured correctly
2023-05-26 01:35:56.478 [INFO ] [omation.rules_tools.TimeStateMachine] - Today is a default day.
2023-05-26 01:35:56.509 [WARN ] [omation.rules_tools.TimeStateMachine] - There is no date time for today before now, we can't know what the current state is.
2023-05-26 01:37:39.177 [INFO ] [omation.rules_tools.TimeStateMachine] - All etod Items are configured correctly
2023-05-26 01:37:39.294 [INFO ] [omation.rules_tools.TimeStateMachine] - Today is a default day.
2023-05-26 01:37:39.325 [WARN ] [omation.rules_tools.TimeStateMachine] - There is no date time for today before now, we can't know what the current state is.
2023-05-26 01:37:39.327 [WARN ] [omation.rules_tools.TimeStateMachine] - time.toZDT()=2023-05-26T01:37:39.326+02:00[SYSTEM]
2023-05-26 07:00:00.016 [INFO ] [omation.rules_tools.TimeStateMachine] - Transitioning Time State Machine from EVENING to MORNING
2023-05-26 07:00:00.016 [INFO ] [omation.rules_tools.TimeStateMachine] - Transitioning Time State Machine from EVENING to MORNING
2023-05-26 07:00:00.017 [INFO ] [omation.rules_tools.TimeStateMachine] - Transitioning Time State Machine from EVENING to MORNING
2023-05-26 07:00:00.017 [INFO ] [omation.rules_tools.TimeStateMachine] - Transitioning Time State Machine from EVENING to MORNING
2023-05-26 07:00:00.019 [INFO ] [omation.rules_tools.TimeStateMachine] - Transitioning Time State Machine from EVENING to MORNING
2023-05-26 07:00:00.028 [INFO ] [omation.rules_tools.TimeStateMachine] - Transitioning Time State Machine from EVENING to MORNING
2023-05-26 07:00:00.042 [INFO ] [omation.rules_tools.TimeStateMachine] - Transitioning Time State Machine from EVENING to MORNING
2023-05-26 07:37:25.351 [INFO ] [omation.rules_tools.TimeStateMachine] - All etod Items are configured correctly
2023-05-26 07:37:25.471 [INFO ] [omation.rules_tools.TimeStateMachine] - Today is a default day.

And now the 2nd site followed suit am hour later.

First is at GMT+2, the other one at GMT+1
There’s something fishy with DST…

That happens when the current time is before any of the times in your Items, in this case you’re default day Items.

In this case the rule depends on restoreOnStartup to determine the current time of day since it can’t figure it out on it’s own.

But if you saw that in the logs, it means at least this one rule triggered.