Generic Presence Detection

Tags: #<Tag:0x00007f617019ebb8>

Edit: Complete rewrite of the tutorial
Edit: For the Python version I now point to the Debounce DP which uses the debounce library and allows for the implementation of this DP without nay code.

This is a tutorial to show a generic and sensor independent way to do presence detection with multiple sensors and implementing anti-flapping (i.e. all sensors must be OFF for a certain amount of time before the home goes to away).

Requirements

  • One or more Switches determines whether someone is present.
  • If one or more of these Switches is ON then someone is presumed to be present (more complex algorithms are possible but implementing them is an exercise left to the student)
  • All Switches must be off for a certain amount of time (5 minutes in this case) before turning off presence. If one returns before that amount of time then presence never turns OFF.

The Code

Items

Switch Presence "Someone is Present" <present> // master presence switch, represents to the rest of OH where someone is home
Group:Switch:AND(OFF,ON) Presence_Sensors <present> // all presence sensors belong to this group
Switch Presence_Timer { expire="5m,command=OFF" } // anti-flapping timer

// Optionally one can create additional groups to aggregate all the sensors for
// each person if that matters to you, but the sensors need to all be members of
// Presence_Sensors as well

Switch Sensor1Person1 (Presence_Sensors)
Switch Sensor2Person1 (Presence_Sensors)
...
Switch Sensor1Person2 (Presence_Sensors)
...

Python

See Design Pattern: Debounce which uses presence detection as an example and uses the debounce Python library to implement this such that the user need only add metadata to the Sensor Group Items.

Rules DSL

rule "Reset Presence and sensors to OFF on startup"
when
    System started
then
    Presence.sendCommand(OFF)
    Presence_Sensors.sendCommand(OFF)
end

rule "A presence sensor updated"
when
        Item Presence_Sensors changed
then

    if(Presence_Timer.state == ON && Presence_Sensors.state == Presence.state) {
        logInfo(logName, "Timer is running but group and proxy are the same, cancelling timer")
        Presence_Timer.postUpdate(OFF)
    }
    else if(Presence_Sensors.state == Presence.state) {
        logInfo(logName, "No timer and both group and proxy are the same, nothing to do")
        return;
    }

    if(Presence_Sensors.state == OFF) {
        logInfo(logName, "Everyone is away, setting anti-flapping timer")
        Presence_Timer.sendCommand(ON)
    }
    else if(Presence_Sensors.state == ON) {
        logInfo(logName, "Someone came home, setting presence to ON")
        Presence.sendCommand(ON)
    }

end

rule "Presence timer expired, no one is home"
when
    Item Presence_Timer received command OFF
then
    logInfo(logName, "Everyone is still away, setting presence to OFF")
    Presence.sendCommand(OFF)
end

Theory of Operation

There are three Items that work together to make this work.

  • Presence_Sensors: A Group of Switches configured so if all the Switches are OFF the Group’s state is OFF and if one or more is ON the Group’s state is ON.

  • Presence_Timer: A Switch that will receive a command OFF 5 minutes after changing to ON. If it gets updated to OFF, nothing happens, effectively cancelling the timer.

  • Presence: A proxy Switch that gets set to ON immediately when Presence_Sensors changes to ON and set to OFF only if Presence_Sensors remains OFF for 5 minutes or longer.

These three Items drive two Rules. The first Rule triggers on any change to Presence_Sensors.

First we check to see if there is a Timer running (i.e. Presence_Timer.state == ON) and whether Presence_Sensors and Presence have the same state. If they are the same (i.e. both OFF or both ON) then there is no longer a need for the Timer so we can cancel it. And since they are already the same state there is nothing else to do.

If there is no Timer and both are the same state then there is nothing at all to do so just return.

If we get to this point in the Rule we know that there is no Timer and that Presence_Sensors and Presence have are different states.

If Presence_Sensors is OFF then we know that Presence is not OFF so we need to create a Timer to turn it OFF in 5 minutes.

If Presence_Sensors is ON then we know we need to send a command ON to Presence immediately.

If there is a Timer but Presence_Sensors and Presence are different, do nothing and let the Timer take care of bringing them to the same state.

40 Likes
Fine tuning of wifi presence detection
Automatic light dimming
Design Pattern: Debounce
Dockerized OH iPhone Detection with HPING3 and sensorReporter
No working trigger functions openHAB 2.1
Disarm z-wave motion sensor
Another presence method - Android specific
reelyActive Smart Spaces Revisited
Presence tutorial - my implementation
Presence (OPEN)
iPhone Presence Detection with hping3 and ARP
KNX Integration & Alexa
Is OpenHab Dying?
Setting a master variable / switch
[Help Needed] Hue online / offline rule
Item persistence after reboot
Can someone set me straight on network bindings?
[SOLVED] Too dumb to work with files :-( ? stuck at getting started with files
[SOLVED] Prevent openhab from triggering rule multiple times
Arriving home - detecting phones which are arriving to Home
Configuration with Alexa Echo Dot
[SOLVED] Best approach delay a flickering contact, proxy and/or timer or?
[SOLVED] Best approach delay a flickering contact, proxy and/or timer or?
OH 2.x Timer Things
Rules with a wait for changing state back
De-Bouncer in Rules? Stop repeat notifications?
Presence rule with reed switch state & time
[SOLVED] Can't update item
Delay Alarm
iCloud binding with multiple phone rules optimization help!
Thermostat bathroom - on/off based on sensor value
[SOLVED] Presence with Android after using Iphone
Need help with presence
Please test the new Expire Binding
[SOLVED] Timer off delay for PowerView blinds
Weird crap! with my HVAC and Openhab
Turning off devices based on Presence
Turning off devices based on Presence
Fighting with rules
How to check time between 2 events
My openHab Setup
Presence (OPEN)
Light switches
Limit how often a rule can be run
Timers for on/off delay
Easy Away Switch / Ruleengine
Extend bluetooth range
Automatic Light Shut-Off Rules
Taming a flapping sensor
If item has not been updated for x time then do something
Central Heating system control - rules the only option?
Presence Detection Rule
Owntracks: Openhab2:Unable to calculate relative location
Activate (arm) timers via mqtt to Tasmota flashed Sonoff Basic R2
In a rule wait for a item change its status
Presence (Occupancy) Detection: Different Approach Using Smart Door Locks
Homematic Thermostat rule
Dishwasher rule
Creating of a delay in rules
Execute function in a time slot
Rule Example Wasp in Box
Presence Detection - Close to Home
Example of simple anti-flaping mechanism for Presence
Complex Rule optimization
[jsr223] New Python Community Library Candicates to test
Journey to JSR223 Python 7 of 9
Presence Detection Seems Too Hard
[SOLVED] How to use timer state as trigger in rule
[SOLVED] How do I debounce or antiflap notifications for many devices in a group?

Off-topic: Is this binding working with OH 1.8? or is there an update for OH1.8 to OH1.9?
The most confusing bit about this forum is the mixing of OH1 and OH2.

You are right. The problem is, that OH2 is getting more and more popular and most postings nowadays are for OH2 but that’s not always stated. It is planned to rework the forum structure to be 2.0 by default in a few weeks to months. I hope the problem will not get worse in that time.

1 Like

tl;dr: It is a 1.9 binding which means it works in OH 1.8 and OH 2.0. The above code is running in OH 2.0 but should work in 1.8 unchanged.

I agree, it is confusing. We are in a state of transition right now but OH 2 is rapidly maturing to the point where it will soon become the default assumed version talked about.

In this particular case, there will never be an update of the core of OH 1.8 to version 1.9. However, most of the bindings and add-ons have continued development. These bindings and add-ons are referred to as version 1.9. You can (and probably should in some cases) run 1.9 version bindings in OH 1.8.3.

In OH 2 there is a new architecture and a new way for bindings and add-ons to work. There is also a compatibility layer which allows one to run older 1.x style bindings inside OH 2. As it stands right now as of this writing, there are more 1.9 bindings that are part of the official distribution than 2.0 bindings, including some really essential bindings like MQTT and HTTP. Though that is going to change soon.

In the Migration Tutorial I actually used an approach that lets one first swap out the core to OH 2 but remain on 1.9 version bindings. And then gradually transition to the 2.0 version of the bindings.

So in short, if it says version 1.9 it will work in 1.8.3 and 2.0.

So here are a few rules of thumb I would use to determine if something posted is applicable to OH 1.8.3 if the:

  • binding/add-on is documented on the wiki as opposed to http://docs.openhab.org
  • version of the binding or add-on starts with a 1, e.g. 1.9
  • example rule imports things from org.openhab it was written for 1.x

It only applies to OH 2.0 if it:

  • talks about PaperUI
  • references Things and/or Channels
  • references BasicUI or ClassicUI
  • references Karaf or the Karaf Console

I hope this helps.

2 Likes

Thank you very much for this clarification… I do appreciate it, and it makes the whole thing much clearer.

Looks interesting! How about also removing the Present_Timer item and adding the expire to the main Present switch?

The problem with that is most of my sensors only report when there is a change. Furthermore the group’s state doesn’t change very frequently. Therefore there isn’t an event to keep rescheduling the timer. You could add a rule that triggers every few minutes to refresh the timer by sending an ON if the sensors are still on, but if you do that you may as well implement the timer in that rule.

In the end, you could use Present as the timer so long as ON keeps getting sent to it while you are present every <n minutes where n is the timer length. That isn’t the case with the code above.

1 Like

Hi rick,
Thanks for that great tutorial.
I was wondering what kind of presence sensors you are using.

I have been struggling to the iPhone as presence detector and using the network binding. But this did not work reliably.

Remember to use the search function first :wink:

Hi Tom,
Thanks for the hint. I am on Windows.

I use a combo of sensors none of which am I particularly happy about their performance for detecting iPhones.

I use the Network binding to ping devices (work like a champ for Android).

I’ve recently implemented the hping3 sensor @ThomDietrich linked to which I’m finding works no better than Network. I’m not sure if I need to adjust the timing or something else but so far I’ve never seen the hping3 detect the device present when Network did not and visa versa. Of course, the hping3 may be making Network work better.

I’ve a Pi 3 running reelyActive. So far it it detects BTLE devices like a champ (my fitbit, wife’s Dexcom and Pebble watch) but it detects the iPhone and my Android very poorly. But this may be caused more because I can’t figure out which device is which so I might not have identified the IDs of the devices I care about. I do notice that every time someone walks by the house reelyActive picks them up. I’m going to watch it some more but this might be a secondary way to detect when someone comes to the door (package delivery). What would be great is if I could find some sort of way to map the BT address of a device, which I can discover on my own, with the reelyActive deviceID.

I’ve also three Pis and my “server” (old laptop) each outfitted with BT and I run a custom script which does something similar to reelyActive, only at a more primitive level, to detect the phones. This works reasonably well though because it uses a sort of moving average to determine presence it isn’t super responsive. Sometimes it also gets stuck reporting a device as ON when it is no longer present,

I’ve not spent a lot of time trying to figure out the problems I have with each of these. I’ve recently had something major go wrong in my office which has really messed up my electronics in strange and inexplicable ways. My monitor died (probably a failed capacitor), the BT on my laptop server can no longer be found, I can no longer access port 443 on the laptop server despite there being no IP tables rules block that port and netstat clearly showing that nginx is listening on that port for all addresses. All my network gear had to be reset (thank goodness for dd-wrt’s backup feature) and I had to remount all of my drives. I don’t know if it was a power surge or an EMP but needless to say, I currently have some bigger problems to figure out right now so I’ve all but disabled my presence detection.

Anyway, as for being on Windows, hping is available on Windows. It will probably require some powershell scripting to make it work but it is not impossible.

4 Likes

@Rick. Thanks and wonderful as always.

1 Like

I hope you can recover fully from it all… sounds weird. Good luck.

@rlkoshak Thanks for the mega tutorial, however i have a question, my phones (android, two different makes) keep being marked as “not connected” by the network binding, despite still being on wifi (and visible on my router as connected), they do then come back but they drop in and out all the time. Does my Thing file look like a valid use case or do i need to tweak something.

Thing network:device:JamesPhone [ hostname=“192.168.1.19”, port=“0”, retry=“1”, timeout=“5000”, refresh_interval=“60000”, use_system_ping=“false”, dhcplisten=“true” ]

Or is this just normal?

I had the same problem with Android phones running Android 6 and above. I think they stop responding to pings when in doze mode.

I use the arp-scan tool combined with the exec binding for detecting phones. For a Nexus 6p, Nexus 5x and Galaxy S5 this works perfectly and always detects the phones (I had to up the number of retries to get the Galaxy S5 to respond reliably)

I think this is normal. Hence the anti-flapping logic and the use of alternative sensors in my setup.

Yes it’s normal (from a technical stand point) but there are of course ways around that. @MikeJMajor refered to the following solution I suppose. It’s reported to be quite reliable between many devices, including Androids and iPhones in doze/deepsleep mode:

Not convinced! … or beg to differ…

I run this set-up and it does not switch to ‘not present’, due to ARP retaining the IP.
… even (two) days later…

I’ve not done enough experiments to prove it, but I think hoping combined with Network binding might be a viable approach. I noticed when I was playing with it that periodically hpinging the iPhone made the Network Item linked to its ip work more reliably.

Also, if I remember correctly doesn’t the script first clear the arp table before doing the hping?

Very inspiring. Will try to imitate.
Thanks!