Bermuda - Bluetooth/BLE Room Presence and tracking [custom integration]

Hello, can you suggest a Bluetooth keyring that works correctly with Bermuda? I don’t want to use the companion app for Home/Away status

1 Like

I don’t use a USB dongle at all. I use ESPHome bluetooth proxies Plus the built in bluetooth adapter of my host.
The bluetooth adapter in my setup only is used to show home/Away on a general level. It is shown as an iBeacon so is probably not this integration at all. It also is used for classic BT detection of devices using a different tracking integration.
The ESPHome BT proxies tell me which location my tracked devices are and if they are out of range of all scanners then they show as unknown.

Chipollo works if you don’t pair it with the APP on your phone.
So does a fitbit/pixel device, again if you don’t have it connected to the APP.

There are other tags available that are Eddystone/iBeacon compatible that will work. I just search Google/Amazon for them.

Hello.
I have a question about IRK, and bluetooth beacon in app home assistant.

I have a android device (watch with wear os, watch ultra exctly) and I obtain the IRK number of this device.
If I enable de ibeacon in the home assistant app I detect with bermuda this ibeacon.
And I detect the IRK with the private ble integration.

But if I stop the ble transmiting in the home assistant app, after a few minutes the sensor bases in IRK private integration, detect away.

Its related the ble transmiting in the home assistant app, with the transmiting of the IRK???

In a follow up to my previous post I am trying to make Bermuda less twitchy about room updates. I guess my house is not the largest and I have quite a lot of indoor and outdoor interference. I mean on average my proxies see about a 1000 devices… :roll_eyes:

image

I am still calibrating my trackers whenever I see fit, but I also try to be clever and use other factors for room guestimation. Previously I tried trilateration with ESPresense but that was also quite hit or miss because of the interference. And ESPresense was also extremely chatty. I guess Bermuda would also be when enabling all the distance sensors, maybe this could also be added as attributes? Because I’m not really interested in storing those values or iterating over all these sensors. But idk :person_shrugging: .

Anyway, I thought of using my motion sensors, which I have plenty of and that seems to reduce twitchyness a fair bit. This is still a WIP, but any ideas are welcome :slight_smile: .

{% set person_entity = "person.alex" %}
{% set area_entity = "sensor.area_alex" %}
{% set devices = [
  "540c501479271eb71aaaac760a98064d",
  "fa4df2222a38bb18a009405aaad40f17"
] %}
{% set occupancy_label = "Presence" %}

{### Template sensor ###}
{% set previous_state = iif(has_value(area_entity), states(area_entity), "unavailable") %}

{# Create namespace for storing data #}
{% set data = namespace(trackers=[], areas=[]) %}

{# Setup trackers #}
{% for d in devices %}
  {% set entities = expand(device_entities(d)) %}
  {% set bermuda_area = entities | selectattr('attributes.device_class', 'eq', 'bermuda__custom_device_class') | list %}

  {% set data.trackers = data.trackers + [{
    "area": bermuda_area | map(attribute='state') | first,
    "distance": entities | selectattr('attributes.device_class', 'eq', 'distance') | map(attribute='state') | list | first | float(20),
    "last_changed": bermuda_area | map(attribute='last_changed') | first | as_timestamp,
  }] %}
{% endfor %}

{# Setup current occupied areas #}
{% for l in label_entities(occupancy_label) %}
  {% if expand(l) | selectattr('state', 'eq', 'on') | list | count > 0 %}
    {% set data.areas = data.areas + [area_name(l)] %}
  {% endif %}
{% endfor %}

{# Set current occupied areas from trackers #}
{% set occupied_areas = data.trackers
                          | map(attribute='area')
                          | reject('eq', 'unknown')
                          | list %}
{% set unique_occupied_areas = occupied_areas | unique | list %}

{# Set average distance in areas from trackers #}
{% set average_distance = data.trackers
                            | rejectattr("area", "eq", "unknown")
                            | map(attribute="distance")
                            | average %}

{% if unique_occupied_areas | count == 1 and occupied_areas | count != 1 %}
  {% if average_distance >= 12 %}
    Outside
  {% elif unique_occupied_areas | first in data.areas %}
    {{ unique_occupied_areas | first }}
  {% else %}
    {{ previous_state }}
  {% endif %}
{% else %}
  {% set is_unknown = data.trackers
                        | map(attribute='area')
                        | select('eq', 'unknown')
                        | unique | list | count == 1 %}

  {% if is_unknown %}
    {% if is_state(person_entity, 'home') %}
      {{ previous_state }}
    {% else %}
      unknown
    {% endif %}
  {% else %}
    {% set newest = data.trackers
                      | rejectattr("area", "eq", "unknown")
                      | sort(reverse=true, attribute='last_changed')
                      | first %}

    {% if newest.distance <= 3.5 and newest.area in data.areas %}
      {{ newest.area }}
    {% elif average_distance >= 8 %}
      Outside
    {% else %}
      {{ previous_state }}
    {% endif %}
  {% endif %}
{% endif %}

The sensor.area_alex is the template sensor itself, this is used to retrieve the previous state. The devices are the id’s of the trackers that I created with Bermuda. And the occupancy label is the label I use to mark my motion sensors. Retrieving those could also be done by iterating the state object, but this seems more efficient. Outside is a special place that will trigger on a distance threshold.

I also tried to template my house layout in Jinja as some sort of linked list in a dict. So that one can only go from ie. Hallway to Livingroom and not from Livingroom to Bedroom. That seemed to work too, but I guess that could be something for later. It also increased complexity quite a lot, which isn’t desirable with Jinja.

The only thing that is still bothering me is that I cannot for the life of me get my wife’s Apple Watch to work reliably. It is just away most of the time. Except when she uses the wrist gesture.

Installed this integration using ESP32s CP2102 flashed with the ready made BT Proxies that I already had in use for the last 2 years ish.

I am getting that issue of the Area and Distance sensor going in the ‘unknown’ state for very long periods of time. This is whilst the tracker device (Android with HA comp app), being stationary.

Both the ESP proxies do get recognised initially. But then seem to switch to unknown or the distance is wildly inaccurate.

I initially left the configurable values as default, but the tracked devices were still going to unknown. (Have tried with two different Android phone).

Then I tried the calibration, which seemed to work when moving away to the ‘5 meter’ distance, with the distance value roughly being reflected. But then, after submitting the changes, when looking at the sensors, Area and Distance, both go to unknown.

As I write this message, the device tracker next to me has gone from 1.2 m to 5m and anywhere in-between and also showing unknown frequently. This is within a space of 5 minutes.

Is there anything obvious that I am missing that I could check?

Thanks.

I had a similar problem with BT proxies that had active scanning enabled (bluetooth_proxy: active: true). I have a few devices in my house that require active bluetooth connections (Ember mugs). When the proxies would handle messages from these devices, the Bermuda status would often go to unknown from those devices.

I “fixed” this by adding BT proxies just for Bermuda with this setting turned off, and a few other BT proxies with it turned on to handle the mugs. The proxies with active scanning turned on sometimes go unknown, but since there is another proxy in the same room with it turned off, it doesn’t affect Bermuda.

Ah interesting, thanks.

I do need to get more ESPs (others) for the sole use of BT presence. The two exiting BT proxies i have provide plenty of coverage.

The proxies are used for SwitchBot blinds, they shouldn’t be actively connecting, but I wouldn’t know if they are polling or something.

I’ve not looked yet, but where do you change the YAML code for the BT proxies?

You can watch the logs of the BT proxy to see if there are active connections.

Check out ESPHome-Configurations on the Bermuda GitHub for more details about configuring ESPHome.

You want to set

bluetooth_proxy:
  active: false

v0.7.3 - New release for HA :rotating_light: 2025.2.0 Compatability!

This release is pretty much compulsory for 2025.2.0 onward, as some changes have been made in HA’s bluetooth integration.

The three big items here are:

  • :rotating_light: FIX for compatibility with HA 2025.2.0 and the new Bluetooth devices in this release. Bermuda will preference areas and names defined by the user in the new Bluetooth core integration’s device page, but will fall back to using the ESPHome / Shelly device names and areas otherwise. Thanks to @tbrasser for the heads-up on this, as well as @jkpe and @bmatheny for their input - much appreciated!
  • :rocket: Significant performance improvements in update cycles thanks to @Lash-L
  • :ring_buoy: FIX crashing and performance improvements for diagnostics download again thanks to @Lash-L

:white_check_mark: Also Bermuda has made it into the HACS default repositories, so discovery of Bermuda (and installation) for new users should be even easier!

:chart_with_upwards_trend: Bermuda’s stats from the opt-in HA telemetry stats show us having over 3,300 users and picking up about 500 per month - given the opt-in nature of those stats this means a likely user count of somewhere between 3,300 and 11,000 :astonished: so umm… welcome to the party!

New contributors!

Speaking of parties…

Thanks for your contributions (and to more from others in the coming releases, already in the pipeline)!

Changes

Update very much encouraged via HACS, full release notes at Release v0.7.3 · agittins/bermuda · GitHub

1 Like

Can we install this right away, or do we have to wait until HA 2025.2 is installed?

Good question - it’s fully backward compatible, my production system is running Bermuda v0.7.3 on HA 2025.1.4 so you shouldn’t™ have any trouble :+1:t3:

2 Likes

Nothing blew up here… So far.

1 Like

Excellent!

Working well here too. Thanks. :grin:

I got this set up on my android phone (Sony Xperia 5V) and everything is working great so far on default settings. I am using Shelly gen 2 devices as bluetooth proxies, some inside walls so I needed to set the transmitter power to high with balanced mode 3Hz to give best performance. I also enabled the option to transmit only when my the phone is on my home WIFI network. I want to now get this working on my partner’s phone (Xiaomi Redmi 12 Pro 5G) to help with some presence related automations. Initially this seemed to be working well using the same settings as mine. However, last night, when her phone ran out of battery then rebooted, it was not detected by any of the bluetooth proxies for almost 6 hours. I checked in the companion app during this period and the ble transmitter was showing as active and transmitting (under the condition that it was connected to my home wifi). So it seems to be a handshake issue after the phone is rebooted. Any ideas?

There isn’t any handshaking stuff going on, as it’s all a one-way flow - the phone should just broadcast adverts, and if they’re being broadcast, Bermuda should pick them up.

The main thing to check is that in Bermuda’s config that you have selected the iBeacon: xxxx device for the phone, and not an entry that just uses the current MAC address. Given your other phone is working OK it’s quite likely that you’ve got this part covered OK.

If you install a BLE monitoring app like NRFConnect (it’s free) on your Xperia, you can see what (and if) your partner’s phone is advertising. This will let you see what’s happening “in the air” to eliminate any part of the Shelly/HA/Bermuda side of things from the equation.

At what point did their phone start showing up again? Was it when a particular action was taken (like a reboot, or cycling bluetooth off and on again etc)?

BTW, regarding automating with wifi as a trigger, also consider using the geo sensors, if you trigger on entering the home zone, your BT advertising will start further away than your wifi can, so the BLE detection will happen immediately that you are in BLE range of any proxy - this might end up being a longer range (and quicker response) than waiting for the wifi to get into range and negotiate a connection. But that’s an aside from your issue, though.

Hi again @agittins and keep up the good work.

Well after much thinking and tinkering here it is…

:rocket: Introducing BLE Positioning System (BPS) – A Smart Indoor Tracking Solution! :house::round_pushpin:

BPS is an innovative (near) real-time indoor positioning system designed to seamlessly integrate with Home Assistant. By utilizing ESPHome devices with Bluetooth proxy functionality and of course Bermuda, BPS can accurately track your Bluetooth devices within your home.

:small_blue_diamond: Key Features:
:heavy_check_mark: (near) Real-time tracking – See exactly where a device is located on a floor plan, just like GPS on a map.
:heavy_check_mark: Zone detection – Define zones (rooms) and track if a device is in a specific zone.
:heavy_check_mark: Multi-floor detection – Determine which floor a device is on for precise presence tracking.

:pushpin: Get started now! Learn more and install BPS from the GitHub page:
:link: GitHub Repository

bps_tracking

3 Likes

Wow! This looks pretty amazing! I installed it on my live system and had a bit of a poke about and it looks very promising (I wasn’t able to spend enough time to get it properly configured, so mostly going by a glance through the code, your examples and some initial attempts at trying to add and scale proxy entities).

This looks really promising!

v0.7.4 Last Seen Sensor, Repairs and Regressions! Latest

This release brings:

  • :wrench: An important fix for distance smoothing that was causing extra-twitchy area changes and sometimes sensors locking into Unknown shortly after starting.
  • :candy: The long-awaited Area Last Seen sensor, that lets you easily automate on where the kids left the tablet before the battery ran out (this sensor is disabled by default, so you need to enable it for your desired devices). Big thanks to @prestomation for their first contribution to Bermuda in getting this one up!
  • :gear: If a scanner is lacking an assigned area, the sensor will indicate this and a repair issue will be raised to make it easier to discover where the problem is.

What’s Changed

  • feat: raise repair for scanners without areas by @agittins in #458
  • Remove manual HACS install steps by @Lash-L in #434
  • Add ‘Area Last Seen’ sensor by @prestomation in #440
  • feat: Flag Area sensor if scanner area is invalid by @agittins in #459
  • chore: use new manager.async_current_scanners api by @agittins in #461
  • fix: regression from v0.7.3 hist…dist…interval by @agittins in #464

New Contributors

Full release notes at Release v0.7.4 Last Seen Sensor, Repairs and Regressions! · agittins/bermuda · GitHub

1 Like