Need help with presence?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

234 Stars 26 Forks 147 Commits 5 Opened issues


Distributed poll-based BTLE presence detection reported via mqtt

Services available


Need anything else?

Contributors list

# 63,390
139 commits
# 704,894
3 commits
# 614,185
1 commit
# 250,018
1 commit


Note: as of

0.5.1, triggered scans, guest scanning, and beacon scanning are removed from
for simplification. Please consider using monitor instead for beacon scanning and detection and for generic device detection. It is unlikely that
will receive substantive updates after version 0.5.1.

TL;DR: Bluetooth-based presence detection useful for mqtt-based home automation. More granular, responsive, and reliable than device-reported GPS. Cheaper, more reliable, more configurable, and less mqtt-spammy than Happy Bubbles. Does not require any app to be running or installed. Does not require device pairing. Designed to run as service on a Raspberry Pi Zero W.

Note that the more frequently you scan for devices, the more 2.4GHz bandwidth you will use. This script may cause interference with Wi-Fi or other bluetooth devices for particularly short delays between scans.


A JSON-formatted MQTT message is reported to a broker whenever a specified bluetooth device responds to a name query. If the device responds, the JSON message includes the name of the device and a confidence of 100.

After a delay, another name query is sent and, if the device does not respond, a verification-of-absence loop begins that queries for the device (on a shorter interval) a set number of times. Each time, the device does not respond, the confidence is reduced, eventually to 0.

A configuration file defines 'owner devices' that contains the mac addresses of the devices you'd like to regularly ping to determine presence.

Topics are formatted like this:


Messages are JSON formatted and contain name and confidence fields, including a javascript-formatted timestamp and a duration of a particular scan (in ms):

 { confidence : 100, name : Andrew’s iPhone, scan_duration_ms: 500, timestamp : Sat Apr 21 2018 11:52:04 GMT-0600 (MDT)}
 { confidence : 0, name : Andrew’s iPhone or Unknown, scan_duration_ms: 5000, timestamp : Sat Apr 21 2018 11:52:04 GMT-0600 (MDT)}

Example Use with Home Assistant

The presence script can be used as an input to a number of mqtt sensors in Home Assistant.. Output from these sensors can be averaged to give a highly-accurate numerical occupancy confidence.

In order to detect presence in a home that has three floors and a garage, we might include one Raspberry Pi per floor. For average houses, a single well-placed sensor can probably work, but for more reliability at the edges of the house, more sensors are better.

- platform: mqtt
  state_topic: 'location/first floor/00:00:00:00:00:00'
  value_template: '{{ value_json.confidence }}'
  unit_of_measurement: '%'
  name: 'Andrew First Floor'

  • platform: mqtt state_topic: 'location/second floor/00:00:00:00:00:00' value_template: '{{ value_json.confidence }}' unit_of_measurement: '%' name: 'Andrew Second Floor'

  • platform: mqtt state_topic: 'location/third floor/00:00:00:00:00:00' value_template: '{{ value_json.confidence }}' unit_of_measurement: '%' name: 'Andrew Third Floor'

  • platform: mqtt state_topic: 'location/garage/00:00:00:00:00:00' value_template: '{{ value_json.confidence }}' unit_of_measurement: '%' name: 'Andrew Garage'

These sensors can be combined/averaged using a min_max:

- platform: min_max
name: "Andrew Home Occupancy Confidence"
type: mean
round_digits: 0
  - sensor.andrew_garage
  - sensor.andrew_third_floor
  - sensor.andrew_second_floor
  - sensor.andrew_first_floor

So, as a result of this combination, we use the entity sensor.andrewhomeoccupancy_confidence in automations to control the state of an input_boolean that represents a very high confidence of a user being home or not.

As an example:

- alias: Andrew Occupancy 
  hide_entity: true
    - platform: numeric_state
      entity_id: sensor.andrew_home_occupancy_confidence
      above: 10
    - service: homeassistant.turn_on
        entity_id: input_boolean.andrew_occupancy

Installation Instructions (Raspbian Jessie Lite Stretch):

Setup of SD Card

  1. Download latest version of jessie lite stretch here

  2. Download etcher from

  3. Image jessie lite stretch to SD card. Instructions here.

  4. Mount boot partition of imaged SD card (unplug it and plug it back in)

  5. [ENABLE SSH] Create blank file, without any extension, in the root directory called ssh

  6. [SETUP WIFI] Create wpa_supplicant.conf file in root directory and add Wi-Fi details for home Wi-Fi:

    ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev

network={ ssid="Your Network Name" psk="Your Network Password" key_mgmt=WPA-PSK }

  1. [FIRST STARTUP] Insert SD card and power on Raspberry Pi Zero W. On first boot, the newly-created wpa_supplicant.conf file and ssh will be moved to appropriate directories. Find the IP address of the Pi via your router. One method is scanning for open ssh ports (port 22) on your local network:
    nmap -p 22

Configuration and Setup of Raspberry Pi Zero W

  1. SSH into the Raspberry Pi (password: raspberry):

    ssh [email protected]
  2. Change the default password:

    sudo passwd pi
  3. [PREPARATION] Update and upgrade:

sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get dist-upgrade -y
sudo rpi-update
sudo reboot
  1. [BLUETOOTH] Install Bluetooth Firmware: ``` #install bluetooth drivers for Pi Zero W sudo apt-get install pi-bluetooth

verify that bluetooth is working

sudo service bluetooth start sudo service bluetooth status ```

  1. [OPTIONAL: BLUEZ UPGRADE] Compile/install latest bluez

This is not strictly required anymore, as pi-bluetooth appears to have been updated to support bluez 0.5.43.

#purge old bluez
sudo apt-get --purge remove bluez

#get latest version number from: #current version as of this writing is 5.49 cd ~; wget tar xvf bluez-5.49.tar.xz

#update errythang again sudo apt-get update

#install necessary packages sudo apt-get install libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev

#move into new unpacked directory cd bluez-5.49

#set exports export LDFLAGS=-lrt

#configure ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-library -disable-systemd

#make & install make sudo make install

#cleanup cd ~ rm -r bluez-5.49/ rm bluez-5.49.tar.xz

#update again sudo apt-get update sudo apt-get upgrade

#verify bluez version bluetoothd -v

  1. [REBOOT]

    sudo reboot

get repo key


add repo

sudo apt-key add mosquitto-repo.gpg.key

download appropriate lists file

cd /etc/apt/sources.list.d/ sudo wget

update caches and install

apt-cache search mosquitto sudo apt-get update sudo aptitude install libmosquitto-dev mosquitto mosquitto-clients ```

  1. [INSTALL PRESENCE] ``` #install git cd ~ sudo apt-get install git

clone this repo

git clone git://

enter presence directory

cd presence/ ```

  1. [CONFIGURE PRESENCE] create file named mqtt_preferences and include content:
    nano mqtt_preferences


mqtt_port="optional broker network port number. Defaults to 1883"
mqtt_user="your broker username"
mqtt_password="your broker password"
mqtt_room="your pi's location"
  1. [CONFIGURE PRESENCE] create file named owner_devices and include mac addresses of devices on separate lines.
nano owner_devices


00:00:00:00:00 #comments 
  1. [CONFIGURE SERVICE] Create file at /etc/systemd/system/presence.service and include content:
sudo nano /etc/systemd/system/presence.service


Description=Presence service

[Service] User=root ExecStart=/bin/bash /home/pi/presence/ & WorkingDirectory=/home/pi/presence Restart=always RestartSec=10


  1. [CONFIGURE SERVICE] Enable service by:
    sudo systemctl enable presence.service
    sudo systemctl start presence.service

That's it. Your broker should be receiving messages and the presence service will restart each time the Raspberry Pi boots.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.