|
24 | 24 | from homeassistant.helpers import device_registry as dr |
25 | 25 | from homeassistant.helpers.aiohttp_client import async_get_clientsession |
26 | 26 | from homeassistant.helpers.debounce import Debouncer |
27 | | -from homeassistant.helpers.device_registry import DeviceEntry, DeviceRegistry |
28 | 27 | from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed |
29 | 28 |
|
30 | 29 | from .const import ( |
|
37 | 36 | ) |
38 | 37 |
|
39 | 38 |
|
40 | | -async def cleanup_device_and_entity_registry( |
41 | | - data: PlugwiseData, |
42 | | - device_reg: DeviceRegistry, |
43 | | - device_list: list[DeviceEntry], |
44 | | - entry: ConfigEntry, |
45 | | -) -> None: |
46 | | - """Remove deleted devices from device- and entity-registry.""" |
47 | | - if len(device_list) - len(data.devices.keys()) <= 0: |
48 | | - return |
49 | | - |
50 | | - # via_device cannot be None, this will result in the deletion |
51 | | - # of other Plugwise Gateways when present! |
52 | | - via_device: str = "" |
53 | | - for device_entry in device_list: |
54 | | - if not device_entry.identifiers: |
55 | | - continue # pragma: no cover |
56 | | - |
57 | | - item = list(list(device_entry.identifiers)[0]) |
58 | | - if item[0] != DOMAIN: |
59 | | - continue # pragma: no cover |
60 | | - |
61 | | - # First find the Plugwise via_device, this is always the first device |
62 | | - if item[1] == data.gateway[GATEWAY_ID]: |
63 | | - via_device = device_entry.id |
64 | | - elif ( # then remove the connected orphaned device(s) |
65 | | - device_entry.via_device_id == via_device |
66 | | - and item[1] not in list(data.devices.keys()) |
67 | | - ): |
68 | | - device_reg.async_update_device( |
69 | | - device_entry.id, remove_config_entry_id=entry.entry_id |
70 | | - ) |
71 | | - LOGGER.debug( |
72 | | - "Removed %s device %s %s from device_registry", |
73 | | - DOMAIN, |
74 | | - device_entry.model, |
75 | | - item[1], |
76 | | - ) |
77 | | - |
78 | | - |
79 | 39 | class PlugwiseDataUpdateCoordinator(DataUpdateCoordinator[PlugwiseData]): |
80 | 40 | """Class to manage fetching Plugwise data from single endpoint.""" |
81 | 41 |
|
@@ -114,9 +74,8 @@ def __init__( |
114 | 74 | timeout=30, |
115 | 75 | websession=async_get_clientsession(hass, verify_ssl=False), |
116 | 76 | ) |
117 | | - self._unavailable_logged = False |
118 | | - self.device_list: list[DeviceEntry] = [] |
119 | | - self.new_devices: bool = False |
| 77 | + self._current_devices: set[str] = set() |
| 78 | + self.new_devices: set[str] = set() |
120 | 79 | self.update_interval = update_interval |
121 | 80 |
|
122 | 81 | async def _connect(self) -> None: |
@@ -155,17 +114,46 @@ async def _async_update_data(self) -> PlugwiseData: |
155 | 114 | raise ConfigEntryError("Device with unsupported firmware") from err |
156 | 115 | else: |
157 | 116 | LOGGER.debug(f"{self.api.smile_name} data: %s", data) |
158 | | - device_reg = dr.async_get(self.hass) |
159 | | - device_list = dr.async_entries_for_config_entry( |
160 | | - device_reg, self.config_entry.entry_id |
161 | | - ) |
162 | | - await cleanup_device_and_entity_registry( |
163 | | - data, |
164 | | - device_reg, |
165 | | - device_list, |
166 | | - self.config_entry |
167 | | - ) |
168 | | - self.new_devices = len(data.devices.keys()) - len(self.device_list) > 0 |
169 | | - self.device_list = device_list |
| 117 | + self._async_add_remove_devices(data, self.config_entry) |
170 | 118 |
|
171 | 119 | return data |
| 120 | + |
| 121 | + def _async_add_remove_devices(self, data: PlugwiseData, entry: ConfigEntry) -> None: |
| 122 | + """Add new Plugwise devices, remove non-existing devices.""" |
| 123 | + # Check for new or removed devices |
| 124 | + self.new_devices = set(data.devices) - self._current_devices |
| 125 | + removed_devices = self._current_devices - set(data.devices) |
| 126 | + self._current_devices = set(data.devices) |
| 127 | + |
| 128 | + if removed_devices: |
| 129 | + self._async_remove_devices(data, entry) |
| 130 | + |
| 131 | + def _async_remove_devices(self, data: PlugwiseData, entry: ConfigEntry) -> None: |
| 132 | + """Clean registries when removed devices found.""" |
| 133 | + device_reg = dr.async_get(self.hass) |
| 134 | + device_list = dr.async_entries_for_config_entry( |
| 135 | + device_reg, self.config_entry.entry_id |
| 136 | + ) |
| 137 | + # via_device cannot be None, this will result in the deletion |
| 138 | + # of other Plugwise Gateways when present! |
| 139 | + via_device: str = "" |
| 140 | + for device_entry in device_list: |
| 141 | + if device_entry.identifiers: |
| 142 | + item = list(list(device_entry.identifiers)[0]) |
| 143 | + if item[0] == DOMAIN: |
| 144 | + # First find the Plugwise via_device, this is always the first device |
| 145 | + if item[1] == data.gateway[GATEWAY_ID]: |
| 146 | + via_device = device_entry.id |
| 147 | + elif ( # then remove the connected orphaned device(s) |
| 148 | + device_entry.via_device_id == via_device |
| 149 | + and item[1] not in list(data.devices.keys()) |
| 150 | + ): |
| 151 | + device_reg.async_update_device( |
| 152 | + device_entry.id, remove_config_entry_id=entry.entry_id |
| 153 | + ) |
| 154 | + LOGGER.debug( |
| 155 | + "Removed %s device %s %s from device_registry", |
| 156 | + DOMAIN, |
| 157 | + device_entry.model, |
| 158 | + item[1], |
| 159 | + ) |
0 commit comments