How to 'createTimer' and 'Timer.cancel' when item change state?

Hi all,

I have created a ‘Notifications.rules’ where I put all things related to notifications. I have created a new ‘var Timer "name"Timer = null’ for each Item I want a timer attached to.

Now I’m tying to create a timer that will send a notification when my garagedoor has been open for 30 min. unless the door is closed before then it needs to be cancled.

With the kind help I go in this post

I’m trying to reuse the code.

But I’m having difficulty with canceling the timer if item change back…

var String Message6 = ‘Garage | Port 2 har stået åbent i 30 minutter! sent from openHAB’

// This rule sends a telegram notification if garagedoor has been open for 30 min.
rule "Send telegram Notification | Garagedoor 2 open for 30 min."
when
Item Garage_Port_2_State_Closed changed to CLOSED
then
if(garagedoor2Timer == null || garagedoor2Timer.hasTerminated) {
garagedoor2Timer = createTimer(now.plusMinutes(30), [|
garagedoor2Timer = null
])
sendTelegram((TelegramBots), (Message6))
}

else
if Item Garage_Port_2_State_Closed changed to OPEN
then
garagedoor2Timer.cancel() //Terminate timer if door is closed before the timer ends
end

Thanks.

BR Søren

NOTE: It is easier to read code if you use code formatting on your postings. Just surround your code with triple backticks like the following:

```
You code goes here
```

I see two errors with your code which might be your problem and some syntax errors.

When you create a Timer, the stuff inside the “[ | ]” is what gets executed when the Timer goes off. You only have garagedoor2Timer = null inside the timer block. Your sendTelegram is outside the timer block so it will immediately send your message rather than waiting for the Timer to expire.

Don’t you want to set the timer when Garage_Port_2State_Closed is OPEN? Your intent is to send the alert when the door has been open for more than 30 minutes, not closed for more than 30 minutes.

Syntax wise, your else clause is not proper syntax. It looks like you are trying to apply the Rule’s Trigger syntax to an if statement which is incorrect. I highly recommend getting Designer and editing your config with it as it will point out syntax errors as you type. The big thing to realize is that a Rules trigger is based on an event. As soon as the described event occurs (e.g. Garage_Port_2_State_Closed changed to CLOSED) the Rule triggers. A if statement is testing for the current state. The difference is subtle but important. So in this case, it makes no sense to have an if statement test for changed to because that is an event, not a state.

So as written your code should look like:

var String Message6 =	'Garage | Port 2 har stået åbent i 30 minutter! sent from openHAB'

// This rule sends a telegram notification if garagedoor has been open for 30 min.
rule "Send telegram Notification | Garagedoor 2 open for 30 min."
when
    Item Garage_Port_2_State_Closed changed to OEPN
then
    if(garagedoor2Timer == null || garagedoor2Timer.hasTerminated) {
        garagedoor2Timer = createTimer(now.plusMinutes(30), [|
            garagedoor2Timer = null
            sendTelegram((TelegramBots), (Message6))
        ]) 
    }
end

rule "Cancel telegram Notification | Garagedoor 2 open for 30 min."
when
    Item Garage_Port_2_State_Closed changed to OPEN
then
    garagedoor2Timer.cancel() //Terminate timer if door is closed before the timer ends
end

Hi Rich,
Thank you for educating me, I appreciate it :slight_smile:

All this coding/programing is new to me, only been at it for a couple of weeks, but I find it easier to learn by doing. Syntax, clause, if statement is very new to me. I’m already using Designer but thanks for the tip. I’m slowly migrating from Domoticz to openHAB where I have worked a little with Lua scripting and used ‘else’ and ‘elseif’. I thought it worked here as well :slight_smile:

My garage door automatic has two build-in reed sensor. One sensor are OPEN when door is fully closed and the other is OPEN when the door is fully open. My rule is based on the sensor that is OPEN when door is closed, so when that change to CLOSED the door is either ajar og fully open. I have actually made a rule that looks at both sensors and if they are both CLOSED it sets a dummy item to OPEN setting the door ajar so now I’m able to see if the door is (fully) open, ajar or closed. And using visibility in sitemaps it only shows the item that is active. I’m actually kind of proud of have succeeded in making it work the way I wanted :slight_smile:

Thanks for the code, I will implement it right away.

Btw. is i correctly assumed that I need a new Timer e.g. garagedoor2Timer, doorbellTimer for each rule? It is true that I cannot reuse timers?

BR Søren

That is a clever way to tell if the door is fully open or ajar. I had a spare Raspberry Pi camera module so I just hooked it up to the Raspberry Pi that controls the door. If I ever need to check I just bring up the feed.

This is more difficult to answer than you might expect.

Think of a Timer as wrapper around a little chunk of code (technically called a lambda) scheduled to run sometime in the future. The “garagedoor2Timer” is a handle on that wrapper which will let you reschedule, cancel that little chunk of code from running, or check to see if the timer has or has not already run.

So what happens if you create a Timer but don’t assign it to a variable (in this case “garagedoor2Timer”)? Well the little chunk of code is still scheduled to run in the future and it still will run in the future. However, you didn’t save the handle to it so you can’t cancel it, check to see if it has or hasn’t run, or do anything else with it.

So what happens if you try to reuse “garagedoor2Timer” in other rules? Well, if you created a timer and assigned the handle to it to garagedoor2Timer when the garage door opened, then before it expires create a new timer and assign that handle to garagedoor2Timer when the doorbell rang, you have just overwritten (read lost) the handle on the the first Timer. In this scenario, the following will happen:

  • garage door closes before both Timers expire: the timer created for the doorbell will be canceled, the timer created for the garage door will still run until it triggers and completes

  • garage door closes after the garage door Timer expires: the timer created for the doorbell will still run but you will lose the handle on that timer because your garage door timer reassigns the handle to null.

  • garage door opens after the doorbell Timer was created: no garage door timer will be created because “garagedoor2Timer” is not null nor has it expired.

So, hopefully you can see, you need to keep the handles for different Timers in their own variable or else you end up overwriting your variables and end up with strange and undesirable interactions between them.

2 Likes

Thanks for the explanation, I see what you are getting at.

Actually I initially started to using the same Timer for several rules but after some thoughts I was afraid that times could cancel each other out so decided to create a new Timer for every rule needing it.

Your code seems to work consistently on garage door 1 but not everytime on door 2,

I had to add

import org.openhab.model.script.actions.Timer

But both before and after adding the import line I’m seeing this error:

2016-05-19 21:47:55.344 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Cancel telegram Notification | Garage
door 2 open for 30 min.': cannot invoke method public abstract boolean org.openhab.model.script.actions.Timer.cancel() on null

Complete code for the two doors:

// This rule sends a telegram notification if garagedoor has been open for 30 min.
rule "Send telegram Notification | Garagedoor 1 open for 30 min."
when
    Item Garage_Port_1_State_Closed changed to CLOSED
then
    if(garagedoor1Timer == null || garagedoor1Timer.hasTerminated) {
    	garagedoor1Timer = createTimer(now.plusMinutes(2), [|
    		garagedoor2Timer = null
    	sendTelegram((TelegramBots), (Message7))
    	])      		
	}
end

rule "Cancel telegram Notification | Garagedoor 1 open for 30 min."
when
    Item Garage_Port_1_State_Closed changed to OPEN
then
    garagedoor1Timer.cancel() //Terminate timer if door is closed before the timer ends
end

// This rule sends a telegram notification if garagedoor has been open for 30 min.
rule "Send telegram Notification | Garagedoor 2 open for 30 min."
when
    Item Garage_Port_2_State_Closed changed to CLOSED
then
    if(garagedoor2Timer == null || garagedoor2Timer.hasTerminated) {
    	garagedoor2Timer = createTimer(now.plusMinutes(2), [|
    		garagedoor2Timer = null
    	sendTelegram((TelegramBots), (Message8))
    	])     
	}
	
rule "Cancel telegram Notification | Garagedoor 2 open for 30 min."
when
    Item Garage_Port_2_State_Closed changed to OPEN
then
    garagedoor2Timer.cancel() //Terminate timer if door is closed before the timer ends
end

The designer do say “missing ‘end’ at ‘rule’” at line “rule “Cancel telegram Notification | Garagedoor 2 open for 30 min.”” but I have looked and looked and I do not see any difference in Cancel rule for door 1 and door 2.

Does it have anything to say that this is the last rule in rules file?

BR Søren

First the easy thing.

Indeed, you do not have an “end” at the end of your “Send telegram Notification | Garagedoor 2 open for 30 min.”

// This rule sends a telegram notification if garagedoor has been open for 30 min.
rule "Send telegram Notification | Garagedoor 2 open for 30 min."
when
    Item Garage_Port_2_State_Closed changed to CLOSED
then
    if(garagedoor2Timer == null || garagedoor2Timer.hasTerminated) {
    	garagedoor2Timer = createTimer(now.plusMinutes(2), [|
    		garagedoor2Timer = null
    	sendTelegram((TelegramBots), (Message8))
    	])     
	}

end

Every rule MUST end with the word “end”. Its not optional.

The error is telling you “Hey! I saw the special word “rule” but you didn’t complete your last rule with the word “end” first!”.

You should check whether “garagedoor1Timer” or “garagedoor2Timer” are null before cancelling it. Your Garage_Port_2_State_Closed can change to OPEN without there being a timer, particularly if you are not using persistence with “restoreOnStartup”. For example, it would change from Undefined to OPEN after a rule file reload or openHAB restart the first time it is updated but in that case there would not be a Timer to cancel.

rule "Cancel telegram Notification | Garagedoor 1 open for 30 min."
when
    Item Garage_Port_1_State_Closed changed to OPEN
then
    if(garagedoor1Timer != null) garagedoor1Timer.cancel() //Terminate timer if door is closed before the timer ends
end

rule "Cancel telegram Notification | Garagedoor 2 open for 30 min."
when
    Item Garage_Port_2_State_Closed changed to OPEN
then
    if(garagedoor2Timer !=null) garagedoor2Timer.cancel()
end

Just out of curiosity: What’s the difference between

myTimer = createTimer(now.plusMinutes(2))[|
 //do stuff]

and

myTimer = createTimer(now.plusMinutes(2), [|
 //do stuff])

?

2 Likes

Both are equivalent. From the Xtext docs:

When a method call’s last parameter is a lambda it can be passed right after the parameter list. For instance if you want to sort some strings by their length, you could write :

Collections.sort(someStrings) [ a, b |
a.length - b.length
]
which is just the same as writing

Collections.sort(someStrings, [ a, b |
a.length - b.length
])
Since you can leave out empty parentheses for methods which get a lambda as their only argument, you can reduce the code above further down to:

textField.addActionListener [
textField.text = “Something happened!”
]

Personally I think it is a really bad design choice. If a lambda can/should be treated like any other object than don’t give it special syntax and abilities when it is an argument to a method call. I therefore always use the latter form.

Now if I were using Xtext for general purpose programming and had to create a bunch of action listeners like in that example I might have a different opinion of this. But for the Rules DSL I think it only adds confusion.

1 Like

Again, thank you.

I need to learn how to decode those error messages. I was looking at the line where the error message was showing.

I’m using the rrd4 persistence with (Does that help me or should I use another persistence?)

Strategies {
	// for rrd charts, we need a cron strategy
	everyDay	: "0 0 0 * * ?"
	everyHour	: "0 0 * * * ?"
	everyMinute : "0 * * * * ?"
}

Items {
	* : strategy = everyChange, restoreOnStartup
}

When reading about rules in general I’ve seen different signs ==, >=, <=, !=, >, <

== This one I know - value has to be what it equals but the others I’m unsure of.

I’ve added you new code and will keep an eye on things :slight_smile:

BR Søren

Comparison:

a == b -> true if a is equal to b (in the meaning of 1=1)
a >= b -> true if a is greater than or equal to b
a <= b -> true if a is less than or equal to b
a != b -> true if a is not equal to b
a > b  -> true if a is greater than b
a < b  -> true if a is less than b

a = b -> set a to the value of b (in difference to the first...)

Thank you, Udo.

That actually makes sense :relaxed:

If you plan on doing any charting you will want to use the everyMinute strategy for those Items. Beyond that rrd4j is a decent choice.

Personally I use a three tiered approach.

  1. Everything gets saved by MapDB and I use MapDB for restore on startup. MapDB is a good choice for this because it only saves the most recent value so it doesn’t grow and can save all data types.

  2. Things I want to chart or reference historic data about get saved to rrd4j using the everyChange and everyMinute strategy. rrd4j is nice because it doesn’t grow beyond a certain point but it can only save numerical data.

  3. Things I want to keep accurate data for a long time or want to analyze or chart using an external charting package I would use MySQL or InfluxDB. I don’t actually have a need for this right now so don’t actually have it set up in my environment.

I assign Items to the different tiers by using Groups.

That little parameter made a hole lot of difference :slight_smile: - Now the charts suddenly looks as I was expecting.

Your three tiered approach sounds like a good solution, I’ll have to look into that.

1 Like

Thanks for the link @rlkoshak :slight_smile:

I’m finding my 30 min notification unreliable. I have a equivalent notification set up in Domoticz so I’m able to check if things are working in each system. I also have a notification setup to notify every time a garage door is opened including taking a snapshot with a 18 secs delay. That works everytime.

This is how things look

Rule:

var Timer garagedoor1Timer = null
var String Message7 =				'Garage | Port 1 har stået åbent i 30 minutter! sent from openHAB'

// This rule sends a telegram notification if garagedoor has been open for 30 min.
rule "Send telegram Notification | Garagedoor 1 open for 30 min."
when
    Item Garage_Port_1_State_Closed changed to CLOSED
then
    if(garagedoor1Timer == null || garagedoor1Timer.hasTerminated) {
    	garagedoor1Timer = createTimer(now.plusMinutes(30), [|
    		garagedoor2Timer = null
    	sendTelegram((TelegramBots), (Message7))
    	])      		
	}
end

rule "Cancel telegram Notification | Garagedoor 1 open for 30 min."
when
    Item Garage_Port_1_State_Closed changed to OPEN
then
     if(garagedoor1Timer != null) garagedoor1Timer.cancel() //Terminate timer if door is closed before the timer ends
end

Item:

Contact Garage_Port_1_State_Closed				"Status: Lukket | Port 1"									<garagedoor>		(Garage) 									{ihc="<0x19f35a"}

I have installed mapdb persistence pr. your advice:

Strategies {
	default = everyChange
}

Items {
	* : strategy = everyChange, restoreOnStartup
}`

Hi
Are anyone able to see any errors in the above post. I’m having issues with this rule. Sometimes it is working (usually when I’m testing) and other times it will not send a notification.

I’m clueless at the moment as to what I should be looking at.

I tried to put logInfo in the rule, and sometimes I got this:

2016-05-26 21:39:46.514 [INFO ] [c.internal.ModelRepositoryImpl] - Refreshing model 'Notifications.rules'
2016-05-26 21:40:01.006 [ERROR] [org.quartz.core.JobRunShell   ] - Job DEFAULT.2016-05-26T21:40:01.004+02:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: org.eclipse.xtext.xbase.impl.XClosureImplCustom@6d9197 (explicitSyntax: true) threw an unhandled Exception: 
java.lang.RuntimeException: The name '<unkown>' cannot be resolved to an item or type.
	at org.openhab.model.script.interpreter.ScriptInterpreter.internalFeatureCallDispatch(ScriptInterpreter.java:67) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateAbstractFeatureCall(XbaseInterpreter.java:658) ~[na:na]
	at sun.reflect.GeneratedMethodAccessor210.invoke(Unknown Source) ~[na:na]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_75]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.7.0_75]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluateArgumentExpressions(XbaseInterpreter.java:751) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._featureCallOperation(XbaseInterpreter.java:712) ~[na:na]
	at sun.reflect.GeneratedMethodAccessor213.invoke(Unknown Source) ~[na:na]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_75]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.7.0_75]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
	at org.openhab.model.script.interpreter.ScriptInterpreter.internalFeatureCallDispatch(ScriptInterpreter.java:69) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateAbstractFeatureCall(XbaseInterpreter.java:658) ~[na:na]
	at sun.reflect.GeneratedMethodAccessor210.invoke(Unknown Source) ~[na:na]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_75]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.7.0_75]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateBlockExpression(XbaseInterpreter.java:321) ~[na:na]
	at sun.reflect.GeneratedMethodAccessor215.invoke(Unknown Source) ~[na:na]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_75]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.7.0_75]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:204) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:28) ~[na:na]
	at com.sun.proxy.$Proxy78.apply(Unknown Source) ~[na:na]
	at org.openhab.model.script.internal.actions.TimerExecutionJob.execute(TimerExecutionJob.java:44) ~[na:na]
	at org.quartz.core.JobRunShell.run(JobRunShell.java:213) ~[quartz-all-2.1.7.jar:na]
	at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557) [quartz-all-2.1.7.jar:na]
2016-05-26 21:40:01.022 [ERROR] [org.quartz.core.ErrorLogger   ] - Job (DEFAULT.2016-05-26T21:40:01.004+02:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: org.eclipse.xtext.xbase.impl.XClosureImplCustom@6d9197 (explicitSyntax: true) threw an exception.
org.quartz.SchedulerException: Job threw an unhandled exception.
	at org.quartz.core.JobRunShell.run(JobRunShell.java:224) ~[quartz-all-2.1.7.jar:na]
	at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557) [quartz-all-2.1.7.jar:na]
Caused by: java.lang.RuntimeException: The name '<unkown>' cannot be resolved to an item or type.
	at org.openhab.model.script.interpreter.ScriptInterpreter.internalFeatureCallDispatch(ScriptInterpreter.java:67) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateAbstractFeatureCall(XbaseInterpreter.java:658) ~[na:na]
	at sun.reflect.GeneratedMethodAccessor210.invoke(Unknown Source) ~[na:na]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_75]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.7.0_75]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluateArgumentExpressions(XbaseInterpreter.java:751) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._featureCallOperation(XbaseInterpreter.java:712) ~[na:na]
	at sun.reflect.GeneratedMethodAccessor213.invoke(Unknown Source) ~[na:na]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_75]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.7.0_75]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
	at org.openhab.model.script.interpreter.ScriptInterpreter.internalFeatureCallDispatch(ScriptInterpreter.java:69) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateAbstractFeatureCall(XbaseInterpreter.java:658) ~[na:na]
	at sun.reflect.GeneratedMethodAccessor210.invoke(Unknown Source) ~[na:na]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_75]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.7.0_75]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateBlockExpression(XbaseInterpreter.java:321) ~[na:na]
	at sun.reflect.GeneratedMethodAccessor215.invoke(Unknown Source) ~[na:na]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_75]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.7.0_75]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:204) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:28) ~[na:na]
	at com.sun.proxy.$Proxy78.apply(Unknown Source) ~[na:na]
	at org.openhab.model.script.internal.actions.TimerExecutionJob.execute(TimerExecutionJob.java:44) ~[na:na]
	at org.quartz.core.JobRunShell.run(JobRunShell.java:213) ~[quartz-all-2.1.7.jar:na]
	... 1 common frames omitted
2016-05-26 21:40:02.442 [INFO ] [o.o.m.s.S.                    ] - Timer_null_minutter tilbage
2016-05-26 21:40:08.853 [INFO ] [o.o.m.s.S.                    ] - Timer startet_null_minutter
2016-05-26 21:40:56.901 [INFO ] [o.o.m.s.S.                    ] - Timer_org.openhab.model.script.internal.actions.TimerImpl@3fa960_minutter tilbage
2016-05-26 21:41:47.274 [INFO ] [c.internal.ModelRepositoryImpl] - Refreshing model 'Notifications.rules'
2016-05-26 21:45:45.954 [ERROR] [org.quartz.core.JobRunShell   ] - Job DEFAULT.2016-05-26T21:45:45.945+02:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: org.eclipse.xtext.xbase.impl.XClosureImplCustom@e78269 (explicitSyntax: true) threw an unhandled Exception: 
org.eclipse.emf.common.util.WrappedException: org.eclipse.xtext.util.PolymorphicDispatcher$NoSuchMethodException: Couldn't find method ''_assignValue'' for objects [JvmVoid:  (eProxyURI: Notifications.rules#xtextLink_::0.2.6.2.0.1.1.0.0.8.7.1.1.0.0::0::/1), <null> <unkown> <XNullLiteralImpl>, null, org.eclipse.xtext.xbase.interpreter.impl.DefaultEvaluationContext@1a13e38, org.eclipse.xtext.util.CancelIndicator$1@bddb36]
	at org.eclipse.xtext.util.Exceptions.throwUncheckedException(Exceptions.java:23) ~[na:na]
	at org.eclipse.xtext.util.PolymorphicDispatcher$DefaultErrorHandler.handle(PolymorphicDispatcher.java:41) ~[na:na]
	at org.eclipse.xtext.util.PolymorphicDispatcher.handleNoSuchMethod(PolymorphicDispatcher.java:304) ~[na:na]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:286) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.assignValue(XbaseInterpreter.java:849) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateAssignment(XbaseInterpreter.java:844) ~[na:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_75]
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_75]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_75]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.7.0_75]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateBlockExpression(XbaseInterpreter.java:321) ~[na:na]
	at sun.reflect.GeneratedMethodAccessor206.invoke(Unknown Source) ~[na:na]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.7.0_75]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.7.0_75]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:204) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:28) ~[na:na]
	at com.sun.proxy.$Proxy78.apply(Unknown Source) ~[na:na]
	at org.openhab.model.script.internal.actions.TimerExecutionJob.execute(TimerExecutionJob.java:44) ~[na:na]
	at org.quartz.core.JobRunShell.run(JobRunShell.java:213) ~[quartz-all-2.1.7.jar:na]
	at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557) [quartz-all-2.1.7.jar:na]
Caused by: org.eclipse.xtext.util.PolymorphicDispatcher$NoSuchMethodException: Couldn't find method ''_assignValue'' for objects [JvmVoid:  (eProxyURI: Notifications.rules#xtextLink_::0.2.6.2.0.1.1.0.0.8.7.1.1.0.0::0::/1), <null> <unkown> <XNullLiteralImpl>, null, org.eclipse.xtext.xbase.interpreter.impl.DefaultEvaluationContext@1a13e38, org.eclipse.xtext.util.CancelIndicator$1@bddb36]
	... 23 common frames omitted

A quick scan of the code reveals that in you timer code you are setting garagedoor2Timer to null inside your garagedoor1timer which send wrong. I think you want to set garagedoor1timer to null there.

Once again, thank you @rlkoshak

I have been looking and looking at the code, but that I did not notice.

Just for good measure if other people sees this thread.

I wanted to share my experience implementing a timer rule to automatically close my garage doors after a 20 minute wait during specified hours. Thank you for your code as it was invaluable for my novice coding skills. I have two Chamberlain/Liftmaster MyQ garage door openers, I created the doors as Roller Shutter items and I still am using OpenHAB v1.8, so the check for open and closed is slightly different than yours.

I have had one issue with the door openers where they sometimes get into a locked state, rapidly flashing timer button, that keeps the rule from operating the door. These openers flash like this when someone crosses the safety sensor but typically reset after 10 seconds. I will follow up with the manufacturer regarding this issue.

import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
import org.openhab.model.script.actions.Timer

var Timer timer_GD1 = null
var Timer timer_GD2 = null

rule "Close_Garage_Doors_At_Night"
	when
		// Check if door should be closed every 10 minutes between 11pm & 6am
		// CRON "Sec Min Hour DayOMon Mon DayOWeek Year"
		Time cron "0 0/10 0-5,23 * * ?"
	then
		logInfo("MyQ", "Starting Close_Garage_Doors_At_Night Rule")
		var SCGS=SingleCarGarageDoor.state  //check state of garage rollershutter: 0=UP 100=DOWN
		logInfo("MyQ", "Checking if SINGLE car garage should be closed after 11pm.. ["+SCGS+"]")
		if(SingleCarGarageDoor.state == 0) {  //check if door is UP, then start 20Min timer to close
			logInfo("MyQ", "SingleCarGarageDoor is open after hours, leaving open for 20 minutes then closing...")
			timer_GD1 = createTimer(now.plusMinutes(20)) [|   //create a timer to close door after 20Min
				logInfo("MyQ", "SingleCarGarageDoor is being closed...")
				sendCommand(SingleCarGarageDoor, DOWN) //close rollershutter door
				logInfo("MyQ", "SingleCarGarageDoor was closed by rule 11pm-6am...")
                                timer_GD1.cancel  //stop the timer
			        timer_GD1 = null  //reset the timer
			]
		}
		var TCGS=TwoCarGarageDoor.state
		logInfo("MyQ", "Checking if TWO car garage should be closed after 11pm.. ["+TCGS+"]")
		if(TwoCarGarageDoor.state == 0) {
			logInfo("MyQ", "TwoCarGarageDoor is open after hours, leaving open for 20 minutes then closing...")
			timer_GD2 = createTimer(now.plusMinutes(20)) [|
				logInfo("MyQ", "TwoCarGarageDoor is being closed...")
				sendCommand(TwoCarGarageDoor, DOWN) 
				logInfo("MyQ", "TwoCarGarageDoor was closed by rule 11pm-6am...")
                               timer_GD2.cancel  //stop the timer
			       timer_GD2 = null  //reset the timer
			]
		}
end