Remove old BMW vehicles/devices automatically (#110255)

* Remove not assigned vehicles from DeviceRegistry on startup

* Replace async_remove_device with async_update_device

* Add test

* Use generator

---------

Co-authored-by: Richard <rikroe@users.noreply.github.com>
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
Richard Kroegel 2024-02-12 10:52:08 +01:00 committed by GitHub
parent 12709050ea
commit 1b8bda6067
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 55 additions and 2 deletions

View file

@ -10,7 +10,11 @@ import voluptuous as vol
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DEVICE_ID, CONF_ENTITY_ID, CONF_NAME, Platform
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import discovery, entity_registry as er
from homeassistant.helpers import (
device_registry as dr,
discovery,
entity_registry as er,
)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.typing import ConfigType
@ -146,6 +150,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
)
)
# Clean up vehicles which are not assigned to the account anymore
account_vehicles = {(DOMAIN, v.vin) for v in coordinator.account.vehicles}
device_registry = dr.async_get(hass)
device_entries = dr.async_entries_for_config_entry(
device_registry, config_entry_id=entry.entry_id
)
for device in device_entries:
if not device.identifiers.intersection(account_vehicles):
device_registry.async_update_device(
device.id, remove_config_entry_id=entry.entry_id
)
return True

View file

@ -2,11 +2,12 @@
from unittest.mock import patch
import pytest
import respx
from homeassistant.components.bmw_connected_drive.const import DOMAIN as BMW_DOMAIN
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
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 FIXTURE_CONFIG_ENTRY
@ -133,3 +134,39 @@ async def test_dont_migrate_unique_ids(
assert entity_not_changed.unique_id == new_unique_id
assert entity_migrated != entity_not_changed
async def test_remove_stale_devices(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
bmw_fixture: respx.Router,
) -> None:
"""Test remove stale device registry entries."""
mock_config_entry = MockConfigEntry(**FIXTURE_CONFIG_ENTRY)
mock_config_entry.add_to_hass(hass)
device_registry.async_get_or_create(
config_entry_id=mock_config_entry.entry_id,
identifiers={(BMW_DOMAIN, "stale_device_id")},
)
device_entries = dr.async_entries_for_config_entry(
device_registry, mock_config_entry.entry_id
)
assert len(device_entries) == 1
device_entry = device_entries[0]
assert device_entry.identifiers == {(BMW_DOMAIN, "stale_device_id")}
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
device_entries = dr.async_entries_for_config_entry(
device_registry, mock_config_entry.entry_id
)
# Check that the test vehicles are still available but not the stale device
assert len(device_entries) > 0
remaining_device_identifiers = set().union(*(d.identifiers for d in device_entries))
assert not {(BMW_DOMAIN, "stale_device_id")}.intersection(
remaining_device_identifiers
)