Openhab 2 Contact Sensor Time Rule

rules
openhab2
beginners
Tags: #<Tag:0x00007fd313fdc788> #<Tag:0x00007fd313fdc3a0> #<Tag:0x00007fd313fdc0a8>

(Nicholas) #1

Hey openhabians!

I’ve got the following piece of code in my rules file. I’ve got a simple contact sensor on our garage door and it sends out a notification every time it changes state (eg. Garage opens / closes = notification). I’ve also got a switch (SecuritySystem) where I can turn these notifications off!

//Garage Door Sensor Is Open

rule "Garage Door Sensor"
when
   Item MGarageDoorSensor1 received update OPEN
then
       if(SecuritySystem.state == ON)
       {
           sendBroadcastNotification("Garage Door OPEN")
       }
end


//Garage Door Sensor Is Closed
rule "Garage Door Sensor CL"
when
   Item MGarageDoorSensor1 received update CLOSED
then
       if(SecuritySystem.state == ON)
       {
           sendBroadcastNotification("Garage Door CLOSED")
       }
end

I wanted to have a rule where if the garage door has been left open for, lets say 10 minutes, it sends out a notification to everyone.

I’ve tried other solutions that have been posted in the forums but each time I add them in, none of the rules work!

Anyone have any idea?

Any help / guidance appreciated (I’m new to this)


(Vincent Regaud) #2

Use the expire binding and another item:

Switch GarageDoor_Timer { expire="10m,command=OFF" }

Rules:
//Garage Door Sensor Is Open

rule "Garage Door Sensor"
when
    Item MGarageDoorSensor1 changed
then
    if(SecuritySystem.state == ON) {
        sendBroadcastNotification("Garage Door " + triggeringItem.state.toString)
        if (triggeringItem.state == OPEN) GarageDoor_Timer.sendCommand(ON) // Start timer
        else GarageDoor_Timer.PostUpdate(OFF) // Cancel the timer
    }
end

rule "Garage Door Timer"
when
    Item GarageDoor_Timer received command OFF
then
    sendBroadcastNotification("Garage Door OPEN for 10 minutes")
end

I condensed your 2 rules into one and added a timer item and rule when it expires


(Nicholas) #3

You’re a legend!!! Thanks heaps! I’ll give it a test tomorrow!


(Rich Koshak) #4

To make this more generic you can use something like what I use. I think I’ve posted this in a DP but I can’t remember so just reposting it here.

Group:Contact:OR(OPEN,CLOSED) gDoorSensors "The doors are [MAP(en.map):%s]" <door>
Group:Switch:OR(ON, OFF) gDoorsTimers

Contact vGarageOpener1 "Garage Door Opener 1 is [MAP(en.map):%s]" <garagedoor> (gDoorSensors)
Switch vGarageOpener1_Timer (gDoorsTimers, gResetExpire) { expire="1h,command=OFF" }

Contact vGarageOpener2 "Garage Door Opener 2 is [MAP(en.map):%s]" <garagedoor> (gDoorSensors)
Switch vGarageOpener2_Timer (gDoorsTimers, gResetExpire) { expire="1h,command=OFF" }

Contact vFrontDoor "Front Door is [MAP(en.map):%s]" <door> (gDoorSensors)
Switch vFrontDoor_Timer (gDoorsTimers, gResetExpire) { expire="1h,command=OFF" }

Contact vBackDoor "Back Door is [MAP(en.map):%s]" <door> (gDoorSensors)
Switch vBackDoor_Timer (gDoorsTimers, gResetExpire) { expire="1h,command=OFF" }

Contact vGarageDoor "Garage Door is [MAP(en.map):%s]" <door> (gDoorSensors)
Switch vGarageDoor_Timer (gDoorsTimers, gResetExpire) { expire="1h,command=OFF" }

Pay special attention to the Group memberships and the naming conventions. Not shown is gResetExpire which is used in a System started rule to retrigger the expire bindings on OH restart.

val logName = "entry"

rule "Set door timer"
when
  Member of gDoorSensors changed
then
  if(previousState == NULL) return; // we don't care about changes from NULL

  val name = triggeringItem.name
  val state = triggeringItem.state

  // Set the timer if the door is open, cancel if it is closed
  if(state == OPEN) sendCommand(name+"_Timer", "ON")
  else postUpdate(name+"_Timer", "OFF")

  // Set the message
  val msg = new StringBuilder
  msg.append(transform("MAP", "en.map", name) + " was ")
  msg.append(if(state == OPEN) "opened" else "closed")

  var alert = false
  if(vTimeOfDay.state.toString == "NIGHT" || vTimeOfDay.state.toString == "BED") {
    msg.append(" and it is night")
    alert = true
  }
  if(vPresent.state == OFF) {
    msg.append(" and no one is home")
    alert = true
  }

  // Alert if necessary
  if(alert){
    msg.append("!")
    aAlert.sendCommand(msg.toString)
  }
  // Log the message if we didn't alert
  else {
    logInfo(logName, msg.toString)
  }
end

rule "Timer expired for a door"
when
  Member of gDoorsTimers received command OFF
then
  val doorName = transform("MAP", "en.map", triggeringItem.name)

  aAlert.sendCommand(doorName + " has been open for over an hour")

  if(vTimeOfDay.state.toString == "NIGHT" || vTimeOfDay.state.toString == "BED") {
        triggeringItem.sendCommand(ON) // reschedule the timer
  }
end

Theory of Operation:
Create a Timer for each sensor named using Design Pattern: Associated Items and place them in Groups.

When any of the door sensors changes state the first Rule triggers. This Rule sets the Expire timer if the door is OPEN and cancels the timer if it is CLOSED. See Design Pattern: Expire Binding Based Timers. We construct the name of the Timer Item using Associated Items naming conventions.

Finally, we construct the message. We only alert the users of the door opening/closing at night time (see Design Pattern: Time Of Day). Alerting is centralized using Design Pattern: Separation of Behaviors.

The second rule gets triggered when any of the door Timers goes off (i.e. receives command OFF). We use Design Pattern: Human Readable Names in Messages to convert the Item name into something more human friendly and then send the alert. If it is night time we reschedule the alert to go off again. During the day we only get the one alert.

An approach like this will work with all your door Items with just these two Rules and you can add new doors just by adding them to the right Group.


(Nicholas) #5

Hey Vincent,

I just tried adding your code - the notifications for when the door status changes work 110% but with the timer for the door being open for 10 mins, it send a notification whether the door is open or not.

EG. Door opens and closes within 1 min, 9 mins later i get a notification saying the garage has been open for more than 10 mins even tho its closed!

Any ideas?


(Nicholas) #6

Hi Rich,

Thanks so much for this. Not going to lie looks a bit daunting at first but I’ll have a play around with it and let you know how I go! Thanks so much for sharing!


(Vincent Regaud) #7

Yes, I made a typo. postUpdate not PostUpdate

rule "Garage Door Sensor"
when
    Item MGarageDoorSensor1 changed
then
    if(SecuritySystem.state == ON) {
        sendBroadcastNotification("Garage Door " + triggeringItem.state.toString)
        if (triggeringItem.state == OPEN) GarageDoor_Timer.sendCommand(ON) // Start timer
        else GarageDoor_Timer.postUpdate(OFF) // Cancel the timer
    }
end

(Nicholas) #8

Works beautifully!! Amazing how something so small can make a difference!

Thanks so much for all your help!


(Vincent Regaud) #9

Coolio, please like and mark the solution post. Thanks