/wifi-presence

Presence detection on OpenWrt routers using connect/disconnect events of WiFi clients. Events are published to MQTT with Home Assistant integration.

Primary LanguageGoMIT LicenseMIT

wifi-presence CI Go Reference

Presence detection on OpenWrt routers using connect/disconnect events of WiFi clients. Events are published to MQTT with Home Assistant integration.

  • What: Standalone application that runs on OpenWrt access points. Publishes WiFi client connect and disconnect events to an MQTT broker.
  • Why: Presence detection for home automation systems. Integrates with Home Assistant using the MQTT integration.
  • How: wifi-presence connects to hostapd's control interface to receive client connect and disconnect events.

Requirements:

  • Supported system running hostapd (such as an OpenWrt AP)
  • MQTT broker

Contents:

wifi-presence diagram

Quickstart

  1. Install wifi-presence on an OpenWrt access point. See okpg or download.
  2. Update the /etc/config/wifi-presence configuration file. Update the mqttAddr to the desired MQTT broker's address.
  3. Publish to the wifi-presence/config topic a list of MAC addresses to track. See configuration.

If using Home Assistant with the same MQTT broker, it should automatically be updated with each configured WiFi client.

Motivation

A home automation system that reacts to presence and absence events provides a more automated experience.

There are many ways to determine presence, e.g. motion sensors, network traffic monitoring, GPS & geo-fencing, etc. A person's phone typically travels with them in and out of a household. Most phones automatically connect and disconnect from home WiFi networks. Therefore a WiFi connection to one or more access points (APs) can be used as a proxy for physical presence.

There are similar projects that periodically ping client devices. This method may be less reliable than using hostapd because phones may not respond to pings while in low power mode. There is also a delay introduced by the ping frequency.

Home Assistant

wifi-presence integrates with Home Assistant using the MQTT integration. This can be enabled/disabled via the -hass.autodiscovery flag (true by default).

Although supported, Home Assistant isn't required. The messages published to MQTT can be consumed by any subscriber(s).

Configuration

Configuration is done via command-line flags at startup, and via MQTT at runtime.

The MQTT configuration determines the WiFi devices/clients wifi-presence will monitor. For each configured device, wifi-presence will publish state information on connect and disconnect. See the note about iOS devices and MAC addresses.

JSON via MQTT

Configuration is a JSON published to the config topic (<mqtt.prefix>/config).

Example configuration:

{
  "devices": [
    {
      "name": "My Phone",
      "mac": "AA:BB:CC:DD:EE:FF"
    },
    {
      "name": "TV",
      "mac": "00:11:22:33:44:55"
    },
    {
      "name": "Other Phone",
      "mac": "FF:EE:EE:DD:CC:BB"
    }
  ]
}

Example using Mosquitto to the JSON configuration in wifi-presence.config.json:

$ mosquitto_pub \
        -h 'my-mqtt-broker' \
        -t 'wifi-presence/config' \
        -r \
        -f wifi-presence.config.json

OpenWrt

The OpenWrt project is

OpenWrt is a highly extensible GNU/Linux distribution for embedded devices (typically wireless routers).

See the openwrt branch for package and build scripts.

opkg

Installation via OpenWrt's opkg package manager:

# Add public key
wget https://wifi-presence.s3.us-east-2.amazonaws.com/public.key
opkg-key add public.key

# Add package source as a custom feed
echo "src/gz wifi-presence http://wifi-presence.s3-website.us-east-2.amazonaws.com" >> /etc/opkg/customfeeds.conf

# Fetch/update list of packages
opkg update

# Install/upgrade wifi-presence
opkg install wifi-presence

# Update configuration
vim /etc/config/wifi-presence

# Enable and start wifi-presence
/etc/init.d/wifi-presence enable

Configuration

The configuration file is: /etc/config/wifi-presence.

Download

OpenWrt packages of wifi-presence are available for download.

Flags

When running wifi-presence using OpenWrt, use the provided /etc/config/wifi-presence file to configure.

As a standalone program, the following command-line flags are used:

wifi-presence [options]

Options:
  -apName string
    	Access point name (default "my-router")
  -debounce duration
    	Time to wait until considering a station disconnected. Examples: 5s, 1m (default 10s)
  -hass.autodiscovery
    	Enable Home Assistant MQTT autodiscovery (default true)
  -hass.prefix string
    	Home Assistant MQTT topic prefix (default "homeassistant")
  -help
    	Print detailed help message
  -hostapd.socks string
    	Hostapd control interface socket(s). Separate multiple paths by ':'
  -mqtt.addr string
    	MQTT broker address, e.g "tcp://mqtt.broker:1883"
  -mqtt.id string
    	MQTT client ID (default "wifi-presence.my-router")
  -mqtt.password string
    	MQTT password (optional)
  -mqtt.prefix string
    	MQTT topic prefix (default "wifi-presence")
  -mqtt.username string
    	MQTT username (optional)
  -sockDir string
    	Directory for local socket(s) (default "/var/folders/99/0z1nqy2d54x12xj2md6xz67w0000gn/T/")
  -v	Verbose logging (alias)
  -verbose
    	Verbose logging
  -version
    	Print version and exit

MQTT

wifi-presence publishes and subscribes to an MQTT broker. The -mqtt.prefix flag can be used to change the topic prefix, along with -hass.prefix for Home Assistant's topic prefix.

The following topics are used:

  • <PREFIX>/<AP_NAME>/status The status of wifi-presence (online / offline).

  • <PREFIX>/config wifi-presence subscribes to this topic for configuration updates.

  • <HASS_PREFIX>/device_tracker/<AP_NAME>/<MAC>/config If -hass.autodiscovery is enabled, then all configured devices will be published to these topics (based on their MAC address). Home Assistant subscribes to these topics and registers/unregisters entities accordingly based on messages received.

  • <PREFIX>/station/<AP_NAME>/<MAC>/state The state of a device (home / not_home) is published to these topics.

  • <PREFIX>/station/<AP_NAME>/<MAC>/attrs A JSON object with device attributes (SSID, BSSID, etc) is published to these topics.

hostapd

wifi-presence requires hostapd running with control interface(s) enabled. This is the default for OpenWrt. The hostapd configuration option is ctrl_interface. More information: https://w1.fi/cgit/hostap/plain/hostapd/hostapd.conf

The wifi-presence -hostapd.socks option should correspond to the socket locations defined by 'ctrl_interface'. Multiple sockets can be monitored (one socket per radio is created by hostapd).

hostapd full version

OpenWrt includes a stripped down version of hostapd, which is the default. This stripped down version is compatible with wifi-presence, but prevents wifi-presence from getting a list of connected devices at startup. In this case, all devices will be considered "disconnected" until a (re)-connect is seen.

The full version of hostapd can be installed to improve wifi-presence. When using the full version, wifi-presence will query hostapd for a list of connected devices at startup/when receiving new configuration. Any connected stations will immediately be considered "connected", triggering a corresponding MQTT message for each.

The full version is included as part of various packages. For example, commands to install the full version using wpad:

opkg remove wpad-basic-wolfssl
opkg install wpad-wolfssl

iOS

iOS version 14 introduced "private Wi-Fi addresses" to improve privacy. When enabled, an iOS client will connect to APs using different MAC addresses. Consider disabling this feature for APs that you control and are running wifi-presence to help make presence detection configuration easier.

Alternatives: OpenWrt Luci Integration

The OpenWrt Luci integration similar presence detection functionality.

Some differences between wifi-presence and the luci integration:

  • The luci integration communicates with the OpenWrt router using the OpenWrt admin HTTP(S) interface, while wifi-presence uses MQTT. The MQTT HomeAssistant integration is then what bridges the two. There's not necessarily an advantage to either approach, although if you don't have MQTT already integrated, then wifi-presence may not make as much sense.

  • Presence Detection:

    • The luci integration uses polling, i.e. it periodically queries the OpenWrt interface for the list of connected clients, while wifi-presence is event-driven. It connects with OpenWrt's hostapd (the system responsible for WiFi) and receives connect/disconnect events in real-time.
    • The luci integration effectively scrapes the ARP and DHCP tables on the OpenWrt router to get a list of connected clients. While wifi-presence is integrated directly with hostapd and has direct access to the connected clients.