Clean up device registry for climate devices that no longer exist in Honeywell (#100072)

This commit is contained in:
mkmer 2023-09-12 14:29:47 -04:00 committed by GitHub
parent 9672cdf3a9
commit 693a271e40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 84 additions and 3 deletions

View File

@ -28,6 +28,7 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_TEMPERATURE, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -97,6 +98,37 @@ async def async_setup_entry(
for device in data.devices.values()
]
)
remove_stale_devices(hass, entry, data.devices)
def remove_stale_devices(
hass: HomeAssistant,
config_entry: ConfigEntry,
devices: dict[str, SomeComfortDevice],
) -> None:
"""Remove stale devices from device registry."""
device_registry = dr.async_get(hass)
device_entries = dr.async_entries_for_config_entry(
device_registry, config_entry.entry_id
)
all_device_ids: list = []
for device in devices.values():
all_device_ids.append(device.deviceid)
for device_entry in device_entries:
device_id: str | None = None
for identifier in device_entry.identifiers:
device_id = identifier[1]
break
if device_id is None or device_id not in all_device_ids:
# If device_id is None an invalid device entry was found for this config entry.
# If the device_id is not in existing device ids it's a stale device entry.
# Remove config entry from this device entry in either case.
device_registry.async_update_device(
device_entry.id, remove_config_entry_id=config_entry.entry_id
)
class HoneywellUSThermostat(ClimateEntity):

View File

@ -12,6 +12,7 @@ from homeassistant.components.honeywell.const import (
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from . import init_integration
@ -33,7 +34,10 @@ async def test_setup_entry(hass: HomeAssistant, config_entry: MockConfigEntry) -
async def test_setup_multiple_thermostats(
hass: HomeAssistant, config_entry: MockConfigEntry, location, another_device
hass: HomeAssistant,
config_entry: MockConfigEntry,
location: MagicMock,
another_device: MagicMock,
) -> None:
"""Test that the config form is shown."""
location.devices_by_id[another_device.deviceid] = another_device
@ -50,8 +54,8 @@ async def test_setup_multiple_thermostats_with_same_deviceid(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
config_entry: MockConfigEntry,
device,
client,
device: MagicMock,
client: MagicMock,
) -> None:
"""Test Honeywell TCC API returning duplicate device IDs."""
mock_location2 = create_autospec(aiosomecomfort.Location, instance=True)
@ -115,3 +119,48 @@ async def test_no_devices(
client.locations_by_id = {}
await init_integration(hass, config_entry)
assert config_entry.state is ConfigEntryState.SETUP_ERROR
async def test_remove_stale_device(
hass: HomeAssistant,
config_entry: MockConfigEntry,
location: MagicMock,
another_device: MagicMock,
client: MagicMock,
) -> None:
"""Test that the stale device is removed."""
location.devices_by_id[another_device.deviceid] = another_device
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.LOADED
assert (
hass.states.async_entity_ids_count() == 6
) # 2 climate entities; 4 sensor entities
device_registry = dr.async_get(hass)
device_entry = dr.async_entries_for_config_entry(
device_registry, config_entry.entry_id
)
assert len(device_entry) == 2
assert any((DOMAIN, 1234567) in device.identifiers for device in device_entry)
assert any((DOMAIN, 7654321) in device.identifiers for device in device_entry)
assert await config_entry.async_unload(hass)
await hass.async_block_till_done()
assert config_entry.state == ConfigEntryState.NOT_LOADED
del location.devices_by_id[another_device.deviceid]
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.LOADED
assert (
hass.states.async_entity_ids_count() == 3
) # 1 climate entities; 2 sensor entities
device_entry = dr.async_entries_for_config_entry(
device_registry, config_entry.entry_id
)
assert len(device_entry) == 1
assert any((DOMAIN, 1234567) in device.identifiers for device in device_entry)