Full 3D Bluetooth trilateration for Home Assistant — for single and multi-storey homes.
Place a handful of cheap ESP32 or Shelly devices around your home and BLE Trilateration resolves every tracked device's position in three-dimensional space in real time. Not just "probably in the lounge" — an actual (x, y, z) coordinate, from which it pins the exact room and floor. It knows your house has physical laws. It won't tell you your phone is in the garage when you're upstairs in bed.
Forked from Bermuda BLE Trilateration by @agittins. The vision for full BLE trilateration originated with agittins, but never quite made it into Bermuda. This fork picks up that idea and runs with it — fully implementing 3D trilateration along with a new estimation pipeline, topology-gated floor inference, and a reworked configuration model.
A network of fixed BLE scanner anchors picks up signal-strength (RSSI) advertisements from your tracked devices. BLE Trilateration runs those readings through a topology-gated trilateration pipeline:
- 3D geometry solve — weighted least-squares trilateration across all visible anchors produces a full
(x, y, z)position estimate with a geometry-quality score. - Calibration fingerprinting — stored RSSI signatures from known room positions are matched against live readings to produce a room probability vector.
- Floor reachability gate — before any floor change is accepted, the system asks: could this device physically have reached that floor? It checks the device's recent position history against configured transition zones (stairs, lifts). Physically impossible floor changes are blocked outright before they can corrupt room inference.
- Floor evidence fusion — fingerprint evidence, RSSI floor evidence, and geometry-derived Z hints are combined — but only among floors the device could actually reach.
- Room inference — final room assignment is locked in within the confirmed floor.
- Hysteresis — stability smoothing is applied only at legitimate room boundaries, not as a band-aid for impossible teleportation.
The key design principle: topology and physical reachability are hard constraints, not suggestions. A device stable in a room on one floor cannot be assigned to another floor two seconds later unless it passed through a configured transition zone. The physics of your house are baked in.
sensorentities for Area (room) and Distance for each tracked devicedevice_trackerentities linkable to Home Assistant Persons for Home/Away tracking- Supports iBeacon devices including Android phones with randomised MAC addresses running the HA Companion App
- Supports IRK (resolvable keys) via the Private BLE Device core integration
- Multi-floor tracking with topology-gated floor inference
- Home Assistant — a recent release
- BLE scanner anchors — one or more of:
- ESPHome devices with the
bluetooth_proxycomponent enabled - Shelly Plus (Gen2 or later) devices with Bluetooth proxying enabled
- A USB Bluetooth adapter on the HA host (limited — no packet timestamps, suitable only for Home/Away and coarse area detection)
- ESPHome devices with the
- BLE devices to track — phones, smart watches, beacon tiles, thermometers, etc.
- At least three anchors for meaningful 2D trilateration; more anchors and vertical spread improve 3D and multi-floor accuracy.
Install via HACS by adding this repository as a custom repository, then search for BLE Trilateration.
Alternatively, copy the custom_components/ble_trilateration/ directory into your HA custom_components/ folder and restart Home Assistant.
After installation, add the integration in Settings → Devices & Services → Add Integration and search for BLE Trilateration.
Setup is done in stages. Each stage builds on the previous one. You can stop after any stage and the integration will still provide value with whatever is configured.
BLE Trilateration works in a Cartesian coordinate system that you define. Before placing anchors you need to pick an origin point — a fixed reference location in your home that will be (0, 0, 0).
Good choices:
- A corner of the house at ground/street level
- The centre of a room on the main floor
The coordinate system convention is:
x— horizontal, positive toward one side of the house (e.g. East)y— horizontal, positive toward the other side (e.g. North)z— vertical, positive upward; the origin floor surface should be atz = 0
All anchor positions, calibration samples, and transition zones must use the same coordinate system.
Each scanner anchor needs a 3D position measured from your chosen origin.
In Settings → Devices & Services → BLE Trilateration → Configure → Scanner Anchors, for each anchor:
- Enter its
x,y, andzcoordinates in metres - Give it a human-readable name
Tips:
- Measure anchor positions as accurately as you can. Errors here directly limit position accuracy.
- Anchors at different heights (e.g. a device on the ceiling vs. one at desk height) provide Z separation that helps floor inference.
- Aim for anchors that cover every room you want to track, with no room having fewer than two visible anchors.
In Configure → Select Devices, choose the BLE devices you want to track. The list shows all currently visible devices. Selecting a device creates sensor and device_tracker entities for it.
Devices can be:
- Regular BLE peripherals (by MAC address)
- iBeacon devices (by UUID)
- Private BLE devices set up via the Private BLE Device integration (for iOS and Android devices with rotating MACs)
For multi-floor homes, tell the integration where each floor's surface is in your coordinate system.
In Configure → Floor Heights, for each Home Assistant floor:
- Set
floor_z_m— the Z coordinate of the floor surface in metres - Optionally set a
floor_z_min_m/floor_z_max_mrange for floors with natural Z variation (outdoor areas, sloped entries, garages)
Example: If your origin is at ground-floor level,
ground_floormight havefloor_z_m = 0, a first floor above might havefloor_z_m = 2.5, and a basementfloor_z_m = -2.8.
The integration uses these values to derive a phone-height band (floor_z_m to floor_z_m + 1.2 m) as a strong prior for the Z estimate during trilateration. Floors with non-overlapping bands can often be discriminated from Z alone.
Calibration samples are RSSI fingerprints recorded at known positions. They allow the classifier to distinguish rooms whose RSSI patterns differ even when trilateration geometry is ambiguous.
In Settings → Developer tools → Actions → Record Calibration Sample:
- Stand (or place your tracked device) at a representative position in a room
- Choose the room/area and confirm the
(x, y, z)position - Let the integration record for 60 seconds
Tips:
- Collect at least one sample per room you want to track
- For large rooms, collect multiple samples at different positions
- Collect samples with your home in its normal state (furniture in place, doors as usually set)
- Samples are tied to the current anchor layout hash — adding or repositioning anchors invalidates existing samples and requires recapture
Transition zones tell the integration where floor changes are physically possible — typically stairs, lifts, or ramps.
Without transition zones configured for a floor pair, the integration falls back to evidence-only floor inference with no topology gate for that pair.
In Settings → Developer tools → Actions → Record Transition Sample:
- Stand at the entry point of the transition (e.g. the bottom of the stairs)
- Record a capture — this records your position and current RSSI fingerprint
- Stand at the exit point of the transition (e.g. the top of the stairs) and record a second capture
- Assign the zone a name and specify the floor pairs it connects (e.g.
ground_floor → first_floor)
Notes:
- Each end of the transition (bottom and top of stairs) should be a separate capture. Do not average them — the integration stores each as an independent Gaussian kernel.
- A zone authorises specific directional floor pairs. A zone connecting
ground_floor → first_floordoes not automatically authoriseground_floor → basement.- The integration blocks floor changes that would require passing through a transition zone that the device has not been near recently.
The integration separates two questions before assigning a floor:
- Which floors are physically reachable right now? — answered by the topology and reachability gate using transition zones and recent device motion
- Among the reachable floors, which one has the best evidence? — answered by fingerprint matching, RSSI, and Z geometry
The reachability gate works as follows:
- When a new floor candidate (challenger) appears, the system freezes the device's last confident pre-challenge position
- It estimates how far the device could have moved since then, based on elapsed time and observed motion
- It checks whether the nearest transition zone covering that floor pair is within that reach
- If not, the challenger is blocked — it cannot win the evidence competition regardless of RSSI
A background traversal tracker continuously records when the device enters and exits each transition zone. If the device genuinely traversed a zone (entered and then exited) in the recent past, the gate is lifted and the floor change is allowed to compete on evidence normally.
This means a legitimate floor change — where the user actually walked up or down the stairs — will succeed. An impossible floor change — where the classifier was confused by multipath signals through a floor slab — will be blocked before it can cascade into wrong room inference.
The ble_trilateration.dump_devices service returns the full internal state of the integration as JSON/YAML. This is useful for:
- Inspecting raw RSSI readings per scanner
- Checking position estimates and geometry quality scores
- Debugging room classification and floor inference
- Building custom template sensors from integration data
Call it from Developer Tools → Services in Home Assistant. Pass an addresses parameter to filter output to a single device.
Note: the internal data structure is not a stable public API. Fields may change between releases.
This project is a fork of Bermuda BLE Trilateration by @agittins. The original integration introduced the concept of BLE-proxy-based room presence in Home Assistant and provided the foundational architecture this fork builds on.
The integration template was originally generated from @oncleben31's Home Assistant Custom Component Cookiecutter and @Ludeeus's integration_blueprint.
Contributions are welcome. Please read CONTRIBUTING.md before submitting a pull request.
