diff --git a/homeassistant/components/esphome/bluetooth/scanner.py b/homeassistant/components/esphome/bluetooth/scanner.py index 7c8064d5583..4fbaf7cabb6 100644 --- a/homeassistant/components/esphome/bluetooth/scanner.py +++ b/homeassistant/components/esphome/bluetooth/scanner.py @@ -6,6 +6,7 @@ import datetime from datetime import timedelta import re import time +from typing import Final from aioesphomeapi import BluetoothLEAdvertisement from bleak.backends.device import BLEDevice @@ -23,6 +24,15 @@ from homeassistant.util.dt import monotonic_time_coarse TWO_CHAR = re.compile("..") +# The maximum time between advertisements for a device to be considered +# stale when the advertisement tracker can determine the interval for +# connectable devices. +# +# BlueZ uses 180 seconds by default but we give it a bit more time +# to account for the esp32's bluetooth stack being a bit slower +# than BlueZ's. +CONNECTABLE_FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS: Final = 195 + class ESPHomeScanner(BaseHaScanner): """Scanner for esphome.""" @@ -45,8 +55,12 @@ class ESPHomeScanner(BaseHaScanner): self._connector = connector self._connectable = connectable self._details: dict[str, str | HaBluetoothConnector] = {"source": scanner_id} + self._fallback_seconds = FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS if connectable: self._details["connector"] = connector + self._fallback_seconds = ( + CONNECTABLE_FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS + ) @callback def async_setup(self) -> CALLBACK_TYPE: @@ -61,7 +75,7 @@ class ESPHomeScanner(BaseHaScanner): expired = [ address for address, timestamp in self._discovered_device_timestamps.items() - if now - timestamp > FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS + if now - timestamp > self._fallback_seconds ] for address in expired: del self._discovered_device_advertisement_datas[address]