Conversion of a 2.4 rule to OH 3.x (DSL)

Hi All

I have two rules which are failing with these errors. Seems the trigger for system started doesnt work now?

Script execution of rule with UID ‘timeofday-9’ failed: ‘withTimeAtStartOfDay’ is not a member of ‘java.time.ZonedDateTime’; line 110, column 23, length 24 in timeofday

and

Script execution of rule with UID ‘system-7’ failed: The name ‘systemStarted’ cannot be resolved to an item or type; line 71, column 7, length 13 in system

Rule:


rule "Calculate time of day state"
when
  System started or
  Channel 'astro:sun:darlingpoint:rise#event'    triggered START or
  Channel 'astro:sun:darlingpoint:set#event'     triggered START or
  Time cron "0 1 0 * * ? *" or
  Time cron "0 0 6 * * ? *" or
  Time cron "0 0 23 * * ? *"

then

  logInfo("Time Of Day", "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)
  vMorning_Time.postUpdate(morning_start.toString)

  val night_start = now.withTimeAtStartOfDay.plusDays(1).minusHours(1)
  vNight_Time.postUpdate(night_start.toString)

  val bed_start = now.withTimeAtStartOfDay
  vBed_Time.postUpdate(bed_start.toString)

  // Convert the Astro Items to Joda DateTime
  val day_start = new DateTime(vSunrise_Time.state.toString)
  val evening_start = new DateTime(vSunset_Time.state.toString)
  val afternoon_start = new DateTime(vEvening_Time.state.toString)

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

  // Publish the current state
  logInfo("Time of Day", "Calculated time of day is " + curr)
  vTimeOfDay.sendCommand(curr)
end

Any suggestions as to the fix? I was under the impression now.withTimeAtStartOfDay was still valid, as was system started

Thanks

It changed behavior in OH 3. Now it really means what it says, the system started. It doesn’t mean the rule file was just loaded. A System started rule will only trigger when OH first comes up now.

If you want to execute a rule after the .rules file is loaded, you have to do it manually. You can do this from MainUI, even for for based rules.

But the trigger is still valid.

The error is weird though as it’s complaining about “systemStarted”, not “System started”. I’m not sure what that’s about. You can try one of the new “System reached start level 40” triggers instead and see if that works. 40 is as early as a rule can run but I usually like to wait for Things to come up so usually use run level 100.

I cringe every time I see this old rule. Even in OH 2 I came up with better approachs. In OH 3 it’s so much simpler to achieve the same thing it’s probably not even worth fixing this version.

A better solution is to put the start times for all your times of day into DateTime Items (Astro is already done). Then create a rule for each one using the “Time is ItemName” trigger. The body of the rule is a one liner to send the time of day to the Item.

rule "Morning start"
when
    Time is Morning timeOnly
then
    TimeOfDay.sendCommand("MORNING")
end

Repeat for each Item and you’re good. Use restoreOnStartup on the TimeOfDay Item and you don’t even have to worry about restarts and the like. In those very rare cases where OH was down long enough to cross a time of day boundry run the proper rule manually or wait for the next time of day.

Or you can install the Time Based State Machine rule template from the marketplace and not have to write any code at all. Just configure a rule and some Items.

As for the date time error, Joda was replaced with ZonedDateTime (Java SE 11 & JDK 11 ) in OH 3 which is slightly different. Any rules that use ZonedDateTime will likely need to be adjusted. See the link above and DateTime Conversion (openHAB 3.x) for details.

In OH 3 and OH 4, working with date times in JS Scripting and jRuby is greatly simplified. In JS Scripting there is a “time.toZDT()” function that converts almost anything you could think of to a date time. So instead of now.withTimeAtStartOfDay() you could use time.toZDT(“00:00”).

1 Like

awesome thanks for taking the time to reply - Ill take your suggestion for the rule create for each one, seems easier for my application.