Timer firing only on first run

I am using openHAB2. I have created a rule to arm my security system 10 minutes after the system is ready between 10 pm and 6 am. It works fine when the event occurs for the first time but is not working on subsequent firing of the event. Here is my code:

var Timer timerStay = null
rule "Arm security"
	when
		Item alarmPanelStatusReady changed to 1
	then
		var Number hour = now.getHourOfDay	
		if ((hour >= 22)  || (hour <= 6)) {
			if(alarmPanelStatusReady.state as DecimalType == 1) {
			  if(timerStay == null) {
			    timerStay = createTimer(now.plusMinutes(10)) [|
			       sendCommand(armStay,ON)
			    `]`
			   }
			}
			else if(timerStay != null) {
			  timerStay.cancel()
			  timerStay = null
			}
		}
end

This line is superfluous since your rule is set to trigger on “alarmPanelStatusReady changed to 1”.

I am not sure if this made it’s way in when you copied your code, but there seems to be some “back ticks” in the above that should not be there.

Given that you test for timer == (and !=) null, it is probably a good idea to set the timer variable to null also when your timer expires, i.e.

As to the functionality, I am not sure exactly how this is supposed to work. Right now you need to change “alarmPanelStatusReady” to “1” to enable the timer (to arm your system) but also to subsequently cancel the timer. Is this correct?

I am not sure how timer works, so was trying to use an existing code that I copied for the web. My requirement is to be able to send a command (armStay) after 10 minutes of firing an event (alarmPanelStatusReady changed to 1). If timer has started and the event is fired again, timer should get reset again to 10 minutes. How do I achieve this?

I’d try the following:

var Timer timerStay = null
rule "Arm security"
	when
		Item alarmPanelStatusReady changed to 1
	then
		var Number hour = now.getHourOfDay	
		if ((hour >= 22) || (hour <= 6)) {
			if(timerStay != null) {
				timerStay.cancel()
				timerStay = null
			}
			timerStay = createTimer(now.plusMinutes(10)) [|
				timerStay = null
				armStay.sendCommand(ON)
			]
		}
end

With this you will create a “fresh” timer every time alarmPanelStatusReady is changed to 1, regardless of whether a timer is already running or not.

Thanks, that worked like a charm! I think I understand the code better now. I still have a question though. When we cancel the timer with cancel(), why do we still have to make it null? What’s the value of timer after it is canceled?

if(timerStay != null) {
				timerStay.cancel()
				timerStay = null    '???

You don’t have to as such, but given that we are using a check for null in the rule to decide if a timer is active (running) or not, then we need to make sure it is null when applicable. Since cancel() does not set the timer variable to null, we need to do it “manually”.

I am not sure, but I suspect it has the same value as before. I guess it is basically a pointer to a timer object, so it may still point to an object that is no longer valid (or something).

Thanks, that was very helpful in my understanding of timers.

Only to confuse a bit more :slight_smile:
you could omit setting timer to null when using

if (!myTimer.running)

instead of testing null

Hmm… I agree that this is a good alternative (or even the right way to do it), HOWEVER, for some reason it does not seem to work (in my setup, at least).

According to OpenHAB Designer auto-complete, I can find the following members/methods on a Timer object:

.running
.isRunning()
.hasTerminated
.hasTerminated()

I cannot get any of these to work…