Also migrate dsmr entries for devices with correct serial (#123407)

dsmr: also migrate entries for devices with correct serial

When the dsmr code could not find the serial_nr for the gas meter,
it creates the gas meter device with the entry_id as identifier.

But when there is a correct serial_nr, it will use that as identifier
for the dsmr gas device.

Now the migration code did not take this into account, so migration to
the new name failed since it didn't look for the device with correct
serial_nr.

This commit fixes this and adds a test for this.
This commit is contained in:
dupondje 2024-08-10 10:40:11 +02:00 committed by GitHub
parent 94af95c95b
commit 750bce2b86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 129 additions and 33 deletions

View File

@ -431,41 +431,42 @@ def rename_old_gas_to_mbus(
) -> None: ) -> None:
"""Rename old gas sensor to mbus variant.""" """Rename old gas sensor to mbus variant."""
dev_reg = dr.async_get(hass) dev_reg = dr.async_get(hass)
device_entry_v1 = dev_reg.async_get_device(identifiers={(DOMAIN, entry.entry_id)}) for dev_id in (mbus_device_id, entry.entry_id):
if device_entry_v1 is not None: device_entry_v1 = dev_reg.async_get_device(identifiers={(DOMAIN, dev_id)})
device_id = device_entry_v1.id if device_entry_v1 is not None:
device_id = device_entry_v1.id
ent_reg = er.async_get(hass) ent_reg = er.async_get(hass)
entries = er.async_entries_for_device(ent_reg, device_id) entries = er.async_entries_for_device(ent_reg, device_id)
for entity in entries: for entity in entries:
if entity.unique_id.endswith( if entity.unique_id.endswith(
"belgium_5min_gas_meter_reading" "belgium_5min_gas_meter_reading"
) or entity.unique_id.endswith("hourly_gas_meter_reading"): ) or entity.unique_id.endswith("hourly_gas_meter_reading"):
try: try:
ent_reg.async_update_entity( ent_reg.async_update_entity(
entity.entity_id, entity.entity_id,
new_unique_id=mbus_device_id, new_unique_id=mbus_device_id,
device_id=mbus_device_id, device_id=mbus_device_id,
) )
except ValueError: except ValueError:
LOGGER.debug( LOGGER.debug(
"Skip migration of %s because it already exists", "Skip migration of %s because it already exists",
entity.entity_id, entity.entity_id,
) )
else: else:
LOGGER.debug( LOGGER.debug(
"Migrated entity %s from unique id %s to %s", "Migrated entity %s from unique id %s to %s",
entity.entity_id, entity.entity_id,
entity.unique_id, entity.unique_id,
mbus_device_id, mbus_device_id,
) )
# Cleanup old device # Cleanup old device
dev_entities = er.async_entries_for_device( dev_entities = er.async_entries_for_device(
ent_reg, device_id, include_disabled_entities=True ent_reg, device_id, include_disabled_entities=True
) )
if not dev_entities: if not dev_entities:
dev_reg.async_remove_device(device_id) dev_reg.async_remove_device(device_id)
def is_supported_description( def is_supported_description(

View File

@ -219,6 +219,101 @@ async def test_migrate_hourly_gas_to_mbus(
) )
async def test_migrate_gas_with_devid_to_mbus(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
device_registry: dr.DeviceRegistry,
dsmr_connection_fixture: tuple[MagicMock, MagicMock, MagicMock],
) -> None:
"""Test migration of unique_id."""
(connection_factory, transport, protocol) = dsmr_connection_fixture
mock_entry = MockConfigEntry(
domain=DOMAIN,
unique_id="/dev/ttyUSB0",
data={
"port": "/dev/ttyUSB0",
"dsmr_version": "5B",
"serial_id": "1234",
"serial_id_gas": "37464C4F32313139303333373331",
},
options={
"time_between_update": 0,
},
)
mock_entry.add_to_hass(hass)
old_unique_id = "37464C4F32313139303333373331_belgium_5min_gas_meter_reading"
device = device_registry.async_get_or_create(
config_entry_id=mock_entry.entry_id,
identifiers={(DOMAIN, "37464C4F32313139303333373331")},
name="Gas Meter",
)
await hass.async_block_till_done()
entity: er.RegistryEntry = entity_registry.async_get_or_create(
suggested_object_id="gas_meter_reading",
disabled_by=None,
domain=SENSOR_DOMAIN,
platform=DOMAIN,
device_id=device.id,
unique_id=old_unique_id,
config_entry=mock_entry,
)
assert entity.unique_id == old_unique_id
await hass.async_block_till_done()
telegram = Telegram()
telegram.add(
MBUS_DEVICE_TYPE,
CosemObject((0, 1), [{"value": "003", "unit": ""}]),
"MBUS_DEVICE_TYPE",
)
telegram.add(
MBUS_EQUIPMENT_IDENTIFIER,
CosemObject(
(0, 1),
[{"value": "37464C4F32313139303333373331", "unit": ""}],
),
"MBUS_EQUIPMENT_IDENTIFIER",
)
telegram.add(
MBUS_METER_READING,
MBusObject(
(0, 1),
[
{"value": datetime.datetime.fromtimestamp(1551642213)},
{"value": Decimal(745.695), "unit": "m3"},
],
),
"MBUS_METER_READING",
)
assert await hass.config_entries.async_setup(mock_entry.entry_id)
await hass.async_block_till_done()
telegram_callback = connection_factory.call_args_list[0][0][2]
# simulate a telegram pushed from the smartmeter and parsed by dsmr_parser
telegram_callback(telegram)
# after receiving telegram entities need to have the chance to be created
await hass.async_block_till_done()
assert (
entity_registry.async_get_entity_id(SENSOR_DOMAIN, DOMAIN, old_unique_id)
is None
)
assert (
entity_registry.async_get_entity_id(
SENSOR_DOMAIN, DOMAIN, "37464C4F32313139303333373331"
)
== "sensor.gas_meter_reading"
)
async def test_migrate_gas_to_mbus_exists( async def test_migrate_gas_to_mbus_exists(
hass: HomeAssistant, hass: HomeAssistant,
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,