Track devolo Home Network Wi-Fi clients via the entity registry (#182327)

This commit is contained in:
Guido Schmitz
2026-09-19 11:25:53 +02:00
committed by GitHub
parent fee52805ab
commit 2329db5a05
2 changed files with 41 additions and 33 deletions
@@ -32,47 +32,30 @@ async def async_setup_entry(
str, DevoloDataUpdateCoordinator[dict[str, ConnectedStationInfo]]
] = entry.runtime_data.coordinators
registry = er.async_get(hass)
tracked = set()
@callback
def new_device_callback() -> None:
"""Add new devices if needed."""
new_entities = []
for mac_address in coordinators[CONNECTED_WIFI_CLIENTS].data:
if mac_address in tracked:
continue
new_entities.append(
DevoloScannerEntity(
coordinators[CONNECTED_WIFI_CLIENTS], device, mac_address
)
"""Add clients that don't have an entity yet."""
async_add_entities(
DevoloScannerEntity(coordinators[CONNECTED_WIFI_CLIENTS], device, mac)
for mac in coordinators[CONNECTED_WIFI_CLIENTS].data
if not registry.async_get_entity_id(
DEVICE_TRACKER_DOMAIN, DOMAIN, f"{device.serial_number}_{mac}"
)
tracked.add(mac_address)
async_add_entities(new_entities)
)
@callback
def restore_entities() -> None:
"""Restore clients that are not a part of active clients list."""
missing = []
for entity in er.async_entries_for_config_entry(registry, entry.entry_id):
if (
entity.platform == DOMAIN
and entity.domain == DEVICE_TRACKER_DOMAIN
and (
mac_address := entity.unique_id.replace(
f"{device.serial_number}_", ""
)
)
not in tracked
):
missing.append(
DevoloScannerEntity(
coordinators[CONNECTED_WIFI_CLIENTS], device, mac_address
)
)
tracked.add(mac_address)
async_add_entities(missing)
async_add_entities(
DevoloScannerEntity(
coordinators[CONNECTED_WIFI_CLIENTS],
device,
entity.unique_id.removeprefix(f"{device.serial_number}_"),
)
for entity in er.async_entries_for_config_entry(registry, entry.entry_id)
if entity.platform == DOMAIN and entity.domain == DEVICE_TRACKER_DOMAIN
)
restore_entities()
new_device_callback()
@@ -95,3 +95,28 @@ async def test_restoring_clients(
state = hass.states.get(entity_id)
assert state is not None
assert state.state == STATE_NOT_HOME
@pytest.mark.usefixtures("mock_device", "entity_registry_enabled_by_default")
async def test_recreating_removed_entity(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test that the entity registry is the source of truth for tracked clients."""
entity_id = (
f"{DEVICE_TRACKER_DOMAIN}.{STATION.mac_address.lower().replace(':', '_')}"
)
entry = configure_integration(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert entity_registry.async_get(entity_id) is not None
entity_registry.async_remove(entity_id)
await hass.async_block_till_done()
assert entity_registry.async_get(entity_id) is None
freezer.tick(SHORT_UPDATE_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert entity_registry.async_get(entity_id) is not None