OpenWRT + MQTT Presence Detection

Hi everyone, just came to share the method i’m using to determine if i’m home.

I use an OpenWRT router, so I can determine what MAC addresses are connected. I like MQTT a lot, so messy SSH connections and scripts on the openhab machine weren’t going to cut it for me.

basically the openwrt router is sending to an mqtt topic by the name of “presence/wifi/MAC” the value ‘ON’ every 5 seconds if the device is connected and that is all it does, openhab gets this, and sets a timer for 7 seconds later turning the state back OFF again. if it receives another ON via MQTT it resets the timer, if not it assumes disconnect. This works very well for me, even if I haven’t touched my Android phone for hours it remains associated with the access point and openhab knows i’m here.

also this will work for wifi routers with multiple wireless interfaces like mine with 2.4ghz and 5ghz.

Install the mosquitto-client package with opkg, then save this shell script as /etc/config/mqtt_connected_wifi.sh and chmod +x

#!/bin/sh

# sends connected clients to mqtt server

while true
do
        for interface in `iw dev | grep Interface | cut -f 2 -s -d" "`
        do
          # for each interface, get mac addresses of connected stations/clients
          maclist=`iw dev $interface station dump | grep Station | cut -f 2 -s -d" "`
          # for each mac address in that list...
          for mac in $maclist
          do
                mosquitto_pub -h 10.1.0.254 -i horus -t "presence/wifi/${mac//:/-}" -m "ON"
          done
        done
sleep 5

in /etc/rc.local add

/etc/config/mqtt_connected_wifi.sh &

before

exit 0

then in your items,
something like this:

Switch LocationJupiter_PhoneWIFI "J Phone on WiFi	[%s]"  { mqtt="<[belic:presence/wifi/d0-22-be-b5-8c-07:state]" }

the rules file looks like this

import org.openhab.model.script.actions.Timer
var Timer jTimer = null

rule "jupiter wifi"
when
    Item LocationJupiter_PhoneWIFI received update
then
		if (LocationJupiter_PhoneWIFI.state == ON) {
		JupiterIsHome.setState(ON)
		if (jTimer != null) { 
			jTimer.cancel()
			jTimer = null
		}
		
        
        jTimer = createTimer(now.plusSeconds(7), [|
        	jTimer = null
        
            LocationJupiter_PhoneWIFI.setState(OFF)
            JupiterIsHome.setState(OFF)
        ])
        
        }
               
       
end

4 Likes

I made a few modifications, since the timer approach in your rule files didn’t work for me. There were always gaps in the presence because the timer wasn’t canceled properly or whatsoever.

I uploaded the new script on Github: https://github.com/dersimn/OpenWRT-Presence-Detector-over-MQTT

3 Likes

Hi I’m really interested in this setup for presence detection. I haven’t got an openwrt compatible router yet but it’s something I’m looking in to, for better security and to use in a presence detection setup.
How reliable is this setup ? Are there any missed detections or false presences.

Been stuck in the depths of my mental health since writing this. Thanks very much for taking it and making it much better. Also thanks for crediting me :slight_smile:

I’ll have to update my system one day. I have turned on that openwrt router and not touched it for around a year now.

Hi Simon,

I’ve followed your instructions on github and everything seems to be working, although I had to make my mosquitto server so that it didnt use SSL, as I couldn’t get it to receive posts from the openwrt router no matter what I tried, is this ok?

anyway I was wondering how you had your sitemaps configuration to show all the switches.

regards

Tim

Bit of a late reply to this but… by default openwrt packages won’t have SSL support in order to reduce the filesystem size. I can’t remember off the top of my head if you can install an alternative package or whether manually building openwrt from source is required. Hope this is helpful to anyone coming across this.