Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions homeassistant/helpers/device_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,17 +399,25 @@ def async_cleanup(
ent_reg: "entity_registry.EntityRegistry",
) -> None:
"""Clean up device registry."""
# Find all devices that are no longer referenced in the entity registry.
referenced = {entry.device_id for entry in ent_reg.entities.values()}
orphan = set(dev_reg.devices) - referenced
# Find all devices that are referenced by a config_entry.
config_entry_ids = {entry.entry_id for entry in hass.config_entries.async_entries()}
references_config_entries = {
device.id
for device in dev_reg.devices.values()
for config_entry_id in device.config_entries
if config_entry_id in config_entry_ids
}

# Find all devices that are referenced in the entity registry.
references_entities = {entry.device_id for entry in ent_reg.entities.values()}

orphan = set(dev_reg.devices) - references_entities - references_config_entries

for dev_id in orphan:
dev_reg.async_remove_device(dev_id)

# Find all referenced config entries that no longer exist
# This shouldn't happen but have not been able to track down the bug :(
config_entry_ids = {entry.entry_id for entry in hass.config_entries.async_entries()}

for device in list(dev_reg.devices.values()):
for config_entry_id in device.config_entries:
if config_entry_id not in config_entry_ids:
Expand Down
2 changes: 1 addition & 1 deletion tests/helpers/test_device_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ async def test_cleanup_device_registry(hass, registry):
device_registry.async_cleanup(hass, registry, ent_reg)

assert registry.async_get_device({("hue", "d1")}, set()) is not None
assert registry.async_get_device({("hue", "d2")}, set()) is None
assert registry.async_get_device({("hue", "d2")}, set()) is not None
assert registry.async_get_device({("hue", "d3")}, set()) is not None
assert registry.async_get_device({("something", "d4")}, set()) is None

Expand Down