From 7bda873c2a53ef42d9d97d63addf514f64cce419 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 31 Jul 2023 01:02:15 -0700 Subject: [PATCH] Fix bthome not remembering a device is a sleepy device (#97517) --- homeassistant/components/bthome/__init__.py | 7 +++++++ homeassistant/components/bthome/binary_sensor.py | 5 +---- homeassistant/components/bthome/const.py | 1 + homeassistant/components/bthome/coordinator.py | 10 ++++++++++ homeassistant/components/bthome/sensor.py | 5 +---- tests/components/bthome/test_sensor.py | 6 +++++- 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/bthome/__init__.py b/homeassistant/components/bthome/__init__.py index 3e2e17a9a2114..751c8f74bf9f1 100644 --- a/homeassistant/components/bthome/__init__.py +++ b/homeassistant/components/bthome/__init__.py @@ -20,6 +20,7 @@ BTHOME_BLE_EVENT, CONF_BINDKEY, CONF_DISCOVERED_EVENT_CLASSES, + CONF_SLEEPY_DEVICE, DOMAIN, BTHomeBleEvent, ) @@ -43,6 +44,11 @@ def process_service_info( entry.entry_id ] discovered_device_classes = coordinator.discovered_device_classes + if entry.data.get(CONF_SLEEPY_DEVICE, False) != data.sleepy_device: + hass.config_entries.async_update_entry( + entry, + data=entry.data | {CONF_SLEEPY_DEVICE: data.sleepy_device}, + ) if update.events: address = service_info.device.address for device_key, event in update.events.items(): @@ -113,6 +119,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: entry.data.get(CONF_DISCOVERED_EVENT_CLASSES, []) ), connectable=False, + entry=entry, ) await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) diff --git a/homeassistant/components/bthome/binary_sensor.py b/homeassistant/components/bthome/binary_sensor.py index d9d24e9500717..277c2af7ff26e 100644 --- a/homeassistant/components/bthome/binary_sensor.py +++ b/homeassistant/components/bthome/binary_sensor.py @@ -203,7 +203,4 @@ def is_on(self) -> bool | None: @property def available(self) -> bool: """Return True if entity is available.""" - coordinator: BTHomePassiveBluetoothProcessorCoordinator = ( - self.processor.coordinator - ) - return coordinator.device_data.sleepy_device or super().available + return self.processor.coordinator.sleepy_device or super().available diff --git a/homeassistant/components/bthome/const.py b/homeassistant/components/bthome/const.py index 75a8ab4fc86b4..780833bf92e9a 100644 --- a/homeassistant/components/bthome/const.py +++ b/homeassistant/components/bthome/const.py @@ -7,6 +7,7 @@ CONF_BINDKEY: Final = "bindkey" CONF_DISCOVERED_EVENT_CLASSES: Final = "known_events" +CONF_SLEEPY_DEVICE: Final = "sleepy_device" CONF_SUBTYPE: Final = "subtype" EVENT_TYPE: Final = "event_type" diff --git a/homeassistant/components/bthome/coordinator.py b/homeassistant/components/bthome/coordinator.py index dafa932a73e93..bb743be7c7fcd 100644 --- a/homeassistant/components/bthome/coordinator.py +++ b/homeassistant/components/bthome/coordinator.py @@ -13,8 +13,11 @@ PassiveBluetoothDataProcessor, PassiveBluetoothProcessorCoordinator, ) +from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant +from .const import CONF_SLEEPY_DEVICE + class BTHomePassiveBluetoothProcessorCoordinator(PassiveBluetoothProcessorCoordinator): """Define a BTHome Bluetooth Passive Update Processor Coordinator.""" @@ -28,12 +31,19 @@ def __init__( update_method: Callable[[BluetoothServiceInfoBleak], Any], device_data: BTHomeBluetoothDeviceData, discovered_device_classes: set[str], + entry: ConfigEntry, connectable: bool = False, ) -> None: """Initialize the BTHome Bluetooth Passive Update Processor Coordinator.""" super().__init__(hass, logger, address, mode, update_method, connectable) self.discovered_device_classes = discovered_device_classes self.device_data = device_data + self.entry = entry + + @property + def sleepy_device(self) -> bool: + """Return True if the device is a sleepy device.""" + return self.entry.data.get(CONF_SLEEPY_DEVICE, self.device_data.sleepy_device) class BTHomePassiveBluetoothDataProcessor(PassiveBluetoothDataProcessor): diff --git a/homeassistant/components/bthome/sensor.py b/homeassistant/components/bthome/sensor.py index fc8673e801bfe..95cba20055fd3 100644 --- a/homeassistant/components/bthome/sensor.py +++ b/homeassistant/components/bthome/sensor.py @@ -400,7 +400,4 @@ def native_value(self) -> int | float | None: @property def available(self) -> bool: """Return True if entity is available.""" - coordinator: BTHomePassiveBluetoothProcessorCoordinator = ( - self.processor.coordinator - ) - return coordinator.device_data.sleepy_device or super().available + return self.processor.coordinator.sleepy_device or super().available diff --git a/tests/components/bthome/test_sensor.py b/tests/components/bthome/test_sensor.py index 4450bfcc93671..582dcabbb3398 100644 --- a/tests/components/bthome/test_sensor.py +++ b/tests/components/bthome/test_sensor.py @@ -9,7 +9,7 @@ from homeassistant.components.bluetooth import ( FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS, ) -from homeassistant.components.bthome.const import DOMAIN +from homeassistant.components.bthome.const import CONF_SLEEPY_DEVICE, DOMAIN from homeassistant.components.sensor import ATTR_STATE_CLASS from homeassistant.const import ( ATTR_FRIENDLY_NAME, @@ -1138,6 +1138,8 @@ async def test_unavailable(hass: HomeAssistant) -> None: assert await hass.config_entries.async_unload(entry.entry_id) await hass.async_block_till_done() + assert CONF_SLEEPY_DEVICE not in entry.data + async def test_sleepy_device(hass: HomeAssistant) -> None: """Test sleepy device does not go to unavailable after 60 minutes.""" @@ -1191,3 +1193,5 @@ async def test_sleepy_device(hass: HomeAssistant) -> None: assert await hass.config_entries.async_unload(entry.entry_id) await hass.async_block_till_done() + + assert entry.data[CONF_SLEEPY_DEVICE] is True