Delete removed device(s) at runtime in Plugwise (#120296)

pull/120571/head
Bouwe Westerdijk 2024-06-26 16:08:32 +02:00 committed by GitHub
parent 55101fcc45
commit 32c07180f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 71 additions and 4 deletions

View File

@ -16,11 +16,12 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryError
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.debounce import Debouncer
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import DEFAULT_PORT, DEFAULT_USERNAME, DOMAIN, LOGGER
from .const import DEFAULT_PORT, DEFAULT_USERNAME, DOMAIN, GATEWAY_ID, LOGGER
class PlugwiseDataUpdateCoordinator(DataUpdateCoordinator[PlugwiseData]):
@ -83,7 +84,46 @@ class PlugwiseDataUpdateCoordinator(DataUpdateCoordinator[PlugwiseData]):
except UnsupportedDeviceError as err:
raise ConfigEntryError("Device with unsupported firmware") from err
else:
self.new_devices = set(data.devices) - self._current_devices
self._current_devices = set(data.devices)
self._async_add_remove_devices(data, self.config_entry)
return data
def _async_add_remove_devices(self, data: PlugwiseData, entry: ConfigEntry) -> None:
"""Add new Plugwise devices, remove non-existing devices."""
# Check for new or removed devices
self.new_devices = set(data.devices) - self._current_devices
removed_devices = self._current_devices - set(data.devices)
self._current_devices = set(data.devices)
if removed_devices:
self._async_remove_devices(data, entry)
def _async_remove_devices(self, data: PlugwiseData, entry: ConfigEntry) -> None:
"""Clean registries when removed devices found."""
device_reg = dr.async_get(self.hass)
device_list = dr.async_entries_for_config_entry(
device_reg, self.config_entry.entry_id
)
# via_device cannot be None, this will result in the deletion
# of other Plugwise Gateways when present!
via_device: str = ""
for device_entry in device_list:
if device_entry.identifiers:
item = list(list(device_entry.identifiers)[0])
if item[0] == DOMAIN:
# First find the Plugwise via_device, this is always the first device
if item[1] == data.gateway[GATEWAY_ID]:
via_device = device_entry.id
elif ( # then remove the connected orphaned device(s)
device_entry.via_device_id == via_device
and item[1] not in data.devices
):
device_reg.async_update_device(
device_entry.id, remove_config_entry_id=entry.entry_id
)
LOGGER.debug(
"Removed %s device %s %s from device_registry",
DOMAIN,
device_entry.model,
item[1],
)

View File

@ -39,7 +39,7 @@ TOM = {
"hardware": "1",
"location": "f871b8c4d63549319221e294e4f88074",
"model": "Tom/Floor",
"name": "Tom Badkamer",
"name": "Tom Zolder",
"sensors": {
"battery": 99,
"temperature": 18.6,
@ -258,3 +258,30 @@ async def test_update_device(
for device_entry in list(device_registry.devices.values()):
item_list.extend(x[1] for x in device_entry.identifiers)
assert "01234567890abcdefghijklmnopqrstu" in item_list
# Remove the existing Tom/Floor
data.devices.pop("1772a4ea304041adb83f357b751341ff")
with patch(HA_PLUGWISE_SMILE_ASYNC_UPDATE, return_value=data):
async_fire_time_changed(hass, utcnow + timedelta(minutes=1))
await hass.async_block_till_done()
assert (
len(
er.async_entries_for_config_entry(
entity_registry, mock_config_entry.entry_id
)
)
== 29
)
assert (
len(
dr.async_entries_for_config_entry(
device_registry, mock_config_entry.entry_id
)
)
== 6
)
item_list: list[str] = []
for device_entry in list(device_registry.devices.values()):
item_list.extend(x[1] for x in device_entry.identifiers)
assert "1772a4ea304041adb83f357b751341ff" not in item_list