Presence detection by reading leases on DHCP server; it works!

The following is now in production at my home, called from crontab every minute - enjoy !

Also available on Github

#!/bin/bash
#
# McPresence.sh - cheap & easy presence detection
#
# Reads known persons' personal mobile device's MAC address
# against the localhost's DHCP leases
# to check each person's presence.
#
# Then sends each person's presence to an Openhab instance
#
# The dhcp-lease-list command is part of the ISC DHCP server's package 
# For other DHCP servers, maybe use libtext-dhcpleases-perl instead
#
# The personal_mobile_devices file takes two columns: MAC address and person
# MAC address must be lowercase - matching is case sensitive. Example:
# 7c:2f:80:0d:3b:a6 Alice
# 55:55:55:55:55:55 Bob
#
# The people's presence in Openhab is modeled as switches
# which are Openhab items recorded in /etc/openhab2/items
# and whose state attribute can be ON or OFF
# For example, here is the content of a /etc/openhab2/items/people.items
# Switch Alice
# Switch Bob
#
# This script is meant to be called from crontab - every minute is adequate.
#
# Absence detection requires DHCP lease expiration - by default ten minutes in ISC DHCP
# Openhab parameters
OH_IP=10.9.0.3
OH_port=80
OH_user=leases
OH_pass=password

# The script's directory - where personal_mobile_devices
# must also be found
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

leases=($(dhcp-lease-list --parsable | awk -F" "  '{print($2)}'))

IFS=$'\n'
for personal_mobile_device in `cat $DIR/personal_mobile_devices`
do
	MAC=`echo $personal_mobile_device | awk '{print($1)}'`
	person=`echo $personal_mobile_device | awk '{print($2)}'`
	if [[ " ${leases[@]} " =~ " ${MAC} " ]]; then
		# Present
		curl -X POST -d "ON" -H "Content-Type: text/plain" \
		http://$OH_user:$OH_pass@$OH_IP:$OH_port/rest/items/$person
	else
		# Absent
		curl -X POST -d "OFF" -H "Content-Type: text/plain" \
		http://$OH_user:$OH_pass@$OH_IP:$OH_port/rest/items/$person
	fi
done
2 Likes

I have this rule running with network-health binding:

rule "Periodically check presence"
when
    Time cron "0 */5 * * * ?"
then
        if (Presence.state == ON)
        {
                if(gMobiles.members.filter(s | s.state == ON).size == 0) {
                        logInfo("PresenceCheck", "No phone within reach, checking for flapping")
                        if(gMobiles.members.filter(s | s.changedSince(now.minusMinutes(5))).size == 0) {
                                logInfo("PresenceCheck", "Nobody is at home")
                                sendCommand(Presence, OFF)
                        }
                }
        }
        else
        {
                //For initialisation. If Presence is undefined or off, although it should be on.
                if(gMobiles.members.filter(s | s.state == ON).size > 0) {
                        sendCommand(Presence, ON)
                }
                else if (Presence.state == NULL || Presence.state == null) {
                        sendCommand(Presence, OFF)
                }
        }

end

Is your script different to mine? I can´t understand your script, i´m no programmer…

Does this work, when you have a router which makes the dhcp-stuff or is it only working, if dhcp is controlled from the server which is running openhab?


Another question:
Is there a way to check in realtime, if a mac-adress is regsitrating in the network?

My amazon dash button often stops working… So it would be a better way (and much faster) if i check for online-status.

Any idea how to do that?

The main difference is that your script runs on the Openhab server host whereas mine runs on the DHCP server host (which, in my case, is another host) and passes the presence to Openhab through Openhab’s REST interface.

No one is born a programmer… And then you begin tinkering with stuff…

Begin by reading the comments lines (the one that begin with “#”) - I meant them to document what the script does.

Receiving MAC address registrations is the whole point of a DHCP server and the dhcpd.leases file is where the ISC DHCP server (the one I’m using) keeps his records of that.

Is this a yes or a no? :wink: Is this doable with your setup? Real-time monitoring of the dhcp-process?

I have not running an extra linux dhcp-server, i have a router which does that for me (fritzbox).

My setup is not realtime: it only updates every minute, detects presence immediately but does not detect absence until the lease expires (ten minutes in my case - but I could make it shorter).

You can only have one DHCP server on each network segment. In your case, a DHCP server is hosted on the Fritzbox. You could rig something like my script and run it on the Fritzbox - it is a Linux server after all, but is will be a slightly different script as you’ll probably find a different DHCP server whose leases file you’ll have to parse.

I wrote that script because I understand the DHCP environment well and found it the easiest way to achieve my goal of cheap & easy presence detection, but I now have doubts that it is the best approach: it adds a dependency on the DHCP server - which means a more complicated system with an additional point of failure. Approaches based on probing MAC address presence using arping directly from the Openhab host may be simpler (provided of course that the Openhab host is on the same network segment as the Wi-Fi mobiles - but that is the typical setup for most people, though it is not mine: my Openhab host is on a different VLAN)

If your model is supported the Fritzbox TR064 Binding might be an option. I am using it to detect smartphone presence in the house and it works really reliable. It also updates every minute by default (but configurable). Absence is detected mostly within 6 to 7 minutes after a phone left the house.

I already use network health binding for presence detection and it works very good.

But i want to use it for amazon dash buttons, too. But there i need real time detection. Openhab amazondashbutton-binding is not working very stable. My dasbutton always gets uninitialized after some time.

Hi folks,

I’ve been following this thread very closely cause I was interested. Thinking about other approaches, I think that using arp (or arping) can be a good approach (assuming that the devices share the same subnet). It would be something like this:

  • sending a broadcast using arping
  • checking in arp table if a MAC address is present
  • If the answer is yes, that device is on-line
  • Otherwise, that device is off-line

I will try some python code to see if it’s doable. Thank you.

1 Like

I also use the network health binding. But I found it to be unreliable especially for mobile devices. The Fritzbox TR064 Binding detects the presence nearly immediately. That is why I use the Fritzbox TR064 Binding for mobile devices while I use the network health binding for my servers which listen to pings.

I use a similar approach, but with my router as dhcp-server. I have an Asus router which I can connect to via telnet using an expect script to get which devices are connected. Works more reliably than the network binding, but sometimes takes a while before a device is marked as not connected.

If you have not looked at the Network Binding in 2.2 and onwards, in combination with arping - please consider re-visiting it.

It is working absolutely perfectly for me, with no reliance on any external scripts or other hardware.

Take a look at this thread:

since OH2.2 you can’t only use a general system ping to see if your server is responding, you can configure the network binding things to look for several ports, so you can even see which service on the server is online (for example web server, samba etc). That’s pretty great!

Since 2.2 the network binding does not work at all anymore on my windows machine. That is why I changed back to the old 1.x network health binding.
I wonder if there is any windows user at all that is ising the recent versions of the network binding successfully?

hm that’s weird, my girlfriend does use a windows machine at home and i could not experience any problems with the detection of that machine…

It is strange, indeed. For me it always displayed devices as online which definetely were not online. So it was not usable anymore.
The other problem is that there seems to be no arping implementation for windows which reduces the benefit of the new features of that binding.

okay, i looked into the log, to see if i’m right on that machine and it looks a bit strange, becacuse the state toggles very often, but in general the OFF/ON detection works with maybe some debouncing…

Line 116997: 2018-01-14 11:36:38.977 [vent.ItemStateChangedEvent] - sw_pc_buero changed from OFF to ON
Line 117019: 2018-01-14 11:37:21.836 [vent.ItemStateChangedEvent] - sw_pc_buero changed from ON to OFF
Line 117020: 2018-01-14 11:37:39.049 [vent.ItemStateChangedEvent] - sw_pc_buero changed from OFF to ON
Line 117034: 2018-01-14 11:38:26.937 [vent.ItemStateChangedEvent] - sw_pc_buero changed from ON to OFF
Line 117036: 2018-01-14 11:38:39.160 [vent.ItemStateChangedEvent] - sw_pc_buero changed from OFF to ON
Line 117055: 2018-01-14 11:39:32.038 [vent.ItemStateChangedEvent] - sw_pc_buero changed from ON to OFF
Line 117056: 2018-01-14 11:39:39.225 [vent.ItemStateChangedEvent] - sw_pc_buero changed from OFF to ON
Line 117069: 2018-01-14 11:40:37.138 [vent.ItemStateChangedEvent] - sw_pc_buero changed from ON to OFF
Line 117070: 2018-01-14 11:40:39.297 [vent.ItemStateChangedEvent] - sw_pc_buero changed from OFF to ON
Line 117086: 2018-01-14 11:41:42.239 [vent.ItemStateChangedEvent] - sw_pc_buero changed from ON to OFF

I would be curious to see what happens if you switch off the device linked to sw_pc_buero. Maybe it continues toggling…?

No it doesn’t, if the pc is “really” off, it remains in the off state:

Line 46711: 2018-01-11 20:19:27.293 [vent.ItemStateChangedEvent] - sw_pc_buero changed from ON to OFF
Line 68347: 2018-01-12 16:53:45.547 [vent.ItemStateChangedEvent] - sw_pc_buero changed from OFF to ON

@liotier I’ve fixed your posting to make reading it easier. Nice idea.