From fda66c4be4ac3de9c9c94521a5942265ad079941 Mon Sep 17 00:00:00 2001 From: Guido Schmitz Date: Fri, 27 Jun 2025 09:52:00 +0200 Subject: [PATCH] Handle deleted devices dynamically in devolo Home Control (#147585) --- .../components/devolo_home_control/entity.py | 14 ++++++++++++-- .../devolo_home_control/test_binary_sensor.py | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/devolo_home_control/entity.py b/homeassistant/components/devolo_home_control/entity.py index dbe53c21412..9edc7d54145 100644 --- a/homeassistant/components/devolo_home_control/entity.py +++ b/homeassistant/components/devolo_home_control/entity.py @@ -9,7 +9,7 @@ from devolo_home_control_api.devices.zwave import Zwave from devolo_home_control_api.homecontrol import HomeControl from homeassistant.components.sensor import SensorDeviceClass -from homeassistant.helpers.device_registry import DeviceInfo +from homeassistant.helpers import device_registry as dr from homeassistant.helpers.entity import Entity from .const import DOMAIN @@ -35,7 +35,7 @@ class DevoloDeviceEntity(Entity): ) # This is not doing I/O. It fetches an internal state of the API self._attr_should_poll = False self._attr_unique_id = element_uid - self._attr_device_info = DeviceInfo( + self._attr_device_info = dr.DeviceInfo( configuration_url=f"https://{urlparse(device_instance.href).netloc}", identifiers={(DOMAIN, self._device_instance.uid)}, manufacturer=device_instance.brand, @@ -88,6 +88,16 @@ class DevoloDeviceEntity(Entity): elif len(message) == 3 and message[2] == "status": # Maybe the API wants to tell us, that the device went on- or offline. self._attr_available = self._device_instance.is_online() + elif message[1] == "del" and self.platform.config_entry: + device_registry = dr.async_get(self.hass) + device = device_registry.async_get_device( + identifiers={(DOMAIN, self._device_instance.uid)} + ) + if device: + device_registry.async_update_device( + device.id, + remove_config_entry_id=self.platform.config_entry.entry_id, + ) else: _LOGGER.debug("No valid message received: %s", message) diff --git a/tests/components/devolo_home_control/test_binary_sensor.py b/tests/components/devolo_home_control/test_binary_sensor.py index b2a58ef5038..657e93a5b90 100644 --- a/tests/components/devolo_home_control/test_binary_sensor.py +++ b/tests/components/devolo_home_control/test_binary_sensor.py @@ -5,9 +5,10 @@ from unittest.mock import patch from syrupy.assertion import SnapshotAssertion from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN +from homeassistant.components.devolo_home_control.const import DOMAIN from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE from homeassistant.core import HomeAssistant -from homeassistant.helpers import entity_registry as er +from homeassistant.helpers import device_registry as dr, entity_registry as er from . import configure_integration from .mocks import ( @@ -19,7 +20,10 @@ from .mocks import ( async def test_binary_sensor( - hass: HomeAssistant, entity_registry: er.EntityRegistry, snapshot: SnapshotAssertion + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + device_registry: dr.DeviceRegistry, + snapshot: SnapshotAssertion, ) -> None: """Test setup and state change of a binary sensor device.""" entry = configure_integration(hass) @@ -55,6 +59,12 @@ async def test_binary_sensor( hass.states.get(f"{BINARY_SENSOR_DOMAIN}.test_door").state == STATE_UNAVAILABLE ) + # Emulate websocket message: device was deleted + test_gateway.publisher.dispatch("Test", ("Test", "del")) + await hass.async_block_till_done() + device = device_registry.async_get_device(identifiers={(DOMAIN, "Test")}) + assert not device + async def test_remote_control( hass: HomeAssistant, entity_registry: er.EntityRegistry, snapshot: SnapshotAssertion