From 28bebf338fd1aca55c5ebcfc3dd31273c419e5cf Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 31 Jul 2023 01:02:36 -0700 Subject: [PATCH] Fix xiaomi_ble not remembering a device is a sleepy device (#97518) --- homeassistant/components/xiaomi_ble/__init__.py | 7 +++++++ homeassistant/components/xiaomi_ble/binary_sensor.py | 5 +---- homeassistant/components/xiaomi_ble/const.py | 1 + homeassistant/components/xiaomi_ble/coordinator.py | 10 ++++++++++ homeassistant/components/xiaomi_ble/sensor.py | 5 +---- tests/components/xiaomi_ble/test_binary_sensor.py | 6 +++++- 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/xiaomi_ble/__init__.py b/homeassistant/components/xiaomi_ble/__init__.py index 1810d52323cb54..b12f4df7db1c52 100644 --- a/homeassistant/components/xiaomi_ble/__init__.py +++ b/homeassistant/components/xiaomi_ble/__init__.py @@ -19,6 +19,7 @@ from .const import ( CONF_DISCOVERED_EVENT_CLASSES, + CONF_SLEEPY_DEVICE, DOMAIN, XIAOMI_BLE_EVENT, XiaomiBleEvent, @@ -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(): @@ -157,6 +163,7 @@ async def _async_poll(service_info: BluetoothServiceInfoBleak): # since we will trade the BLEDevice for a connectable one # if we need to poll it connectable=False, + entry=entry, ) await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) entry.async_on_unload( diff --git a/homeassistant/components/xiaomi_ble/binary_sensor.py b/homeassistant/components/xiaomi_ble/binary_sensor.py index f7c4c87014c97b..5ff418fe831b37 100644 --- a/homeassistant/components/xiaomi_ble/binary_sensor.py +++ b/homeassistant/components/xiaomi_ble/binary_sensor.py @@ -136,7 +136,4 @@ def is_on(self) -> bool | None: @property def available(self) -> bool: """Return True if entity is available.""" - coordinator: XiaomiActiveBluetoothProcessorCoordinator = ( - 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/xiaomi_ble/const.py b/homeassistant/components/xiaomi_ble/const.py index 1566478bcea689..346d8a613184e8 100644 --- a/homeassistant/components/xiaomi_ble/const.py +++ b/homeassistant/components/xiaomi_ble/const.py @@ -7,6 +7,7 @@ CONF_DISCOVERED_EVENT_CLASSES: Final = "known_events" +CONF_SLEEPY_DEVICE: Final = "sleepy_device" CONF_EVENT_PROPERTIES: Final = "event_properties" EVENT_PROPERTIES: Final = "event_properties" EVENT_TYPE: Final = "event_type" diff --git a/homeassistant/components/xiaomi_ble/coordinator.py b/homeassistant/components/xiaomi_ble/coordinator.py index 2a4b35f61719e0..94e70ca9835d58 100644 --- a/homeassistant/components/xiaomi_ble/coordinator.py +++ b/homeassistant/components/xiaomi_ble/coordinator.py @@ -15,9 +15,12 @@ from homeassistant.components.bluetooth.passive_update_processor import ( PassiveBluetoothDataProcessor, ) +from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.debounce import Debouncer +from .const import CONF_SLEEPY_DEVICE + class XiaomiActiveBluetoothProcessorCoordinator(ActiveBluetoothProcessorCoordinator): """Define a Xiaomi Bluetooth Active Update Processor Coordinator.""" @@ -39,6 +42,7 @@ def __init__( ] | None = None, poll_debouncer: Debouncer[Coroutine[Any, Any, None]] | None = None, + entry: ConfigEntry, connectable: bool = True, ) -> None: """Initialize the Xiaomi Bluetooth Active Update Processor Coordinator.""" @@ -55,6 +59,12 @@ def __init__( ) 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 XiaomiPassiveBluetoothDataProcessor(PassiveBluetoothDataProcessor): diff --git a/homeassistant/components/xiaomi_ble/sensor.py b/homeassistant/components/xiaomi_ble/sensor.py index f0f0d7fa71e174..86ffdedafd1a35 100644 --- a/homeassistant/components/xiaomi_ble/sensor.py +++ b/homeassistant/components/xiaomi_ble/sensor.py @@ -200,7 +200,4 @@ def native_value(self) -> int | float | None: @property def available(self) -> bool: """Return True if entity is available.""" - coordinator: XiaomiActiveBluetoothProcessorCoordinator = ( - 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/xiaomi_ble/test_binary_sensor.py b/tests/components/xiaomi_ble/test_binary_sensor.py index 424f6e22b26dd6..5dd1b965f25959 100644 --- a/tests/components/xiaomi_ble/test_binary_sensor.py +++ b/tests/components/xiaomi_ble/test_binary_sensor.py @@ -7,7 +7,7 @@ from homeassistant.components.bluetooth import ( FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS, ) -from homeassistant.components.xiaomi_ble.const import DOMAIN +from homeassistant.components.xiaomi_ble.const import CONF_SLEEPY_DEVICE, DOMAIN from homeassistant.const import ( ATTR_FRIENDLY_NAME, STATE_OFF, @@ -313,6 +313,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.""" @@ -363,3 +365,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