Limits in number of timers?

Hi there,
I’m using OH 2.5.0.1 on a Raspi Pi3. Have it running stable for about half a year now with several Sensors and switches. Going to add more rollershutters with different opening/closing time.
Using the following rule to define timers for the rollershutters:

var Timer uptimer = null
var Timer downtimer = null
var Timer finaldowntimer = null
var Timer SZ_uptimer = null
var Timer SZ_downtimer = null
rule “Zeitbestimmung Rollos”
when
System started or
Time cron “0 2 0 * * ? *”
then

uptimer = createTimer(new DateTime (Rollo_hoch.state.toString), [
Rollo_Terassentuer_Percent.sendCommand(100)
createTimer(now.plusSeconds(60),[Rollo_Couch_Percent.sendCommand(100)])
createTimer(now.plusSeconds(120),[Rollo_Kueche_Percent.sendCommand(100)])
createTimer(now.plusSeconds(180),[Rollo_Schreibtisch_Percent.sendCommand(100)])
uptimer = null])

downtimer = createTimer(new DateTime (Rollo_runter.state.toString), [
if (Wohnzimmer_Terrassentuer.state==CLOSED && Fliegentuer_drin.state==OFF ) {Rollo_Terassentuer_Percent.sendCommand(50)}
createTimer(now.plusSeconds(60),[Rollo_Kueche_Percent.sendCommand(0)])
createTimer(now.plusSeconds(120),[Rollo_Couch_Percent.sendCommand(0)])
createTimer(now.plusSeconds(180),[Rollo_Schreibtisch_Percent.sendCommand(0)])
downtimer = null])

finaldowntimer = createTimer(new DateTime (closeofday), [
if (Wohnzimmer_Terrassentuer.state==CLOSED && Fliegentuer_drin.state==OFF ) {Rollo_Terassentuer_Percent.sendCommand(0)}
finaldowntimer = null])

SZ_uptimer = createTimer(new DateTime (morning_endplus), [
Rollo_SZlinks_Percent.sendCommand(100)
createTimer(now.plusSeconds(45),[Rollo_SZmitte_Percent.sendCommand(100)])
SZ_uptimer = null])

SZ_downtimer = createTimer(new DateTime (evening_endplus), [
Rollo_SZlinks_Percent.sendCommand(0)
createTimer(now.plusSeconds(45),[Rollo_SZmitte_Percent.sendCommand(0)])
SZ_downtimer = null])
end

Purpose of this rule is to have the rollershutters opening and closing after each other and not in parallel. I did want to have a minute between the different shutters. I did read that using sleep is a bad idea and found some examples using „fire and forget“ timers.

The problem – since I added the last two timers (SZ_uptimer & SZ_downtimer) i get errors when timers fire. The actions are performed but I’m of course not happy to see errors in the log. Have shifted the time, so there are no timers firing simultaneously (e.g. downtimer at 22 and SZ_downtimer at 22:05)
Errormsg in logfile looks like the attached:

2020-07-23 22:00:00.004 [ERROR] [org.quartz.core.JobRunShell ] - Job DEFAULT.Timer 108 2020-07-23T22:00:00.000+02:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ {
.sendCommand()
createTimer(,)
createTimer(,)
createTimer(,)
.downtimer =
} ] threw an unhandled Exception:
java.lang.NullPointerException: null
at org.eclipse.smarthome.model.script.engine.ScriptError.(ScriptError.java:65) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:140) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:991) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:954) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:235) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluateArgumentExpressions(XbaseInterpreter.java:1205) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1135) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:1081) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:151) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:861) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:231) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:458) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:239) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:201) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:29) ~[?:?]
at com.sun.proxy.$Proxy270.apply(Unknown Source) ~[?:?]
at org.eclipse.smarthome.model.script.internal.actions.TimerExecutionJob.execute(TimerExecutionJob.java:48) ~[?:?]
at org.quartz.core.JobRunShell.run(JobRunShell.java:202) [bundleFile:?]
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [bundleFile:?]

Could you give me some hints there?

Please use How to use code fences.

Do you see these errors when you reload the .rules file? If so that’s to be expected. Your running timers become orphaned when reloading a .rules file so when the timer expires it can’t run the code in the lambda because it no longer has it’s context.

The error posted comes from downtimer. And its caused by an evaluation but it’s not clear which of those lines it’s failing on. If this isn’t just caused by orphaned timers, you will need to add some logging to try and identify which line it’s failing on. Given that timer, I would guess it’s in the if statement.

Hi Rich,
thanks for your reply! Will try to use code fences next time - I always wondered how people do it but was not thinking to the end in order to be able to do it the nice way myself.

I would hope that the effect comes from orphaned timers, because the code worked for months before I added the last two timers in the rule. Should be easy to check - I just need OH one day untouched - right?
So if I don’t change the code the orphaned timers would disappear until the next day.

Will let you know the outcome. I indeed stumbled often over the fact that after I change something in the script causing a restart or recompilation my shutters get crazy for the rest of the day - but the next day everything is fine.

Cheers Frank

Your script appears to do no validation of the target times held in your Items; sometimes it’s going to try to create timers with scheduled times in past, I would think?
Not quite sure what happens then! Immediate execution I should think, which in your case will spawn more timers.

Hi there,
seems indeed the reason were orphaned timers. I didnt touch the programming for the last days and everything worked like expected without error messages. Thanks a lot for the hint! - Although I don’t know why I didnt spot it before, probably the effect was caused by more orphaned timers than before.
Is there a nice possibility to spot and cancel orphaned timers? I bet I’m not the only one falling into that hole.
I think I’m going to add validation of the target times like proposed by rossko57 - this probably avoids the “going crazy” effect of shutters ervery time I’m recompiling.
Cheers Frank

No. Once orphaned, they are inaccessible.

(The substitute for createTimer() functions in the new rule engine does allow you to deal with them if the rule is unloaded. This will never happen in DSL.)

In Rules DSL no. In openHAB 3 Rules Engine (i.e. NGRE), at least with Python and I suspect with the other languages there is a special function you can define called scriptUnloaded that gets called just prior to the rules becoming unloaded. You can and should cancel your timers in that function to avoid orphaned timers in the first place.

Maybe. Rules DSL has been ported to the OH3 Rules Engine. If not now, there might be work in the future to add some of the missing features like this to Rules DSL.