Michael Zazon

Home automation · Build log

Our heat pump heads as Bluetooth proxies

The ESP32 boards already on the Mitsubishi heads become passive Bluetooth proxies for room-level presence via Bermuda.

Part 4 · CN105

HA now knows which room my phone is in, because the nine ESP32 boards I have plugged into the CN105 ports of my Mitsubishi heads (see the first part) double as passive Bluetooth proxies, and the Bermuda integration translates what they hear into a room.

This enables more precise occupancy tracking of who. Also another unlock: when our toddler runs off with the Apple TV remote and hides it, we can easily pinpoint it. It’s the little things :)

I came across a few Reddit posts on folks running Bermuda in Home Assistant and was really curious about the use cases. Tracking AirTags in the house, phones, Apple Watches, and experimenting with lower cost BLE devices was intriguing. I’m finding that there is a plugin for everything in HA and each one more tempting than the next, so no surprise that I wanted to peel back this onion. I looked into the hardware required for this and to no surprise the brilliant ESP32 was at the heart of everything. Turns out I have 10 of these around my house now (9 Mitsubishi heads and one Navien tankless water heater) and the locations are spread around naturally such that it’s ideal for BLE triangulation.

Previously, I didn’t have Bluetooth enabled in Home Assistant (my host adapter entry was disabled, no Bermuda or Private BLE Device integration) and in each head I have an M5Stack AtomS3 Lite running ESPHome using the esp-idf framework with the MitsubishiCN105ESPHome component. esp-idf is what ESPHome recommends for their Bluetooth proxy so I was already on the right framework. The tenth board I have (the Navien) is left out of this, it has an RS485 going to the water heater and isn’t a proxy.

One of the only concerns I had was the shared hardware on the ESP32 for Wi-Fi and Bluetooth, given I rely on these to be the backbone of my climate controls of the house (more details on the climate coordinator later). We needed to thoroughly test these out before rolling any driver changes out to everything to activate the BLE listening. We can’t tolerate any Wi-Fi drops or flakiness, in other words.

The ESP32-S3 has a single 2.4 GHz radio which Wi-Fi and Bluetooth take turns using. The Bermuda wiki warns that setting the scan interval and scan window too close together can cause Wi-Fi dropouts and Home Assistant timeouts. A sweep of Reddit mostly reassured me: one user runs five Mitsubishi heads from an ESP32 doing CN105 plus BLE proxy on the same board, proxies fine alongside serial and IR. The bad reports were all load-related: busy ESP32s, unstable active GATT connections, Bermuda plus active proxies crashing a Home Assistant Green, silently hung scanners “fixed” by watchdog reboots.

Those reports shaped the package: the heads only listen, so passive scanning, passive proxy, no GATT connections (I don’t need them for anything in the house). The scan window is 160 ms every 320 ms (half duty), Bermuda suggests 300 ms. The free heap sensor exposes memory leaks. Every head includes the same common/ble-proxy.yaml:

# Bluetooth proxy on every head (Kitchen pilot 2026-10-06, fleet 2026-10-09).
# Passive only: presence (IRK/iBeacon) and BLE sensors need no connections,
# and every bad report from other users involves active GATT connections.
# The S3 shares one radio between Wi-Fi and BLE, so the scan window starts at
# half duty; raise it only if Wi-Fi and the CN105 link stay clean.
esp32_ble_tracker:
  scan_parameters:
    interval: 320ms
    window: 160ms
    active: false

bluetooth_proxy:
  active: false

debug:

sensor:
  - platform: debug
    free:
      name: Free Heap
      entity_category: diagnostic

Each head picks it up with one line under packages: in its own file, for example kitchen-ac.yaml:

  ble_proxy: !include common/ble-proxy.yaml

I decided to roll this out to our kitchen split head first, monitor the impact and closely monitor the telemetry from the device. It ran for almost 3 days with no issues… green light!

The Kitchen head has the strongest Wi-Fi signal in the house at around −36 dBm, so I figured it would be the best place to start. I flashed the firmware on October 6 at 14:41. The boot log showed passive scan at 160 of 320 ms, scanner running, and HA automatically added a Bluetooth entry. In the first five minutes, it heard about 60 devices, mostly Apple and Eve, had 174 KB of free heap, and the Wi-Fi signal was −37 dBm. If the silent scan hangs, that’s pilot failure.. a watchdog reboot is unacceptable on a heat pump controller.

The soak checks continued to be boring. After about 40 hours, the head had not rebooted, the CN105 link was never broken, Wi-Fi was at −37 to −40 dBm, and the free heap was flat at around 174 KB. At about 67 hours, on the morning of October 9, the situation was the same, with about 55 devices in view and the last advert 0.2 seconds before the check. All unavailable in the history was fleet-wide and due to a Home Assistant restart, not the head.

The same afternoon, I gave the other eight heads the same package in sequence from 13:12 to 13:22, verified their MAC address before the OTA, and all came back with the CN105 link and their previous climate state. At 15:23, Bermuda 0.8.7 was live on all nine proxies.

Nine ESP32 heads reporting Bluetooth adverts to Home Assistant and Bermuda Kitchen Dining Living Playroom Primary bedroom Primary closet Guest bedroom Kids' room Kids' room BLE adverts over Wi-Fi Navien: not a proxy Home Assistant signal strength Bermuda picks a room

I seem to be picking up all sorts of passers-by, UPS deliveries, DoorDasher phones coming up to the front door, and all kinds of interesting things.

As of the night of October 11 (about 2.4 days), Bermuda has seen 739 devices total, 78 of which were visible at the time via all nine proxies. I can resolve my iPhone to a room, but not its exact position within the room, since I’m estimating distance based on signal strength on each proxy.

Home Assistant’s Bermuda device page for an iPhone: Area reads Master Bedroom, Floor reads Second Floor, the nearest scanner is the Master Bedroom AC at -64 dBm, and the unfiltered distance to each other head is listed below

On the climate side, same check: no unplanned reboots, and the CN105 link is still up on all nine heads. Each unavailable was either a HA restart or a planned OTA, so there were zero single-head dropouts. Mean Wi-Fi signal per head is unchanged from pre-proxy. Mean free heap is 173 to 174 KB, with brief dips recovered.

I think this opens up a lot of future use cases on cheap hardware, or even repurposing existing gear (I’m very much against e-waste, and for being thrifty in one’s hobby.)

I have only scratched the surface with Bermuda, and some fine tuning is underway to make the most of it. I can see more interesting automations taking shape soon. I’m not sure if this replaces the need for mmWave presence sensors, but maybe combined with some Wi-Fi sensing techniques and some of the things Hue is doing with their Pro hub and presence detection, a combination of these could lead to some fun discoveries and use cases!

The heads have one more job in this house.. the climate coordinator that ties them all together is up next.