Smart Home Fix

Find a failed Bluetooth proxy before sensors vanish

When several Bluetooth sensors disappear together, replacing all their batteries is the wrong first move. Monitor the proxy itself, its 2.4 GHz Wi-Fi or Ethernet path and which nearby devices remain visible so the fault points to the shared link.

The fault this project detects

This project detects an offline ESPHome Bluetooth proxy, a weak network path and a group of BLE entities becoming unavailable together. It separates one flat sensor battery from a shared proxy or coverage failure.

The example uses an ESP32 proxy in a hallway, native ESPHome API connectivity, a Wi-Fi signal entity and two nearby Bluetooth sensors. Ethernet-capable hardware can replace Wi-Fi where the installation and board support it.

Bluetooth proxy fault evidence flow Multiple measurements are combined into advisory, warning and critical fault states. Proxy API status2.4 GHz link qualityNearby BLE sensor ANearby BLE sensor B Evidence model direction + context agreement + duration Advisory dashboard only Warning one push Critical repeat + audible
Several sensors disappearing through the same proxy is stronger evidence than any one unavailable entity.

The evidence model

A useful alarm does not promote one noisy reading straight to an emergency. It combines measurements that fail in different ways:

  1. Value: proxy network signal and device availability expose the current path.
  2. Direction: a Statistics helper can reveal a deteriorating RSSI baseline before disconnections.
  3. Agreement: two nearby BLE entities failing together supports a shared coverage or proxy fault.
  4. Context and time: native API status and persistence prevent normal advertisement gaps from paging you.

BLE advertisements are intermittent by design. The monitor therefore requires duration or agreement and treats the proxy's own API connection as independent evidence.

Freshness is separate evidence

An entity can keep a plausible old value without becoming unavailable. Inspect last_changed on a source that should genuinely change, and note the longest gap between meaningful state changes you actually see across a normal week in your own History - that measured interval is the freshness threshold to record for your setup. If the measured process can legitimately stay flat, add a changing source heartbeat or timestamp; do not treat an unchanged temperature, level or power value as proof that the transport is alive.

Rate maths: never copy a gradient

The Trend integration expresses min_gradient in units per second. The arithmetic example from the project brief is 4 °C/hour ÷ 3600 = 0.00111 °C/s. That is an example conversion, not a threshold for this equipment. Calculate the rate from your own timestamped readings: take two points from your own History, divide the change in the measured value between them by the elapsed seconds, and that result is your site-specific gradient. A Derivative helper can instead display a friendlier per-hour unit when configured that way.

Collect this data before choosing a threshold

Capture several days of proxy uptime, Wi-Fi signal and update gaps for each important BLE device. Include busy 2.4 GHz periods and closed-door conditions.

MeasurementWhy it mattersRequired value
binary_sensor.hall_ble_proxy_statusNative API connectivityNote how this entity behaves across a real restart and any outage you can observe on your own network, so you know its normal pattern.
sensor.hall_ble_proxy_wifi_signalBackhaul qualityWatch this over a few days and note your own normal and weak dBm ranges for that particular install position.
sensor.freezer_ble_temperatureFirst nearby advertisement streamCheck History and note the longest gap between updates you see during genuinely normal operation.
sensor.laundry_ble_humiditySecond nearby advertisement streamCheck History and note the longest gap between updates you see during genuinely normal operation.
Bluetooth integration diagnosticsWhich proxy hears each deviceReview the diagnostics page over normal operation and note which proxy healthily routes and covers each device in your own home.

The experiment that makes this article defensible

  1. Record normal updates for every important BLE sensor through a full day and night.
  2. During a supervised maintenance window, reboot the proxy and observe entity recovery without cycling the sensors.
  3. Move the proxy only through practical installation positions and compare coverage; do not infer range from one reading.
  4. If using Wi-Fi, repeat during busy 2.4 GHz conditions; a 5 GHz-only network will not serve common ESP32 proxy hardware.

Before you rely on any of this, gather your own timestamped readings, note the Home Assistant version you're running, record your exact entity IDs, and save one or two History or dashboard screenshots as your evidence baseline. Do not stage an unsafe electrical, refrigeration, pressure, battery or water fault merely to make a graph.

Create the helpers

Use Settings → Devices & services → Helpers. Create the named Number or Toggle helpers before loading the templates. Where this guide uses a Derivative, Statistics, History Stats, Integral, Schedule or Utility Meter helper, the current Home Assistant interface can create it; the source links below describe the current options.

Helper or derived entityPurposeSetting
sensor.hall_ble_proxy_wifi_signal_meanStatistics helper for recent RSSI meanChoose a sampling size and maximum age by checking how much your own raw RSSI reading bounces around between samples.
input_number.bluetooth_proxy_hold_minutesPersistence before WarningSet this long enough to ride out your own network's normal brief dropouts without a false Warning.
input_number.bluetooth_proxy_weak_wifi_dbmSite-specific weak-link thresholdSet this to the weak dBm figure you measured for your own install position in the data-collection step above.
input_boolean.bluetooth_proxy_monitoring_enabledMaster notification gateLeave this off while you test the automation against your own readings, then switch it on once you trust the thresholds.
input_number.bluetooth_proxy_critical_repeat_minutesCritical repeat spacingChoose a repeat spacing greater than zero based on how often you want a critical alert repeated for your own household.

Current Home Assistant YAML

Merge top-level keys with your existing configuration instead of duplicating them. Replace the example entity IDs consistently. If you keep automations in automations.yaml, paste only the automation list items there, without a top-level automation: wrapper.

Expose proxy connectivity and network signal in ESPHome

Merge these components into the existing ESPHome node. Keep the normal board, network, API, OTA and security settings from the device's validated configuration.

esp32_ble_tracker:

bluetooth_proxy:
  active: true

binary_sensor:
  - platform: status
    name: "Hall BLE proxy status"

sensor:
  - platform: wifi_signal
    name: "Hall BLE proxy WiFi signal"

Corroborate proxy and sensor failures in Home Assistant

Unavailable BLE entities are used here because not every Bluetooth integration exposes a changing source timestamp. For a critical process, use a dedicated heartbeat or second sensing path as well.

template:
  - binary_sensor:
      - name: "Bluetooth proxy warning"
        unique_id: bluetooth_proxy_warning
        default_entity_id: binary_sensor.bluetooth_proxy_warning
        device_class: problem
        delay_on:
          minutes: >
            {{ states('input_number.bluetooth_proxy_hold_minutes') | int(0) }}
        state: >
          {% set proxy_off = is_state('binary_sensor.hall_ble_proxy_status', 'off') %}
          {% set weak = has_value('sensor.hall_ble_proxy_wifi_signal_mean')
             and (states('sensor.hall_ble_proxy_wifi_signal_mean') | float)
                 <= (states('input_number.bluetooth_proxy_weak_wifi_dbm') | float) %}
          {% set a_missing = states('sensor.freezer_ble_temperature') in ['unknown', 'unavailable'] %}
          {% set b_missing = states('sensor.laundry_ble_humidity') in ['unknown', 'unavailable'] %}
          {{ proxy_off or weak or (a_missing and b_missing) }}
        attributes:
          reason: >-
            Proxy is {{ states('binary_sensor.hall_ble_proxy_status') }},
            mean Wi-Fi signal is {{ states('sensor.hall_ble_proxy_wifi_signal_mean') }} dBm,
            freezer sensor is {{ states('sensor.freezer_ble_temperature') }} and
            laundry sensor is {{ states('sensor.laundry_ble_humidity') }}.

      - name: "Bluetooth proxy critical"
        unique_id: bluetooth_proxy_critical
        default_entity_id: binary_sensor.bluetooth_proxy_critical
        device_class: problem
        state: >
          {{ is_state('binary_sensor.bluetooth_proxy_warning', 'on')
             and is_state('binary_sensor.hall_ble_proxy_status', 'off')
             and states('sensor.freezer_ble_temperature') in ['unknown', 'unavailable'] }}

Warning and Critical notification actions

Replace the mobile notification action and media-player entity with your own. Put critical-monitoring-alert.mp3 in /media, test it manually, and leave the monitoring Toggle off until calibration is complete.

automation:
  - id: bluetooth_proxy_warning_push
    alias: "Bluetooth proxy - Warning push"
    mode: single
    triggers:
      - trigger: state
        entity_id: binary_sensor.bluetooth_proxy_warning
        to: "on"
    conditions:
      - condition: state
        entity_id: input_boolean.bluetooth_proxy_monitoring_enabled
        state: "on"
    actions:
      - action: notify.mobile_app_your_phone
        data:
          title: "Bluetooth proxy warning"
          message: >-
            {{ state_attr('binary_sensor.bluetooth_proxy_warning', 'reason')
                or 'The warning condition is active. Check Home Assistant for evidence.' }}

  - id: bluetooth_proxy_critical_repeat
    alias: "Bluetooth proxy - Critical repeat"
    mode: restart
    triggers:
      - trigger: state
        entity_id: binary_sensor.bluetooth_proxy_critical
        to: "on"
    conditions:
      - condition: state
        entity_id: input_boolean.bluetooth_proxy_monitoring_enabled
        state: "on"
    actions:
      - action: notify.mobile_app_your_phone
        data:
          title: "Bluetooth proxy critical"
          message: "The critical condition is active. Check the equipment and evidence now."
      - action: media_player.play_media
        target:
          entity_id: media_player.alert_speaker
        data:
          media_content_id: "media-source://media_source/local/critical-monitoring-alert.mp3"
          media_content_type: "audio/mpeg"
      - repeat:
          while:
            - condition: state
              entity_id: binary_sensor.bluetooth_proxy_critical
              state: "on"
            - condition: template
              value_template: >-
                {{ states('input_number.bluetooth_proxy_critical_repeat_minutes') | int(0) > 0 }}
          sequence:
            - delay:
                minutes: >-
                  {{ states('input_number.bluetooth_proxy_critical_repeat_minutes') | int(0) }}
            - condition: state
              entity_id: binary_sensor.bluetooth_proxy_critical
              state: "on"
            - action: notify.mobile_app_your_phone
              data:
                title: "Bluetooth proxy still critical"
                message: "The critical condition remains active."
            - action: media_player.play_media
              target:
                entity_id: media_player.alert_speaker
              data:
                media_content_id: "media-source://media_source/local/critical-monitoring-alert.mp3"
                media_content_type: "audio/mpeg"

Why the logic works

Proxy API state observes the bridge, RSSI observes its backhaul, and multiple BLE entities observe radio coverage. Their different failure modes make agreement far more useful than repeatedly alerting on every individual sensor.

The design is intentionally diagnostic rather than controlling. It reports an impossible or abnormal relationship; it does not bypass equipment protection or decide that a single suspected cause is proven.

Severity tiers without alert fatigue

TierMeaningAction
AdvisoryProxy signal or device update behaviour has moved outside its recent baseline.Dashboard only
WarningThe proxy is offline, its link remains weak, or multiple nearby BLE entities fail together.One push notification
CriticalA required BLE measurement is unavailable while its serving proxy is also confirmed offline.Push, repeat and audible alert

A weak clue remains visible without interrupting you. A Warning requires persistence or corroboration. Critical is reserved for direct danger or several independent signals. That separation is what stops a useful monitoring system becoming notification wallpaper.

Troubleshooting

The status entity is missing
Add the ESPHome status binary sensor, compile and adopt the updated node, then confirm the generated entity ID.
BLE devices jump between proxies
That can be healthy. Inspect Bluetooth diagnostics and design around coverage overlap rather than pinning a device without evidence.
Wi-Fi RSSI is good but BLE is poor
The Wi-Fi and Bluetooth radios have different paths and interference; reposition based on BLE observations too.
Active connections are unreliable
Active proxy connections consume resources and differ from passive advertisements. Check the current ESPHome limits and device behaviour.
A single sensor vanishes
Check its battery, advertisement interval and local obstruction before blaming the shared proxy.

Safety and limits

A Bluetooth proxy is not a certified alarm receiver. Do not make freezers, medical equipment, security or life safety depend on one ESP32 and one network path. Use approved local alarms and redundant sensing where consequences are serious.

If a webhook is added later, treat its webhook_id like a password, keep local_only: true unless a reviewed design requires otherwise, and never use an unauthenticated webhook for locks, garage doors, power isolation or anything destructive.

Official sources

These are the primary documentation pages used for the design. Check them against the Home Assistant or ESPHome version you are actually running.

Related Smart Home Fix guides

FAQ

Does an unavailable Bluetooth sensor prove the proxy failed?

No. The sensor battery, advertising interval, obstruction or integration can fail independently. Proxy status and a second nearby sensor provide corroboration.

Does an ESP32 Bluetooth proxy use 5 GHz Wi-Fi?

Common ESP32 proxy boards use 2.4 GHz Wi-Fi. Confirm the exact board specification and provide suitable 2.4 GHz coverage or supported Ethernet.

Why monitor proxy Wi-Fi signal?

The BLE radio can be healthy while the proxy's Home Assistant backhaul is weak. Both paths must work for observations to arrive.

Should I enable active Bluetooth connections?

Only if the devices need them. Active connections use proxy resources, so check the current ESPHome documentation and measured workload.

How many proxies do I need?

There is no fixed count. Place them from measured coverage, building materials, device density and the consequence of losing one path.