Generic Presence Detection

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!

Based on this conversation, I decided to change my script to that from SeaSide, because it loops through multiple IPs. Tested this arvo, and it works; also, and yes, because of clearing the arp entry for the relevant IP. Nice.
Also adopted the MQTT publish approach, as this is what I will be using (Architecturally) whenever possible.

From a rights perspective I had to use sudo in front of the arp entry deletion, and add openhab to the sudoers without password.

No network binding used for this.
So basically, the shell script is triggered by a rule.
The script publishes to mosquitto topic;
OH subscribes to mosquitto topic

1 Like

@Max_G
Glad it could help someone. I prefer to not invoke the polling to see if a device is available from within openhab, since
I run it every two minutes for several devices, IMO it’s better suited to be run outside openhab in a crond-job or similar.
You don’t have to give openhab permissions to all commands in the sudoers table you can add

username ALL=(ALL) NOPASSWD: /sbin/ip

to allow allow username to be able to execute ip (for flushing that is). I’m sure you are aware of this, but just writing it since it seems a lot of people allow openhab to execute just about anything.

Regards, S

2 Likes

Just because I’m curious: With the two iPhones in my house, as soon as I integrate the arp flush, the script doesn’t work reliable. Without this line, it’s pretty solid and only misses a beat from time to time.

When you guys say it works for you, do you also use iPhones or only Android?

@jaydee73
One iphone 6 and two android devices Oneplus 3 and Onplus one.
The oneplus 3 is also pretty good at sleeping, and turning wireless network off, so I need a timeout.
For iphone I have 19 mins and 11 mins for android.

I have basically followed @rlkoshak post about presence.

I have:

val String LOG_NAME = "PRESENCE"
var Timer mJPhoneIPTimer = null

rule "JPhoneIPChange" 
when
    Item JPhoneIPMqtt changed from ON to OFF
then
     val int sleepTimerJ = (JPhoneIPSleepTimer.state as DecimalType).intValue
     if (PresenceOverride.state != ON) {
        logInfo(LOG_NAME, "J Phone is not home after setting timer to delay: " +   sleepTimerJ)
        try {
            mJPhoneIPTimer = createTimer(now.plusMinutes(sleepTimerJ), [|
                                         logInfo(LOG_NAME, "J Phone is not home after " + sleepTimerJ + " mins")
                                          JPhoneIP.sendCommand(OFF)
                                          NotifyPresence.postUpdate("J is not home on IP Phone time: " + sleepTimerJ)
                                         mJPhoneIPTimer = null
                                         ])    
        } catch (Exception x) { 
            logInfo(LOG_NAME,"Could not set value for sleep timer")
        }
     }
end

items:

Number   JPhoneIPSleepTimer "Oneplus 3 Sleep Timer [%d min]"   <clock>                   (gRestore) 
Switch   JPhoneIPMqtt       "OnePlus 3 Network Mqtt [%s]"                  <network>                     { mqtt="<[mosquitto:presence_sensors/network/j:state:default]" }
Switch   JPhoneIP           "OnePlus 3 Network [%s]"            <network>   (gJPresent, gPresent,gRestore) 
S

Sitemap:

 Setpoint item=JPhoneIPSleepTimer minValue=1 maxValue=60 step=1

I think the example in the wiki doesn’t take advantage of the powerful groups. I use:

Group:Switch:OR(ON, OFF)	group_presence						"Gruppe zur Anwesenheitserkennung"
Group:Switch:OR(ON, OFF)	group_movement						"Gruppe der Bewegungsmelder"				(group_presence)
rule "Zyklische Anwesenheitserkennung"
when
    Time cron "0 */5 * * * ?"
then
    if (presence.state == ON) {
        if (group_presence.state == OFF) {
	    if (!group_presence.changedSince(now.minusMinutes(5)) sendCommand(presence, OFF)
        }
    }
    else {
        if (group_presence.state == ON) sendCommand(presence, ON)
        else if (presence.state == NULL) sendCommand(presence, OFF)
    }
end

rule "Eventbasierte Anwesenheitserkennung"
when
	Item group_presence changed from OFF to ON
then
    if (presence.state != ON) sendCommand(presence, ON)
end

which is really easy to understand…