Clarification on Timer

Hello,

I am trying to create a basic presence detection rule but I am struggling with the timer issue.

The pseudocode I am thinking of implementing is the following

when
   main_door change to CLOSED 
then
   start Timer for 10 mins
   if group_motion_sensors change from OFF to ON or if interior_doors change
                 set presence_switch to ON and 
                 stop timer
   else if after 10 minutes mobile_in_homewifi is OFF 
              set presence_switch to off and send email

How do I go about creating the timer so that it behaves like the above code? Most examples I have seen only execute some code after the timer has elapsed but I want to execute some code during the timeframe set by the timer.

Apologies if the question sounds dump. I am not an experienced programmer

Regards,

Hello @cgeo,

if you want to use a timer you should use something like this

//Define a timer var first:
var Timer presenceTimer = null

//Now, when the timer is needed set it up like this:
presenceTimer = createTimer(now.plusMinutes(10)) [|
// everything you define here will be executed after the timer ran out (10 minutes)
presenceTimer = null //set the timer to null - just to be safe
]

When you work with rules that are triggered by motion you should consider using locks, otherwise this rule may be executed many times, which leads to concurrency.

This is only a hint and no solution for your problem. I am currently working on a similar rule and haven’t found the perfect solution yet.

Hey Phil,

Thanks for the quick reply. My rule is triggered by a change in a door state using a door sensor so no motion sensors will be in play

My problem is exactly that. The code after the createtimer will be executed after the timer has elapsed. I want to check for the if conditions during the timer (during the 10 mins) and I am not sure how to do that. Basically I want to check if any motion sensor or door sensor is triggered within the 10 mins in order to decide on presence. Maybe the timer is not something I should use ? No idea

I’ve built a similar rule and would add that for the 2nd part of your rule, when the sensor or door change you can use your if statement around those conditions and then

if (event) then {
  presenceTimer.cancel()
}

I am currently facing the exact same challenge.
Unfortunately, I don’t have a solution for that ready today. However, I have two possible solutions in mind:

  1. When the door is closed set an item (e.g. presence_evaluation) to ON; set the timer to 10 minutes and set the item to OFF when the timer elapsed
    Every time motion is detected you can check if the item (presence_evaluation) is ON and trigger an action

  2. Persist all changes to your motion item. When the door is closed, set your timer and when the timer elapsed check if there is a new persistence entry for that item.

I think that the second solution is much more efficient, but I haven’t tried it yet.

Now that I have my rules files in front of me, here is how I structured something similar. I actually used multiple rules, 2 to set the presence items and 1 to do the home/away (one big caveat is my timers aren’t working right on my Nest check, so not sure if it’s the runtime or I changed something in my code that broke it). For my Switch_HomeMode I use 1=Home, 2=Away, and 3=Vacation (manual override state hence the check on HomeMode prior to changing). Here are my rules:

// Global Variables
var Timer tMotion = null
var Timer tNest = null

val int motionTimeout = 30
val int nestTimeout = 30

//Security Motion Occupancy
rule "Security Motion Occupancy"
when
	Item Sensor_Security_Motion_Tripped changed to OPEN
then
	if(tMotion==null) {
		Sensor_Security_Motion.sendCommand(ON)
		tMotion = createTimer(now.plusMinutes(motionTimeout)) [|
			Sensor_Security_Motion.sendCommand(OFF)
			tMotion = null
		]
	} else {
		tMotion.reschedule(now.plusMinutes(motionTimeout))
	}
end

//Set Nest Occupancy Switch_HomeMode
rule "Nest Occupancy Switch"
when 
	Item Sensor_Nest_Mode changed
then
 	if(Sensor_Nest_Mode.state == "auto-away") {
 		if(tNest==null) {
 			tNest = createTimer(now.plusMinutes(nestTimeout)) [|
 				Sensor_Nest_Motion.sendCommand(OFF)
				tNest = null
			]
		} 
		else {
 			tNest.reschedule(now.plusMinutes(nestTimeout))
		}
	} 
	else if(Sensor_Nest_Mode.state == "home") {
		if(Sensor_Nest_Motion.state!= ON) {
			Sensor_Nest_Motion.sendCommand(ON)
 		}
		if(tNest!=null) {
 			tNest.cancel()
			tNest = null
 		}
	}
end
		
//Set Home/Away status
rule "Set HomeAway Status"
when
	Item Motion changed or
   Time cron "0 0 8 * * ?"
then
    val TimeOn = now.withTimeAtStartOfDay.plusHours(8).millis
    val TimeOff = now.withTimeAtStartOfDay.plusHours(22).millis
 	if((Motion.state == OFF) && now.isAfter(TimeOn) && now.isBefore(TimeOff) && (Switch_HomeMode.state == 1)) {
		Switch_HomeMode.sendCommand(2)	
	} 
	else if((Motion.state == ON) && (Switch_HomeMode.state == 2)) {
		Switch_HomeMode.sendCommand(1)
	}
end

I was able to resolve my error with some help. The above rules now work for using presence switches based on my Nest status and my security motion detector to set home/away status. Hopefully this helps you out.

See:

For your particular case I would recommend option 1, Flag. It would look something like this:

Switch DetectPresence { expire="10m,command=OFF" }
rule "Start detecting presence"
when
    Item main_door changed
then
    if(main_door.state == CLOSED) { // for now there is a bug which may make changed to CLOSED not work
        DetectPresence.sendCommand(ON)
    }
end

rule "Motion sensors or interior doors changed"
when
    Item gMotionSensors received update or
    Item gInteriorDoors received update
then
    if(DetectPresence.state == ON && Presence.state != ON) {
        Presence.sendCommand(ON)
        DetectPresence.postUpdate(OFF) // stop the Expire timer without triggering rule below
    }
end

rule "Stop detecting presence"
when
    Item DetectPresence received command OFF // this does work and is not subject to the bug mentioned above
then
    if(mobile_in_homewifi.state == OFF) {
        Presence.sendCommand(OFF)
        sendMail(...)
    }
end

Since as you describe in your logic, you only switch Presence OFF if your mobile is not on the wifi, why not just use the mobile being on the wifi as your presence detection?

The above doesn’t cover the case though where you open the main door but fail to trip any motion sensors or interior doors. When the Expire binding timer goes off your phone would be on the network but no other event occured to turn Presence ON so it will remain OFF despite your being home.

I would make the event of your phone joining the wifi one of the events that switches Presence to ON and cancels the Timer.

Also, if someone breaks into your house Presence will be set to ON and you will get no alert because you cancel the Timer.

Thank you all. Since I have not set up persistence I was forced to go for option 1.
The idea is not complicated but thank you guys a lot for the sample code it really helps speed up things.

I have search for days but it turns out I never found the ‘Do While’ guide
@rlkoshak just for the record there is a small mistake on “Start detecting presence” rule in the ‘when’ section

Item Main_door changed (it is missing Item)

It is true that with the above I need to have accurate sensors everywhere. I am planning to include switching on/off lights, TV, maybe some pressure sensors on the bed and whatever else can be triggered during the 10mins timeframe.
During testing I realised that Network binding is pretty flaky and as it looses the wifi connection sometimes for hours so I cannot rely on that alone. Ideally I would like to check this when I open the door but I am afraid it will take time for it to join the wifi (sometimes I need to really turn on the screen for it to join the network)

To make it work as a basic alarm, I am thinking of removing the 10 min duration when presence is already set to off and the main door opens but I would need some kind of recognition mechanism (combination of bluetooth, wifi or sth else ?) that would ‘recognize’ me before I open the door

I wrote it in response to your posting. It didn’t exist until yesterday.