Add serial_number to device registry entries (#77713)

This commit is contained in:
Erik Montnemery 2022-09-27 09:08:54 +02:00 committed by GitHub
parent c52d0f7495
commit cba3b6ad94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 148 additions and 5 deletions

View File

@ -167,6 +167,7 @@ def _entry_dict(entry):
"model": entry.model, "model": entry.model,
"name_by_user": entry.name_by_user, "name_by_user": entry.name_by_user,
"name": entry.name, "name": entry.name,
"serial_number": entry.serial_number,
"sw_version": entry.sw_version, "sw_version": entry.sw_version,
"via_device_id": entry.via_device_id, "via_device_id": entry.via_device_id,
} }

View File

@ -32,7 +32,7 @@ DATA_REGISTRY = "device_registry"
EVENT_DEVICE_REGISTRY_UPDATED = "device_registry_updated" EVENT_DEVICE_REGISTRY_UPDATED = "device_registry_updated"
STORAGE_KEY = "core.device_registry" STORAGE_KEY = "core.device_registry"
STORAGE_VERSION_MAJOR = 1 STORAGE_VERSION_MAJOR = 1
STORAGE_VERSION_MINOR = 3 STORAGE_VERSION_MINOR = 4
SAVE_DELAY = 10 SAVE_DELAY = 10
CLEANUP_DELAY = 10 CLEANUP_DELAY = 10
@ -83,6 +83,7 @@ class DeviceEntry:
model: str | None = attr.ib(default=None) model: str | None = attr.ib(default=None)
name_by_user: str | None = attr.ib(default=None) name_by_user: str | None = attr.ib(default=None)
name: str | None = attr.ib(default=None) name: str | None = attr.ib(default=None)
serial_number: str | None = attr.ib(default=None)
suggested_area: str | None = attr.ib(default=None) suggested_area: str | None = attr.ib(default=None)
sw_version: str | None = attr.ib(default=None) sw_version: str | None = attr.ib(default=None)
via_device_id: str | None = attr.ib(default=None) via_device_id: str | None = attr.ib(default=None)
@ -180,6 +181,10 @@ class DeviceRegistryStore(storage.Store[dict[str, list[dict[str, Any]]]]):
# Introduced in 2022.2 # Introduced in 2022.2
for device in old_data["devices"]: for device in old_data["devices"]:
device["hw_version"] = device.get("hw_version") device["hw_version"] = device.get("hw_version")
if old_minor_version < 4:
# Introduced in 2022.10
for device in old_data["devices"]:
device["serial_number"] = device.get("serial_number")
if old_major_version > 1: if old_major_version > 1:
raise NotImplementedError raise NotImplementedError
@ -301,6 +306,7 @@ class DeviceRegistry:
manufacturer: str | None | UndefinedType = UNDEFINED, manufacturer: str | None | UndefinedType = UNDEFINED,
model: str | None | UndefinedType = UNDEFINED, model: str | None | UndefinedType = UNDEFINED,
name: str | None | UndefinedType = UNDEFINED, name: str | None | UndefinedType = UNDEFINED,
serial_number: str | None | UndefinedType = UNDEFINED,
suggested_area: str | None | UndefinedType = UNDEFINED, suggested_area: str | None | UndefinedType = UNDEFINED,
sw_version: str | None | UndefinedType = UNDEFINED, sw_version: str | None | UndefinedType = UNDEFINED,
via_device: tuple[str, str] | None = None, via_device: tuple[str, str] | None = None,
@ -366,6 +372,7 @@ class DeviceRegistry:
merge_identifiers=identifiers or UNDEFINED, merge_identifiers=identifiers or UNDEFINED,
model=model, model=model,
name=name, name=name,
serial_number=serial_number,
suggested_area=suggested_area, suggested_area=suggested_area,
sw_version=sw_version, sw_version=sw_version,
via_device_id=via_device_id, via_device_id=via_device_id,
@ -395,6 +402,7 @@ class DeviceRegistry:
name: str | None | UndefinedType = UNDEFINED, name: str | None | UndefinedType = UNDEFINED,
new_identifiers: set[tuple[str, str]] | UndefinedType = UNDEFINED, new_identifiers: set[tuple[str, str]] | UndefinedType = UNDEFINED,
remove_config_entry_id: str | UndefinedType = UNDEFINED, remove_config_entry_id: str | UndefinedType = UNDEFINED,
serial_number: str | None | UndefinedType = UNDEFINED,
suggested_area: str | None | UndefinedType = UNDEFINED, suggested_area: str | None | UndefinedType = UNDEFINED,
sw_version: str | None | UndefinedType = UNDEFINED, sw_version: str | None | UndefinedType = UNDEFINED,
via_device_id: str | None | UndefinedType = UNDEFINED, via_device_id: str | None | UndefinedType = UNDEFINED,
@ -479,6 +487,7 @@ class DeviceRegistry:
("model", model), ("model", model),
("name", name), ("name", name),
("name_by_user", name_by_user), ("name_by_user", name_by_user),
("serial_number", serial_number),
("suggested_area", suggested_area), ("suggested_area", suggested_area),
("sw_version", sw_version), ("sw_version", sw_version),
("via_device_id", via_device_id), ("via_device_id", via_device_id),
@ -566,6 +575,7 @@ class DeviceRegistry:
model=device["model"], model=device["model"],
name_by_user=device["name_by_user"], name_by_user=device["name_by_user"],
name=device["name"], name=device["name"],
serial_number=device["serial_number"],
sw_version=device["sw_version"], sw_version=device["sw_version"],
via_device_id=device["via_device_id"], via_device_id=device["via_device_id"],
) )
@ -608,6 +618,7 @@ class DeviceRegistry:
"model": entry.model, "model": entry.model,
"name_by_user": entry.name_by_user, "name_by_user": entry.name_by_user,
"name": entry.name, "name": entry.name,
"serial_number": entry.serial_number,
"sw_version": entry.sw_version, "sw_version": entry.sw_version,
"via_device_id": entry.via_device_id, "via_device_id": entry.via_device_id,
} }

View File

@ -64,6 +64,7 @@ async def test_list_devices(hass, client, registry):
"model": "model", "model": "model",
"name_by_user": None, "name_by_user": None,
"name": None, "name": None,
"serial_number": None,
"sw_version": None, "sw_version": None,
"via_device_id": None, "via_device_id": None,
}, },
@ -80,6 +81,7 @@ async def test_list_devices(hass, client, registry):
"model": "model", "model": "model",
"name_by_user": None, "name_by_user": None,
"name": None, "name": None,
"serial_number": None,
"sw_version": None, "sw_version": None,
"via_device_id": dev1, "via_device_id": dev1,
}, },
@ -106,6 +108,7 @@ async def test_list_devices(hass, client, registry):
"model": "model", "model": "model",
"name_by_user": None, "name_by_user": None,
"name": None, "name": None,
"serial_number": None,
"sw_version": None, "sw_version": None,
"via_device_id": None, "via_device_id": None,
} }

View File

@ -189,6 +189,7 @@ async def test_loading_from_storage(hass, hass_storage):
"model": "model", "model": "model",
"name_by_user": "Test Friendly Name", "name_by_user": "Test Friendly Name",
"name": "name", "name": "name",
"serial_number": "serial_no",
"sw_version": "version", "sw_version": "version",
"via_device_id": None, "via_device_id": None,
} }
@ -231,6 +232,7 @@ async def test_loading_from_storage(hass, hass_storage):
model="model", model="model",
name_by_user="Test Friendly Name", name_by_user="Test Friendly Name",
name="name", name="name",
serial_number="serial_no",
suggested_area=None, # Not stored suggested_area=None, # Not stored
sw_version="version", sw_version="version",
) )
@ -261,8 +263,8 @@ async def test_loading_from_storage(hass, hass_storage):
@pytest.mark.parametrize("load_registries", [False]) @pytest.mark.parametrize("load_registries", [False])
async def test_migration_1_1_to_1_3(hass, hass_storage): async def test_migration_1_1_to_1_4(hass, hass_storage):
"""Test migration from version 1.1 to 1.3.""" """Test migration from version 1.1 to 1.4."""
hass_storage[device_registry.STORAGE_KEY] = { hass_storage[device_registry.STORAGE_KEY] = {
"version": 1, "version": 1,
"minor_version": 1, "minor_version": 1,
@ -350,6 +352,7 @@ async def test_migration_1_1_to_1_3(hass, hass_storage):
"model": "model", "model": "model",
"name": "name", "name": "name",
"name_by_user": None, "name_by_user": None,
"serial_number": None,
"sw_version": "new_version", "sw_version": "new_version",
"via_device_id": None, "via_device_id": None,
}, },
@ -367,6 +370,7 @@ async def test_migration_1_1_to_1_3(hass, hass_storage):
"model": None, "model": None,
"name_by_user": None, "name_by_user": None,
"name": None, "name": None,
"serial_number": None,
"sw_version": None, "sw_version": None,
"via_device_id": None, "via_device_id": None,
}, },
@ -385,8 +389,8 @@ async def test_migration_1_1_to_1_3(hass, hass_storage):
@pytest.mark.parametrize("load_registries", [False]) @pytest.mark.parametrize("load_registries", [False])
async def test_migration_1_2_to_1_3(hass, hass_storage): async def test_migration_1_2_to_1_4(hass, hass_storage):
"""Test migration from version 1.2 to 1.3.""" """Test migration from version 1.2 to 1.4."""
hass_storage[device_registry.STORAGE_KEY] = { hass_storage[device_registry.STORAGE_KEY] = {
"version": 1, "version": 1,
"minor_version": 2, "minor_version": 2,
@ -473,6 +477,7 @@ async def test_migration_1_2_to_1_3(hass, hass_storage):
"model": "model", "model": "model",
"name": "name", "name": "name",
"name_by_user": None, "name_by_user": None,
"serial_number": None,
"sw_version": "new_version", "sw_version": "new_version",
"via_device_id": None, "via_device_id": None,
}, },
@ -490,6 +495,126 @@ async def test_migration_1_2_to_1_3(hass, hass_storage):
"model": None, "model": None,
"name_by_user": None, "name_by_user": None,
"name": None, "name": None,
"serial_number": None,
"sw_version": None,
"via_device_id": None,
},
],
"deleted_devices": [],
},
}
@pytest.mark.parametrize("load_registries", [False])
async def test_migration_1_3_to_1_4(hass, hass_storage):
"""Test migration from version 1.3 to 1.4."""
hass_storage[device_registry.STORAGE_KEY] = {
"version": 1,
"minor_version": 3,
"key": device_registry.STORAGE_KEY,
"data": {
"devices": [
{
"area_id": None,
"config_entries": ["1234"],
"configuration_url": None,
"connections": [["Zigbee", "01.23.45.67.89"]],
"disabled_by": None,
"entry_type": "service",
"hw_version": "hw_version",
"id": "abcdefghijklm",
"identifiers": [["serial", "12:34:56:AB:CD:EF"]],
"manufacturer": "manufacturer",
"model": "model",
"name": "name",
"name_by_user": None,
"sw_version": "version",
"via_device_id": None,
},
{
"area_id": None,
"config_entries": [None],
"configuration_url": None,
"connections": [],
"disabled_by": None,
"entry_type": None,
"hw_version": None,
"id": "invalid-entry-type",
"identifiers": [["serial", "mock-id-invalid-entry"]],
"manufacturer": None,
"model": None,
"name_by_user": None,
"name": None,
"sw_version": None,
"via_device_id": None,
},
],
"deleted_devices": [],
},
}
await device_registry.async_load(hass)
registry = device_registry.async_get(hass)
# Test data was loaded
entry = registry.async_get_or_create(
config_entry_id="1234",
connections={("Zigbee", "01.23.45.67.89")},
identifiers={("serial", "12:34:56:AB:CD:EF")},
)
assert entry.id == "abcdefghijklm"
# Update to trigger a store
entry = registry.async_get_or_create(
config_entry_id="1234",
connections={("Zigbee", "01.23.45.67.89")},
identifiers={("serial", "12:34:56:AB:CD:EF")},
sw_version="new_version",
)
assert entry.id == "abcdefghijklm"
# Check we store migrated data
await flush_store(registry._store)
assert hass_storage[device_registry.STORAGE_KEY] == {
"version": device_registry.STORAGE_VERSION_MAJOR,
"minor_version": device_registry.STORAGE_VERSION_MINOR,
"key": device_registry.STORAGE_KEY,
"data": {
"devices": [
{
"area_id": None,
"config_entries": ["1234"],
"configuration_url": None,
"connections": [["Zigbee", "01.23.45.67.89"]],
"disabled_by": None,
"entry_type": "service",
"hw_version": "hw_version",
"id": "abcdefghijklm",
"identifiers": [["serial", "12:34:56:AB:CD:EF"]],
"manufacturer": "manufacturer",
"model": "model",
"name": "name",
"name_by_user": None,
"serial_number": None,
"sw_version": "new_version",
"via_device_id": None,
},
{
"area_id": None,
"config_entries": [None],
"configuration_url": None,
"connections": [],
"disabled_by": None,
"entry_type": None,
"hw_version": None,
"id": "invalid-entry-type",
"identifiers": [["serial", "mock-id-invalid-entry"]],
"manufacturer": None,
"model": None,
"name_by_user": None,
"name": None,
"serial_number": None,
"sw_version": None, "sw_version": None,
"via_device_id": None, "via_device_id": None,
}, },
@ -918,6 +1043,7 @@ async def test_update(hass, registry, update_events):
name_by_user="Test Friendly Name", name_by_user="Test Friendly Name",
name="name", name="name",
new_identifiers=new_identifiers, new_identifiers=new_identifiers,
serial_number="serial_no",
suggested_area="suggested_area", suggested_area="suggested_area",
sw_version="version", sw_version="version",
via_device_id="98765B", via_device_id="98765B",
@ -939,6 +1065,7 @@ async def test_update(hass, registry, update_events):
model="Test Model", model="Test Model",
name_by_user="Test Friendly Name", name_by_user="Test Friendly Name",
name="name", name="name",
serial_number="serial_no",
suggested_area="suggested_area", suggested_area="suggested_area",
sw_version="version", sw_version="version",
via_device_id="98765B", via_device_id="98765B",
@ -978,6 +1105,7 @@ async def test_update(hass, registry, update_events):
"model": None, "model": None,
"name": None, "name": None,
"name_by_user": None, "name_by_user": None,
"serial_number": None,
"suggested_area": None, "suggested_area": None,
"sw_version": None, "sw_version": None,
"via_device_id": None, "via_device_id": None,