How to implement timer with parameter

That line says, in English, “Give me the first switch that is on in the gIrrigation group.” No l broken down by words:

*gIrrigation - the group with your irrigation switches

  • . members - all the members as a list
  • .filter - apply a rule to give me a list of only those members that match a criteria
  • [v|v.state==ON] - this is the criteria to filter. It’s a little complicated to explain the full syntax here. Suffice to say it means those members whose state is ON
    *.head - the first item in the list

If none of your switches are on you could get a null exception here.

Hi Marcin,
I use a Vegetronix sensor together with an NETIOAVR board.
See here:

It works as it should.
Access to the NETIOAVR board via short shell script and telnet access.
Cheers
Björn

Yes, so if all of them are off, so this check will cause an error:

Error during the execution of startup rule ‘System started Irrigation’:
cannot invoke method public abstract java.lang.String
org.openhab.core.items.Item.getName() on null

how to avoid it ?

Also I have no idea about strange delay, according your code, this part is responsible for switching off current relay and switching on next one:

// Create a timer to turn off curr and turn on next
irrigationTimer = createTimer(now.plusSeconds((60 * currValveMins as DecimalType).intValue)) [|
logInfo(“Irrigation”, "Turing off " + currValveName)
currValveSwitch.sendCommand(OFF)
if((nextValveSwitch != null) && (irrigationTimer != null)){
logInfo(“Irrigation”, "Turing on " + nextValveName)
Irrigation_Curr.sendCommand(nextValveName)
nextValveSwitch.sendCommand(ON)
}

So after off immediately next one should be on, but I got:

2016-05-24 23:12:54.433 [INFO ] [penhab.model.script.Irrigation] - Irrigation started, turning on Irrigation_1
2016-05-24 23:13:40.638 [INFO ] [penhab.model.script.Irrigation] - Turing off Irrigation_1
2016-05-24 23:13:51.452 [INFO ] [penhab.model.script.Irrigation] - Turing on Irrigation_2
2016-05-24 23:14:56.232 [INFO ] [penhab.model.script.Irrigation] - Turing off Irrigation_2
2016-05-24 23:15:17.404 [INFO ] [penhab.model.script.Irrigation] - Turing on Irrigation_3
2016-05-24 23:16:15.773 [INFO ] [penhab.model.script.Irrigation] - Turing off Irrigation_3
2016-05-24 23:16:38.789 [INFO ] [penhab.model.script.Irrigation] - Turing on Irrigation_4
2016-05-24 23:17:36.284 [INFO ] [penhab.model.script.Irrigation] - Turing off Irrigation_4
2016-05-24 23:17:46.274 [INFO ] [penhab.model.script.Irrigation] - Turing on Irrigation_5
2016-05-24 23:18:49.669 [INFO ] [penhab.model.script.Irrigation] - Turing off Irrigation_5
2016-05-24 23:19:16.199 [INFO ] [penhab.model.script.Irrigation] - Turing on Irrigation_6
2016-05-24 23:20:40.171 [INFO ] [penhab.model.script.Irrigation] - Turing off Irrigation_6
2016-05-24 23:21:38.967 [INFO ] [penhab.model.script.Irrigation] - Turing on Irrigation_7
2016-05-24 23:24:04.792 [INFO ] [penhab.model.script.Irrigation] - Turing off Irrigation_7
2016-05-24 23:25:51.426 [INFO ] [penhab.model.script.Irrigation] - Irrigation is complete

All Irrigation_Time set to 0.5min, but if you check off - on it is almost one minute.

Trying to get the “Irrigaton Switch cascade” rule to work. I’m getting the following errors message in my logs:

[ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Irrigation switch cascade': The name '<XFeatureCallImplCustom>.state' cannot be resolved to an item or type.

Here is my rule:

var Timer irrigationTimer = null

rule "Irrigation switch cascade" 
when
    Item Zone_1 received command ON or
    Item Zone_2 received command ON or
    Item Zone_3 received command ON or
    Item Zone_4 received command ON or
    Item Zone_5 received command ON or
    Item Zone_6 received command ON   
then
    // Get the currently running valve
    val currValveName = Irrigation_Curr.state.toString
    val currValveSwitch = GIrrigation.members.filter[i|i.name == currValveName].head
    val currValveNum = Integer::parseInt(currValveName.split("_").get(1))
    val currValveMins = GIrrigationTimer.members.filter[t|t.name == currValveName+"_Time"].head.state as DecimalType

    // Get the next running valve in the sequence
    val nextValveNum = currValveNum + 1
    val nextValveName = "Zone_" + nextValveNum
    val nextValveSwitch = GIrrigation.members.filter[i|i.name == nextValveName].head // will be null if not found

    // Create a timer to turn off curr and turn on next
    irrigationTimer = createTimer(now.plusMinutes((currValveMins.state as DecimalType).intValue)) [|
        logInfo("Irrigation", "Turning off " + currValveName)
        currValveSwitch.sendCommand(OFF)

        if(nextValveSwitch != null) {
            logInfo("Irrigation", "Turning on " + nextValveName)
            Irrigation_Curr.sendCommand(nextValveName)
            nextValveSwitch.sendCommand(ON)
        }
        else{ 
            logInfo("Irrigation", "Irrigation is complete")
            Irrigation_Curr.sendCommand("None")
            Sprinkler_Now.sendCommand(OFF)
        }
        irrigationTimer = null
    ]
end

I’ve tried changing the createTimer line to just: IrrigationTimer = createTimer(now.plusMinutes(currValveMins) but it still doesn’t work. My zones and timers are in this format:

Switch Zone_1  "Front Yard-Main"     (GIrrigation)  {openSprinkler="0"}  
Switch Zone_2  "Front Yard-Bushes"   (GIrrigation)  {openSprinkler="1"}
Switch Zone_3  "Front Yard-Sidewalk" (GIrrigation)  {openSprinkler="2"}
Switch Zone_4  "Back Yard-Perimeter" (GIrrigation)  {openSprinkler="3"}
Switch Zone_5  "Back Yard-Interior"  (GIrrigation)  {openSprinkler="4"}
Switch Zone_6  "Front Yard-Walk Way" (GIrrigation)  {openSprinkler="5"}
Number Zone_1_Time "Zone #1 Minutes [%d mins]"  (GIrrigationTimer)
Number Zone_2_Time "Zone #2 Minutes [%d mins]"  (GIrrigationTimer)
Number Zone_3_Time "Zone #3 Minutes [%d mins]"  (GIrrigationTimer)
Number Zone_4_Time "Zone #4 Minutes [%d mins]"  (GIrrigationTimer)
Number Zone_5_Time "Zone #5 Minutes [%d mins]"  (GIrrigationTimer)
Number Zone_6_Time "Zone #6 Minutes [%d mins]"  (GIrrigationTimer)

Any help would be appreciated.

There is a function createTimerWithArgument which allows you pass an argument to the closure.
Maybe this will help you?

Also for such complex rules you should (imho) consider the jsr223-binding to create rules (e.g. jython or something else).

The error is complaining about one of your calls to .state is referencing an Item that doesn’t exist. I think your problem is

(currValveMins.state as DecimalType)

You have already extracted and cast the state from GIrrigationTimer to populate currValveMins. In otherwords, currValveMins is already a DecimalType, not an Item.

1 Like

Hi Rich,
I changed the line to:

irrigationTimer = createTimer(now.plusMinutes(currValveMins))

and received this error message.

[o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Irrigation switch cascade': Could not invoke method: org.joda.time.DateTime.plusMinutes(int) on instance: 2016-08-31T13:15:41.555-04:00

I am importing org.joda.time.* at the top of the rules file. Anything else I’m missing or doing wrong?

Hmmmm. You might need to explicitly get at the int using .intValue

currValveMins.intValue

OK, this is a copy of my log file after making that change:

2016-08-31 13:42:06.585 [INFO ] [penhab.model.script.Irrigation] - Turning off Zone_1
2016-08-31 13:42:06.966 [INFO ] [penhab.model.script.Irrigation] - Turning on Zone_2
2016-08-31 13:43:07.317 [INFO ] [penhab.model.script.Irrigation] - Turning off Zone_2
2016-08-31 13:43:07.371 [INFO ] [penhab.model.script.Irrigation] - Turning on Zone_3
2016-08-31 13:43:42.427 [WARN ] [g.openhab.io.net.http.HttpUtil] - Method failed: HTTP/1.1 500 Internal Server Error
2016-08-31 13:44:07.440 [INFO ] [penhab.model.script.Irrigation] - Turning off Zone_3
2016-08-31 13:44:07.491 [INFO ] [penhab.model.script.Irrigation] - Turning on Zone_4
2016-08-31 13:45:07.544 [INFO ] [penhab.model.script.Irrigation] - Turning off Zone_4
2016-08-31 13:45:07.597 [INFO ] [penhab.model.script.Irrigation] - Turning on Zone_5
2016-08-31 13:46:07.679 [INFO ] [penhab.model.script.Irrigation] - Turning off Zone_5
2016-08-31 13:46:07.841 [INFO ] [penhab.model.script.Irrigation] - Turning on Zone_6
2016-08-31 13:47:07.948 [INFO ] [penhab.model.script.Irrigation] - Turning off Zone_6
2016-08-31 13:47:08.149 [INFO ] [penhab.model.script.Irrigation] - Irrigation is complete

I can see the zones changing on my sitemap watching the “irrigaton_curr” item I have setup. The problem I’m having now is when I look outside only the first zone is actually going on. The other zones are not actually turning on. This is a opensprinkler type system. Any ideas why OpenHAB thinks the zones are running, when actually they are not?

I figured it out. I put a 2 second thread:sleep command between the zone closing and the next zone starting up. It works great now. Maybe the commands from OpenHAB were coming to fast for OpenSprinkler to handle. Thanks for the help.

Sounds very reasonable. You might do some experimentation to see how short of a time you can have between commands and post that to the binding’s wiki page. While knowing this isn’t a big deal for day to day operation it could come up in testing like you experienced.

I am daring to revive this thread for various reasons:

  1. I am trying to implement this sprinkler / irrigation approach
  2. Silent changes were made during the discussion
  3. I am also having trouble making this work
  4. I though there is value in it for those who want to work with the thread’s solution.

I have been abstinent form OH v1 for quite a while, and seem to have forgotten a few things.
I basically implemented the following based on this thread:

sitemap irrigation label="Irrigation" {
  Frame {
    Group item=gIrriAll		label="Irrgiation Test"		icon="water_drops"
    Setpoint item=Irrigation1_1_Time|minValue=1|maxValue=30|step=1|
    Setpoint item=Irrigation1_2_Time|minValue=1|maxValue=30|step=1|
    Setpoint item=Irrigation1_3_Time|minValue=1|maxValue=30|step=1|
  }
}
Group   gIrriAll
Group   gIrrigation													(gIrriAll)
Group   gIrrigationTime												(gIrriAll)
Switch  Irrigation_1				"Zone 1 valve"					(gIrrigation, gIrriAll)
Switch  Irrigation_2				"Zone 2 valve"					(gIrrigation, gIrriAll)
Switch  Irrigation_3				"Zone 3 valve"					(gIrrigation, gIrriAll)
String  Irrigation_Curr				"Current active zone is [%s]"	(gIrriAll)
Switch  Irrigation_Auto				"Irrigation Auto"				(gIrriAll)
Switch  Irrigation_Now				"Irrigation Now"				(gIrriAll)
Number  Irrigation_1_Time 			"Zone 1 duration [%d mins]"		(gIrrigationTime, gIrriAll)
Number  Irrigation_2_Time 			"Zone 2 duration [%d mins]"		(gIrrigationTime, gIrriAll)
Number  Irrigation_3_Time 			"Zone 3 duration [%d mins]"		(gIrrigationTime, gIrriAll)
Switch  Irrigation_Allowed			"Test switch to trigger cascade"	(gIrriAll)
import org.openhab.core.library.types.*
import org.openhab.core.library.items.*
import org.openhab.core.types.*
import org.openhab.core.items.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
import org.eclipse.xtext.xbase.lib.*
import org.joda.time.*
import org.openhab.library.tel.types.CallType
import java.util.Set

// ------------------------------------------------------------------------

val Timer  irrigationTimer   = null

// https://community.openhab.org/t/how-to-implement-timer-with-parameter/10600/7

// If you have persistence and it does not save Strings use this rule
rule "System started"
  when
    System started
  then
    logInfo("Irrigation.0", "System Start: Irrigation .")
    // assumes no more than one is ON at a time
    val curr = gIrrigation.members.filter[v|v.state == ON].head
    logInfo("Irrigation.0", "System Start: Irrigation ..")
    
    if(curr == null) {
      Irrigation_Curr.sendCommand("None")
      logInfo("Irrigation.0", "System Start: Irrigation ...")
    } else {
      Irrigation_Curr.sendCommand(curr.name)
      logInfo("Irrigation.0", "System Start: Irrigation ....")

      // retrigger the cascade rule to recreate the timer
      curr.sendCommand(ON)
      logInfo("Irrigation.0", "System Start: Irrigation .....")
    }
    
    // any newly created timer duration variable won't be set until intitialised
    if (Irrigation_1_Time.state == Uninitialized) {
      logInfo("Irrigation.0", "System Start: Irrigation initialise state: Irrigation_1_Time")
      Irrigation_1_Time.postUpdate(5)
    }
    if (Irrigation_2_Time.state == Uninitialized) {
      Irrigation_2_Time.postUpdate(5)
      logInfo("Irrigation.0", "System Start: Irrigation initialise state: Irrigation_2_Time")
    }
    if (Irrigation_3_Time.state == Uninitialized) {
      Irrigation_3_Time.postUpdate(5)
      logInfo("Irrigation.0", "System Start: Irrigation initialise state: Irrigation_3_Time")
    }
    logInfo("Irrigation1.0", "System Start: Irrigation initialise state: done.")
    
    // does not take into account how long it has already been running
end


rule "Start Irrigation"
  when
    Item Irrigation_Allowed changed to ON
  then
    if(Irrigation_Auto.state == ON || Irrigation_Now.state == ON){
      // start with valve 1
      logInfo("Irrigation.0", "Irrigation started...")
      Irrigation_Curr.sendCommand(Irrigation_1.name)
      Irrigation_1.sendCommand(ON)
      logInfo("Irrigation.1", "... turning on {}", Irrigation_Curr.state)
    }
end

rule "Irrigation switch cascade"
  when
    Item Irrigation_1 received command ON or
    Item Irrigation_2 received command ON or
    Item Irrigation_3 received command ON
  then
    // Get the currently running valve
    val currValveName   = Irrigation_Curr.state.toString
    //logInfo("Irrigation.2", "... currValveName..: {}", currValveName)
    
    val currValveSwitch = gIrrigation.members.filter[i|i.name == currValveName].head
    //logInfo("Irrigation.3", "... currValveSwitch: {}", currValveSwitch.state)
    
    val currValveNum    = Integer::parseInt(currValveName.split("_").get(1))
    //logInfo("Irrigation.4", "... currValveNum...: {}", currValveNum)
    
    val currValveMins   = gIrrigationTime.members.filter[t|t.name == currValveName + "_Time"].head.state as DecimalType
    //logInfo("Irrigation.5", "... currValveMins..: {}", currValveMins)
    
    // Get the next running valve in the sequence
    val nextValveNum    = currValveNum + 1
    val nextValveName   = "Irrigation_" + nextValveNum
    
    // will be null if not found
    val nextValveSwitch = gIrrigation.members.filter[i|i.name == nextValveName].head

    // Create a timer to turn off curr and turn on next
    irrigationTimer = createTimer(now.plusMinutes(currValveMins.intValue), [|
    logInfo("Irrigation", "Turing off " + currValveName)
    currValveSwitch.sendCommand(OFF)

    // without the sleep commands OFF one ON the next follow too quickly
    Thread::sleep(2000)

    if(nextValveSwitch != null) {
      logInfo("Irrigation", "Turing on " + nextValve.name)
      Irrigation_Curr.sendCommand(nextValveName)
      nextValveSwitch.sendCommand(ON)
    } else {
      logInfo("Irrigation", "Irrigation is complete")
      Irrigation_Curr.sendCommand("None")
    }
    irrigationTimer = null
    ])
end

rule "Cancel Irrigation"
  when
    Item Irrigation_Allowed received command OFF
  then
    // Cancel any timers
    if(irrigationTimer != null && !irrigationTimer.hasTerminated) {
      irrigationTimer.cancel
    }
    irrigationTimer = null
    
    // Turn off any open valves
    gIrrigation.members.forEach[v | if(v.state != OFF) v.sendCommand(OFF) ]
    
    // Update the status
    Irrigation_Curr.sendCommand("None")
    logInfo("Irrigation", "Irrigation stopped / ended / finished.")
end

The silent change that was made (Rich’s initial line)

    // Get the next running valve in the sequence
    val nextValveName   = "Irrigation_" + currValveNum

should read (as reflected in my listing)

    // Get the next running valve in the sequence
    val nextValveName   = "Irrigation_" + nextValveNum

Persistence in rrd4j.persist:

  gIrriAll			: strategy = everyChange, restoreOnStartup

Errors I encounter…

In start-up

[ERROR] [m.r.internal.engine.RuleEngine] - Error during the execution of startup rule 'System started': cannot invoke method public abstract java.lang.String org.openhab.core.items.Item.getName() on null

which is related to this line:

    Irrigation_Curr.sendCommand(curr.name)

The next error is:

[ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Irrigation switch cascade': Cannot cast org.openhab.core.types.UnDefType to org.openhab.core.library.types.DecimalType

2

related to this line:

    val currValveMins   = gIrrigationTime.members.filter[t|t.name == currValveName + "_Time"].head.state as DecimalType

Any hints appreciated.

[2018-03-10 Updated] incorporated all changes to make this a working solution

So if you are still on OH 1.x it is likely that your Rules are executing before your Items have been fully loaded and their states restored. You can see this in openhab.log. I solved this in the past by making changes to openhab.cfg to make the file polling time for rules be much longer than for everything else. This will give enough time for the Items to be fully loaded and populated with restoreOnStartup (if you are using that) before any rules start executing.

This is less of a problem on OH 2.x though some have reported it as a problem. In those there are a number of mitigations that could be applied, probably the simplest is a sleep for a second at the start of the System started rule.

The true source of the problem is that there are no members of gIrrigation that are ON when the Rule execites in which case the line val curr = gIrrigation.members.filter[v|v.state == ON].head will return null.

This could also be a bit of a bug because I think the rule will also fail any time the system started and the irrigation was not running (i.e. all members of gIrrigation were OFF). The System started Rule should be changed to:

    if(curr != null) {
        Irrigation_Curr.sendCommand(curr.name)
        logInfo("Irrigation.0", "Sys Start: ...")

        // retrigger the cascade rule to recreate the timer
        curr.sendCommand(ON)
        logInfo("Irrigation.0", "Sys Start: ....")
    }
    else {
        Irrigation_Curr.sendCommand("None")
    }

With this change if the irrigation was not running then Curr gets set to “None”.

NOTE: It has been years since I’ve looked at this code and it has a lot of moving parts. There may be some subtle side effect I don’t remember that may require more to be done.

Edit: Fixed stupid mistake on my part in the else clause. We need to send “None”, not curr.name because curr is null.

1 Like

Thank Rich, I always appreciate your input…
BTW: did you upgrade to OH2 yet?

I was hoping that the posters (@sherif, @MikeH) who implemented this solution would reply and maybe even share their exact set-up, for others to simply copy, thus avoiding making the same mistakes…

I made the change, same result…
All switches/valves are off;

val curr = gIrrigation.members.filter[v|v.state == ON].head

returns null, log registers:

[m.r.internal.engine.RuleEngine] - Error during the execution of startup rule 'System started': cannot invoke method public abstract java.lang.String org.openhab.core.items.Item.getName() on null

… and execution seems to stop there, as it does not enter the if/else

Code listed for completeness:

rule "System started"
  when
    System started
  then
    logInfo("Irrigation.0", "Sys Start: .")
    // assumes no more than one ON at a time
    val curr = gIrrigation.members.filter[v|v.state == ON].head
    logInfo("Irrigation.0", "Sys Start: ..")
    logInfo("Irrigation.0", "Sys Start: {}", curr)
    
    if(curr != null) {
      Irrigation_Curr.sendCommand(curr.name)
      logInfo("Irrigation.0", "Sys Start: ...")

      // retrigger the cascade rule to recreate the timer
      curr.sendCommand(ON)
      logInfo("Irrigation.0", "Sys Start: ....")
    } else {
      Irrigation_Curr.sendCommand(curr.name)
      logInfo("Irrigation.0", "Sys Start: .....")
    }
    
    // does not take into account how long it has already been running
end

I wrote the Migration Tutorial and upgraded to write that. I’ve been running OH2 since before the 2.0 release.

When this clause runs you already know that curr is null so you can’t call curr.name here. You need to send “None” as the command indicating that no irrigation is running (i.e. all the valves are OFF). That was a dumb mistake on my posting above. I’ve fixed it there too. Your rule should be:

rule "System started"
  when
    System started
  then
    logInfo("Irrigation.0", "Sys Start: .")
    // assumes no more than one ON at a time
    val curr = gIrrigation.members.filter[v|v.state == ON].head
    logInfo("Irrigation.0", "Sys Start: ..")
    logInfo("Irrigation.0", "Sys Start: {}", curr)
    
    if(curr != null) {
      Irrigation_Curr.sendCommand(curr.name)
      logInfo("Irrigation.0", "Sys Start: ...")

      // retrigger the cascade rule to recreate the timer
      curr.sendCommand(ON)
      logInfo("Irrigation.0", "Sys Start: ....")
    } else {
      Irrigation_Curr.sendCommand("None")
      logInfo("Irrigation.0", "Sys Start: .....")
    }
    
    // does not take into account how long it has already been running
end
1 Like

Thanks… all sorted now and working :slight_smile:
Have updated my revival post (Mar 9) to show a working solution.

1 Like

Want to back to Irrigation case.
Thanks to Rich I build irrigation rules 3 years ago and it was working fine, even after my OH1.8->2.4 upgrade, done a year ago.
Problem appeared suddenly without touching anything. I have recognised that my irrigation doesn’t stop :frowning:. There were no errors, just one cicuit was on … like infinitive time.
General code of “Irrigation switch cascade” I have exactly same as above. I have removed (in the begging) rule start, since it gave an error, but it works over 2 years.
Now I have added it (as above) and it looks that I have some problem with pointers:

2019-06-12 23:02:14.091 [INFO ] [se.smarthome.model.script.Irrigation] - Irrigation is complete
2019-06-12 23:03:09.827 [ERROR] [org.quartz.core.JobRunShell         ] - Job DEFAULT.2019-06-12T23:03:09.819+02:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ | {
  org.eclipse.xtext.xbase.impl.XIfExpressionImpl@1ceb54e
} ] threw an unhandled Exception: 
java.lang.NullPointerException: null
	at org.eclipse.smarthome.model.script.engine.ScriptError.<init>(ScriptError.java:66) ~[?:?]

Problem is that sometimes it works without any issues and sometime it stucks.
If problem occurred in “cascade” then irrigation is all time on.

Any ideas how to troubleshoot ?

Just to be sure, were you editing other rules or items files beforehand?
When you edit a rules file, any currently scheduled timers continue to wait until their appointed time, then usually throw a null error.
When you edit items files, Items will be reset to NULL states.

Before I will trigger/ test a rule I always wait to see “Refreshing model …” in the log.
Also I ensure that all irrigation are off and cascade rule with timers was stopped.

This is a several years old post. I’ve long since moved the code to it’s own design pattern posting and have tried to maintain that. Please review Design Pattern: Cascading Timers and make any updates necessary.

The error is occurring in a lambda somewhere, most likely the Timer but it could be any of them. Usually, when you see a null exception it is because of a problem with a type conversion (e.g. trying to cast or use the state of a Number Item in a calculation but the Item’s state is actually NULL).

I have concerns including the following.

  • The System started Rule was there for a reason. Removing it to solve an error breaks one of the assumptions the other Rules depend upon and besides, it’s always better to fix errors than to eliminate code that does something to get rid of an error.

  • The code above was written for OH 1.8. Over the years that code has had numerous bugs fixed and it’s been rewritten at least twice. I couldn’t even guarantee that that code above exactly as it is written would even be valid.

You will need to add logging to verify which lambda (i.e. which [ | ] chunk of code) is throwing the error. Then wrap the code in that lambda with a try/catch and log the actual error. Sometimes this is very informative.

In general, when Rules have worked for a long time and suddenly stop working the cause is almost always because for some reason an Item was changed, restoreOnStartup didn’t reset an Item on time or for some other reason an Item is NULL or UNDEF and the Rule doesn’t know how to handle it.

Don’t discount rossko57’s observation also. If you have a Timer running and then reload a .rules file, the Timer keeps running. And when it finally goes off the error usually looks just like what you posted. Waiting for the “Refreshing model …” before triggering the rule again and all the rest does nothing to get rid of the orphaned Timer. It’s still there and will still throw an error when it goes off.