Reolink fix dev/entity id migration (#130836)
parent
039df1070e
commit
a379535127
|
@ -326,7 +326,19 @@ def migrate_entity_ids(
|
||||||
else:
|
else:
|
||||||
new_device_id = f"{device_uid[0]}_{host.api.camera_uid(ch)}"
|
new_device_id = f"{device_uid[0]}_{host.api.camera_uid(ch)}"
|
||||||
new_identifiers = {(DOMAIN, new_device_id)}
|
new_identifiers = {(DOMAIN, new_device_id)}
|
||||||
device_reg.async_update_device(device.id, new_identifiers=new_identifiers)
|
existing_device = device_reg.async_get_device(identifiers=new_identifiers)
|
||||||
|
if existing_device is None:
|
||||||
|
device_reg.async_update_device(
|
||||||
|
device.id, new_identifiers=new_identifiers
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Reolink device with uid %s already exists, "
|
||||||
|
"removing device with uid %s",
|
||||||
|
new_device_id,
|
||||||
|
device_uid,
|
||||||
|
)
|
||||||
|
device_reg.async_remove_device(device.id)
|
||||||
|
|
||||||
entity_reg = er.async_get(hass)
|
entity_reg = er.async_get(hass)
|
||||||
entities = er.async_entries_for_config_entry(entity_reg, config_entry_id)
|
entities = er.async_entries_for_config_entry(entity_reg, config_entry_id)
|
||||||
|
@ -352,4 +364,18 @@ def migrate_entity_ids(
|
||||||
id_parts = entity.unique_id.split("_", 2)
|
id_parts = entity.unique_id.split("_", 2)
|
||||||
if host.api.supported(ch, "UID") and id_parts[1] != host.api.camera_uid(ch):
|
if host.api.supported(ch, "UID") and id_parts[1] != host.api.camera_uid(ch):
|
||||||
new_id = f"{host.unique_id}_{host.api.camera_uid(ch)}_{id_parts[2]}"
|
new_id = f"{host.unique_id}_{host.api.camera_uid(ch)}_{id_parts[2]}"
|
||||||
entity_reg.async_update_entity(entity.entity_id, new_unique_id=new_id)
|
existing_entity = entity_reg.async_get_entity_id(
|
||||||
|
entity.domain, entity.platform, new_id
|
||||||
|
)
|
||||||
|
if existing_entity is None:
|
||||||
|
entity_reg.async_update_entity(
|
||||||
|
entity.entity_id, new_unique_id=new_id
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Reolink entity with unique_id %s already exists, "
|
||||||
|
"removing device with unique_id %s",
|
||||||
|
new_id,
|
||||||
|
entity.unique_id,
|
||||||
|
)
|
||||||
|
entity_reg.async_remove(entity.entity_id)
|
||||||
|
|
|
@ -469,6 +469,116 @@ async def test_migrate_entity_ids(
|
||||||
assert device_registry.async_get_device(identifiers={(DOMAIN, new_dev_id)})
|
assert device_registry.async_get_device(identifiers={(DOMAIN, new_dev_id)})
|
||||||
|
|
||||||
|
|
||||||
|
async def test_migrate_with_already_existing_device(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
reolink_connect: MagicMock,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
device_registry: dr.DeviceRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test device ids that need to be migrated while the new ids already exist."""
|
||||||
|
original_dev_id = f"{TEST_MAC}_ch0"
|
||||||
|
new_dev_id = f"{TEST_UID}_{TEST_UID_CAM}"
|
||||||
|
domain = Platform.SWITCH
|
||||||
|
|
||||||
|
def mock_supported(ch, capability):
|
||||||
|
if capability == "UID" and ch is None:
|
||||||
|
return True
|
||||||
|
if capability == "UID":
|
||||||
|
return True
|
||||||
|
return True
|
||||||
|
|
||||||
|
reolink_connect.channels = [0]
|
||||||
|
reolink_connect.supported = mock_supported
|
||||||
|
|
||||||
|
device_registry.async_get_or_create(
|
||||||
|
identifiers={(DOMAIN, new_dev_id)},
|
||||||
|
config_entry_id=config_entry.entry_id,
|
||||||
|
disabled_by=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
device_registry.async_get_or_create(
|
||||||
|
identifiers={(DOMAIN, original_dev_id)},
|
||||||
|
config_entry_id=config_entry.entry_id,
|
||||||
|
disabled_by=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert device_registry.async_get_device(identifiers={(DOMAIN, original_dev_id)})
|
||||||
|
assert device_registry.async_get_device(identifiers={(DOMAIN, new_dev_id)})
|
||||||
|
|
||||||
|
# setup CH 0 and host entities/device
|
||||||
|
with patch("homeassistant.components.reolink.PLATFORMS", [domain]):
|
||||||
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert (
|
||||||
|
device_registry.async_get_device(identifiers={(DOMAIN, original_dev_id)})
|
||||||
|
is None
|
||||||
|
)
|
||||||
|
assert device_registry.async_get_device(identifiers={(DOMAIN, new_dev_id)})
|
||||||
|
|
||||||
|
|
||||||
|
async def test_migrate_with_already_existing_entity(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
reolink_connect: MagicMock,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
device_registry: dr.DeviceRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test entity ids that need to be migrated while the new ids already exist."""
|
||||||
|
original_id = f"{TEST_UID}_0_record_audio"
|
||||||
|
new_id = f"{TEST_UID}_{TEST_UID_CAM}_record_audio"
|
||||||
|
dev_id = f"{TEST_UID}_{TEST_UID_CAM}"
|
||||||
|
domain = Platform.SWITCH
|
||||||
|
|
||||||
|
def mock_supported(ch, capability):
|
||||||
|
if capability == "UID" and ch is None:
|
||||||
|
return True
|
||||||
|
if capability == "UID":
|
||||||
|
return True
|
||||||
|
return True
|
||||||
|
|
||||||
|
reolink_connect.channels = [0]
|
||||||
|
reolink_connect.supported = mock_supported
|
||||||
|
|
||||||
|
dev_entry = device_registry.async_get_or_create(
|
||||||
|
identifiers={(DOMAIN, dev_id)},
|
||||||
|
config_entry_id=config_entry.entry_id,
|
||||||
|
disabled_by=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
entity_registry.async_get_or_create(
|
||||||
|
domain=domain,
|
||||||
|
platform=DOMAIN,
|
||||||
|
unique_id=new_id,
|
||||||
|
config_entry=config_entry,
|
||||||
|
suggested_object_id=new_id,
|
||||||
|
disabled_by=None,
|
||||||
|
device_id=dev_entry.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
entity_registry.async_get_or_create(
|
||||||
|
domain=domain,
|
||||||
|
platform=DOMAIN,
|
||||||
|
unique_id=original_id,
|
||||||
|
config_entry=config_entry,
|
||||||
|
suggested_object_id=original_id,
|
||||||
|
disabled_by=None,
|
||||||
|
device_id=dev_entry.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert entity_registry.async_get_entity_id(domain, DOMAIN, original_id)
|
||||||
|
assert entity_registry.async_get_entity_id(domain, DOMAIN, new_id)
|
||||||
|
|
||||||
|
# setup CH 0 and host entities/device
|
||||||
|
with patch("homeassistant.components.reolink.PLATFORMS", [domain]):
|
||||||
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert entity_registry.async_get_entity_id(domain, DOMAIN, original_id) is None
|
||||||
|
assert entity_registry.async_get_entity_id(domain, DOMAIN, new_id)
|
||||||
|
|
||||||
|
|
||||||
async def test_no_repair_issue(
|
async def test_no_repair_issue(
|
||||||
hass: HomeAssistant, config_entry: MockConfigEntry, issue_registry: ir.IssueRegistry
|
hass: HomeAssistant, config_entry: MockConfigEntry, issue_registry: ir.IssueRegistry
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
Loading…
Reference in New Issue