[SOLVED] Rule createTimer

I have a TKB TSM02 ZWave sensor which has PIR Motion detection, but it doesn’t report OFF, it only reports ON.

So I created the following rule:

var timer = null

rule "TSM02 Motion OFF"
when
    Item ZW_AnaKapi_Hareket received update ON
then
    if(timer == null) {
        logInfo("FILE", "Setting to ON and creating timer")
        timer = createTimer(now.plusMinutes(2), [|
            logInfo("FILE", "Timer expired and setting to OFF")
            ZW_AnaKapi_Hareket.postUpdate(OFF)
            timer = null
        ])
    } else {
        logInfo("FILE", "Timer rescheduled")
        timer.reschedule(now.plusMinutes(2))
    }
end

But, I’m getting the following error when timer needs to be rescheduled, so the reschedule operation does not work. Looks like createTimer does not return a reference to a Timer object.

08:22:43.271 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'TSM02 Motion OFF': An error occured during the script execution: The name '<XFeatureCallImplCustom>.reschedule(<XMemberFeatureCallImplCustom>)' cannot be resolved to an item or type.

Can anybody point out what may be wrong with my rule code and how to fix it?

I don’t use openhab2, so it may have changed, but my timers are declared as

var Timer timerLivingLampstand = null

Thanks. That was it. Needed to specify variable type!

Hi , @ertanden @gpbenton

Can anybody please tell me…?
I have device TKB-TSM02 4 in 1 slim multi-sensor (PIR,Temp,Lux,Door) .
Is it supported openhab 1.7.0…?
In which version it works good…?

Regards,
shrikant

I use TSM02 in openhab2 latest snapshot without problem. The only thing needed is a rule like the following to set motion to off:

var Timer timer = null

rule "TSM02 Motion OFF"
when
    Item ZW_AnaKapi_Hareket received update ON
then
    if(timer == null) {
        logInfo("FILE", "Setting to ON and creating timer")
        timer = createTimer(now.plusMinutes(2), [|
            logInfo("FILE", "Timer expired and setting to OFF")
            ZW_AnaKapi_Hareket.postUpdate(OFF)
            timer = null
        ])
    } else {
        logInfo("FILE", "Timer rescheduled")
        timer.reschedule(now.plusMinutes(2))
    }
end
1 Like

hi

why there is need of writing rule for making state OFF…?

Regards,
shrikant

Because the sensor doesn’t set the state to OFF. It just reports when there’s motion…

may be it is acting as presence sensor…

Yes it may be related to my configuration. My TSM02 is configured in “Security Mode”, it may report state OFF in “Home Automation” mode. Didn’t try that actually.

Hi,

I have a slightly related problem: my rule is triggered by opening a door, and after 30 seconds it checks, whether the door is still open. If yes, it waits for another 30 seconds - if not, the light turns off.
Here my rule:
rule "Licht Atrium-Durchgang"
when
Item Status_F_E1_06 changed to OPEN
or
Item Status_AT_N_01 changed to OPEN
then
var Timer offTimer

if (Dawn.state == OPEN) {
	sendCommand( Licht_Atrium_Durchgang, ON)
	offTimer = createTimer(now.plusSeconds(30)) [|
		if (Status_F_E1_06.state == OPEN || Status_AT_N_01.state == OPEN) {
				offTimer.reschedule(now.plusSeconds(30))
			} else {
				sendCommand( Licht_Atrium_Durchgang, OFF)
			}			
	]
}

end

The designer marks the offTimer.reschedule command with the message: Cannot refer to the non-final variable offTimer inside a lambda expression. But the rule still works.
However I would have that clean. So can anybody suggest a better way to write this rule please?

Thanks
Matthias

1 Like

Bit late here … it’s because the variable pointing to the Timer is declared within the scope of the rule. Later on, when the Timer attempts to execute the .reschedule, the rule has completed and that variable has gone.

To fix, declare the Timer variable outside of the rule as a global

1 Like

Thanks. That solved it!

Can someone explain to me why there is a pipe character at the end of this line here?

offTimer = createTimer(now.plusSeconds(30)) [|

To tell the “compiler” to expect several lines of code
If your timer only does 1 line of code you can dispense with it:

offTimer = createTimer(now.plusSeconds(30), [ logInfo("HELLO", "WORLD") ])

and why is the round bracket in one case doubled and the other not?
createTimer(now.plusSeconds(30)) [|
versus
createTimer(now.plusSeconds(30) [| …
])
is the lampda still part of the timer code if the round bracket is used 2 times?

In your first example, you have open and closing brackets:

createTimer(now.plusSeconds(30)) [| # this has an open parens at the now.plus... and the closing after the 30, the 30 itself is in parens

createTimer(now.plusSeconds(30) [|... # this has no closing parens for the opening at the (now...

I am someone can explain better than I can, but if you have an opening parenthesis, you need a closing one. I am assuming the timer has to precede the lambda, the brackets after the timer are what is inclusive for the lambda.

~John

So both version are correct to execute the lambda when the timer starts the execution?
Or is the lambda definition in the first version independent from the timer code and due not executed what i would expect? (This version is often shown in examples but i tried it for myself and the timer did not really trigger the code)

Both versions should work the same way.
I prefer the version where the lambda is inside the createTimer action brackets. This clearly shows where the code belongs. And I find it cleaner and easier to read. The lambda code is not “floating” if you see what I mean.

1 Like