Resetting timers

Hi,

I’m trying to create a simple rule which detects motion and turns on lights. As long as motion continues, keep the lights on. All of the events work correctly (detecting motion, turning the light on/off). If I trigger the light on, then leave the room, it will turn off as appropriate. The issue happens when I turn the light on, then reset the timer by creating additional activity; it seems to break the timer.

Unfortunately I don’t know where the logic has failed and how to debug it. The rules are as follows:

//Define Variables
var Timer OfficeLightTimer = null

//Office Movement sensor  

rule "Office Movement"
when Item Office_Motion received update ON
then 
    if(OfficeLightTimer == null) {(Office_Lamp_pwr.sendCommand(ON))}
    else OfficeLightTimer.cancel()
end

rule "Office Light Timer"
when Item Office_Motion received update OFF
then
    if(OfficeLightTimer == null) {OfficeLightTimer = createTimer(now.plusSeconds(15), [|Office_Lamp_pwr.sendCommand(OFF)])}
    OfficeLightTimer.cancel()
end

Any advice would be very greatly appreciated.

TIA.

hmmm. I don’t see a big breaker also.
But I got rid of my timers instead of expire-binding.

You simply tell an item, what to do after an amount of time. If I understand correctly you’re sending an update to the Office_Lamp_pwr item everytime you detect movement? Then everytime an update occurs, the expire-timer gets reset automatically:

Item Switch Office_Lamp_pwr { <YourBindingForLampHere>, expire="15s,command=OFF" }

You can then deactivate the second rule and Change your first ins simply:

rule "Office Movement"
when 
    Item Office_Motion received update ON
then 
    Office_Lamp_pwr.sendCommand(ON)
end
1 Like

Hi binderth
Thanks so much for the advice.

I am detection movement via the Fibaro motion sensor (https://www.fibaro.com/en/products/motion-sensor/).

I pick up its output and put the value into a switch (Office_Motion). It will send an ‘ON’ when detecting motion and then monitor the room for several seconds. If no further activity is detected, it will update to ‘OFF’.

So my logic is that if I’m in the room, I’ll trigger an initial ‘ON’ event. From time-to-time I won’t move so it will timeout and send the ‘OFF’ signal. To avoid sitting in the dark, I’d like to set a wait timer to see if the switch goes back to ‘ON’.

If I understand your code above (and forgive me – I am only a few days into this), I don’t think it will handle the switch going ‘ON’/‘OFF’/‘ON’ without light going out.

Hi Matt,

we’re all here to learn! :wink:
But yes, the Code above does indeed trigger the Office_Lamp_pwr to OFF after 15secs (if I interpret the name correctly) - but that’s what your “Office Light Timer” rule also was supposed to do?

Just to be clear (as I don’t know the Fibaro): The device will trigger Motion (Office_Motion => ON) and will after some time without movement trigger Motion again (Office_Motion => OFF). And then you have 15secs to avoid getting the Office_Lamp_pwr to also go OFF to move again?
That’s what most newbies are struggling with. You’ve got multiple logics: the one from your “smart devices” - and the one in openHAB rules.

To see in in timeline:

(everything is OFF)

  1. movement in Office
    Office_Motion=> from OFF to ON
    Office_Lamp_pwe => from OFF to ON
  2. movement in Office
    Office_Motion => from ON to ON
    Office_Lamp_pwr=> from ON to ON (resets timer)
    <<repeats until no movement detected>>
  1. no movement in Office for some time
    Office_Motion => from ON to OFF (interval setting in your Fibaro)
    Office_Lamp_pwr=> timer 15secs from ON to OFF

so, if your Fibaro does only updates > 15secs (e.g. no frequent ONs on every movement in step2, but only after its own timer), then of course your lamp will just go out within this interval. So either set the interval of your Office_Lamp_pwr in expire to a value higher than that of your Fibaro or just set the expire-statement to your Office_Motion item and let the lamp go out accordingly.

1 Like

I think the syntax is used wrong

should be:

rule "Office Light Timer"
  when Item Office_Motion received update OFF
then
    if(OfficeLightTimer == null)
    {
         OfficeLightTimer = createTimer(now.plusSeconds(15)) //other use of () !
         [|
            Office_Lamp_pwr.sendCommand(OFF)
            OfficeLightTimer.cancel() //not needed timer is over at this point of rule
            OfficeLightTimer = null
          ]
   }
end

cancel tiemr is not needed because if OfficeLightTimer == null then timer is already canceled. And the timer will be cancels before finished because out of the []. Only what is inside of the brackets will wait until tiemr is ended.
1 Like

Your understanding of what I’m trying to achieve is bang-on, binderth.

And you’ve pointed me to my answer. The simplest approach is dealt with by the ‘multiple logic’ observation you made – get the Fibaro to manage the timer and simply respond to its results. I hadn’t realised how configurable the zwave devices are.

Thanks so much for your advice.

1 Like

Here’s how I achieved what I think your looking for. My motion sensor has a 3 minute timeout before setting the OFF command, which works quite well. So far so good, I’ve not been left in the dark yet.

I’m by no means a coder and can honestly say I struggle to get to grips most of the time. So most of my rules are very simple as you can see from the one below.

I hope this helps.

rule "Kitchen Motion Sensor Off"
when
	Item Kitchen_SP3102_Motion changed from ON to OFF
then
        var Timer Kitchen_Motion_Sensor_Timer = null
	if(Kitchen_Strip_Light_Dimmer.state > 0) {
		Kitchen_Motion_Sensor_Timer = createTimer(now.plusMinutes(1))
		[|
			if(Kitchen_SP3102_Motion.state == OFF) {
                       		Kitchen_Strip_Light_Switch.sendCommand(OFF)
			}
        ]
	}
end
1 Like

Yeah, you have some syntax issues as well as in the Office Light Timer rule, you create the timer and then cancel it on the next line rendering it useless. Here is what I would do:

//Define Variables
var Timer OfficeLightTimer = null

//Office Movement sensor

rule "Office Movement"
when Item Office_Motion changed from OFF to ON
then
	if(OfficeLightTimer!==null) {
		OfficeLightTimer.cancel()  //cancel existing timer
	}
	Office_Lamp_pws.sendCommand(ON)  //turn on light
end

rule "Office Light Timer"
when Item Office_Motion changed from ON to OFF
then
	if(OfficeLightTimer!==null) {
		OfficeLightTimer.cancel() //cancel exsiting timer
	}
	OfficeLightTimer = createTimer(now.plusSeconds(15)) [| //create new timer
        //code to run at timers end goes in this block.  Rest of rule continues.
		Office_Lamp_pws.sendCommand(OFF) // turn off light
	]
end

Note that I also changed your whens to be changed from’s. This is more reliable at system startup.

You could collapse down some of the if brackets and whatnot but I like this format for readability.

I typed the above in notepad as I’m at work so there might be a typo I’m not seeing as I don’t have error checking in notepad :slight_smile:

2 Likes

You are testing the Timer to see if it is null but never setting it back to null after it expires or you cancel it. So after you create your first Timer if(OfficeLightTimer == null) will always evaluate to false.

So set the last line of your Timer body to set OfficeLightTimer to null and be sure to set OfficeLightTimer to null after you cancel it.

The second problem is that you are missing the else in your second Rule so you create the Timer and then immediately cancel it.

I highly recommend the Expire binding, as Thomas suggested. Design Pattern: Expire Binding Based Timers will show you have to do it. It ends up making the code much simpler to write and understand. No more book keeping.

Not wrong, both are valid syntax.

1 Like

Thanks to everyone who offered advice here. I’m very new to OpenHab but am thrilled with the community spirit.

I hope to be able to contribute back in the future.

Thanks!