I've written before about using an ESP32 to do Better Presence Detection with Home Assistant and ESPresense. ESPresense works by using ESP32s positioned in different rooms to track the relative movement of a person by monitoring the signal strength of a BLE device that they carry (such as a smartphone).
I've been using ESPresense for seven months now, and it has been a very reliable way to know which room someone is likely to be in based on where their smartphone is in the house.
Someone who read my original blog post on ESPresense got in touch recently to ask if it's possible to easily enumerate which devices are in a room. Naturally, I was curious to know if this was possible and to see what I could find out.
Recap: ESPresense Basics
The basic premise of ESPresense is that you will need to place a device running ESPresense in each room that you want to perform presence detection. This way, a device you are tracking (e.g. a smartphone) can be associated with being in the room with the ESPresense device with the strongest signal, inferring the stronger the signal, the closer you are to the ESPresense device.
ESPresense transmits two different sets of topics:
espresense/devices/*
Any device picked up by ESPresense will be tracked under a Device ID and provided its own topic where information is pushed about the RSSI signal strength of ESPresense devices that can see the BLE beacon being trackedespresense/rooms/*
Each ESPresense device will publish a room topic that will publish basic information about the ESPresense device
In Home Assistant, we're able to configure in our sensor.yaml
the devices that we want to track within Home Assistant, for example:
- platform: mqtt_room
name: "James iPad BLE"
device_id: "roomAssistant:xxxx-xxxx-xxxx"
state_topic: "espresense/devices/roomAssistant:xxxx-xxxx-xxxx"
timeout: 5
away_timeout: 120
- platform: mqtt_room
name: "James iPhone BLE"
device_id: "roomAssistant:xxxx-xxxx-xxxx"
state_topic: "espresense/devices/roomAssistant:xxxx-xxxx-xxxx"
timeout: 5
away_timeout: 120
Home Assistant will then track my iPhone and iPad. Using the information published about each device, Home Assistant will determine which room I am in and save that against the state of "James iPad BLE" and "James iPhone BLE", respectively.
The result is that there isn't an easy way that I've come across to list or monitor all devices in a given room.
In my original ESPresense blog post, I talked about writing automations to turn off lights if no one was home, for example:
alias: Office Off - Unoccupied
description: "Turn the lights off if James isn't in the office for more than 10 minutes"
mode: single
trigger:
- platform: state
entity_id:
- sensor.james_iphone_ble
from: office
for: 00:10:00
action:
- service: light.turn_off
data: {}
target:
entity_id:
- light.office_lights
- service: switch.turn_off
data: {}
target:
entity_id: switch.office_lights
The key bit in the above snippet is the trigger section. However, if you want to track quite a few devices, this could be quite painful to manage as you'd have to update every automation with each device you want to track.
What if you could easily track the number of devices in each room instead of having to check that each device being tracked isn't in the room?
Counting Room Occupancy
Counting the number of devices in a room could be a simpler way to determine if a room is occupied or not, rather than having to check the state of each device in a trigger
condition of every automation that you want to be based on room occupancy.
The best way that I've found to do this is via a template sensor which I've added to my sensor.yaml
:
- platform: template
sensors:
office_occupancy:
friendly_name: Office Occupancy
value_template: >
{% set ns = namespace(occupancy=0) %}
{%- for sensor in states.sensor %}
{%- if 'distance' in sensor.attributes and sensor.state == 'office' %}
{%- set ns.occupancy = ns.occupancy + 1 %}
{%- endif %}
{%- endfor %}
{{ ns.occupancy }}
You would need to create an occupancy sensor for each room where you wanted to monitor the occupancy count. I've created an occupancy sensor for my office in the above example.
This works by enumerating all sensors with a distance
attribute and incrementing a count if they are in the given room. In an ideal world, the template would check that the platform
for the sensor is set to mqtt_room
, however it doesn't look like it is possible to interrogate the platform
value of the sensor. Whilst this possibly isn't the most watertight way of doing this, my testing has shown that the only devices I have that have a distance attribute are mqtt_room
sensors that I have setup. If I wanted I could aim to make the more robust, and in the absense of being able to check that the platform
is set to mqtt_room
I could check that the sensor name/ID includes BLE
as I've used a consistent naming convention when setting up the various mqtt_room
sensors.
The state
value of my occupancy sensor is simply the number of BLE devices being tracked that have a state of "office". At the moment, I'm sat in my home office writing this blog post, and both my iPhone and iPad are on the desk, as a result the occupancy count for the room shows as 2.

This means that I have a more generic way of determining if a room is occupied moving forwards. Rather than needing to list individual devices in trigger conditions of automations I can simply check an occupancy sensor to see if the count is 0
or >0
.
This feels to me like a simple way of determining an occupancy coutn for a room, but if anyone knows of a better way to do this, please let me know!