ES

ESPresense

DIY Bluetooth presence detection with ESP32 nodes

Home Automation ★ 1.5k stars Medium setup MIT

ESPresense is firmware for ESP32 devices that creates a network of Bluetooth presence-detection nodes. It reports the location of phones, watches, and beacons to home automation systems over MQTT.

Key features

  • Room-level presence detection
  • ESP32 sensor network
  • MQTT reporting
  • Beacon and device tracking

Pros & cons

Strengths

  • Accurate indoor presence
  • Cheap hardware

Trade-offs

  • Needs multiple ESP32 nodes
  • Tuning required

ESPresense replaces

Last reviewed Sep 13, 2026 · 861 words

One ESP32 per room at about 6 dollars each, plus an MQTT broker you probably already have, is what it costs to know which room a person is in rather than whether their phone is on the Wi-Fi. That is the deal ESPresense offers. It is firmware, not a server: you flash it to cheap boards, they listen for Bluetooth Low Energy advertisements, and they publish distance estimates for each device they hear to MQTT. Everything clever happens downstream in Home Assistant or in the companion app.

The firmware flashes from a browser and needs no toolchain

The espresense.com installer uses Web Serial, so Chrome or Edge, a USB cable and a supported board are the whole requirement. The M5Atom Lite and the plain ESP32 dev kits are the boards the community has done the most tuning on; ESP32-C3 and S3 variants work with different antenna behaviour. After flashing, the node hosts a captive portal for Wi-Fi and MQTT settings, then reboots and starts publishing under espresense/devices/<device-id>/<room> with a JSON payload carrying RSSI, estimated distance and a fingerprint.

Where it sits in a stack: a broker such as Mosquitto, the nodes as MQTT publishers, and a consumer that turns "distance 1.8 m from kitchen node" into "person is in the kitchen". The consumer is the part people underestimate.

Tracking a phone is the hard part, and iPhones are hardest

Beacons, Tiles and most watches advertise a stable identifier, so they just work. Phones randomise their Bluetooth address every 15 minutes or so, which is the entire point of the privacy feature and the entire reason ESPresense has an identity resolution step. Two working routes:

  • Android: the Home Assistant companion app can broadcast a BLE transmitter beacon with a fixed UUID. Enable it, set the interval, and the node sees a stable ID.
  • iPhone and Apple Watch: extract the identity resolving key (IRK) for the device and give it to ESPresense so it can de-randomise the address. The project documents the extraction; it involves a paired Mac or a Windows registry read and is a one-time chore per device.

Skip identity work and you get a node that reports 40 anonymous devices, which is useless. Do it for the 2 to 4 devices that matter and you get room-level presence that beats any Wi-Fi or GPS method for the indoor case, which is the case that matters for lights and heating.

The companion app does the trilateration you do not want to write

ESPresense Companion is a separate Docker container with a floor plan editor. You draw rooms, place nodes at their real coordinates, and it fuses the distance reports from several nodes into an x/y position and a room name, then pushes device_tracker entities into Home Assistant via MQTT discovery. Without it you fall back to the older pattern of a per-room sensor and an automation that picks the nearest, which works in a flat with 3 nodes and gets flaky in a house with 8.

Run the companion on the same box as the broker. It is light, and it also gives you a live map that makes the next step tolerable.

Tuning is real work, and 3 numbers do most of it

The catalogue lists tuning as a con and it is right. The distance estimate comes from RSSI through a path-loss model, and walls, bodies and fridge doors all lie to it. The values that move results:

  • ref_rssi per device, the signal strength at 1 metre. Calibrate by standing 1 metre from a node and reading the raw value.
  • absorption per node, how quickly signal decays with distance. Between 3 and 4 for most rooms; higher for thick walls.
  • max_distance, the cut-off past which a node ignores a device. Set it just beyond the room's far corner or two rooms will fight.

Plan an evening of walking around with the companion map open. The result stabilises; it never becomes perfect, and the correct expectation is "which room, updated within 10 seconds", not "which chair".

It is not a security system and not a substitute for ESPHome

ESPresense answers one question. For sensors, relays and displays on the same class of hardware, ESPHome is the tool, and the two coexist happily on separate boards. Do not try to run both on one ESP32; BLE scanning wants the radio and the CPU to itself. And because presence is inferred from a phone people sometimes leave on a shelf, use it for comfort automations, not for locking doors.

What I'd do

Buy 4 M5Atom Lites, flash from the browser, run Mosquitto and the ESPresense Companion in Docker next to Home Assistant, and set up identity for two phones before touching any tuning. Give it a week to settle, then write the two automations that justify it: lights off when a room empties and heating down when the house does. If your first month with Home Assistant is still underway, put this on the list for month three.

Compare ESPresense

1 head-to-head comparisons.

Similar home automation apps