mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Include changes in EVENT_DEVICE_REGISTRY_UPDATED (#66641)
This commit is contained in:
parent
21f2c664d9
commit
dcb3fc49c9
@ -11,7 +11,7 @@ import attr
|
|||||||
from homeassistant.backports.enum import StrEnum
|
from homeassistant.backports.enum import StrEnum
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED
|
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED
|
||||||
from homeassistant.core import Event, HomeAssistant, callback
|
from homeassistant.core import Event, HomeAssistant, callback
|
||||||
from homeassistant.exceptions import RequiredParameterMissing
|
from homeassistant.exceptions import HomeAssistantError, RequiredParameterMissing
|
||||||
from homeassistant.loader import bind_hass
|
from homeassistant.loader import bind_hass
|
||||||
import homeassistant.util.uuid as uuid_util
|
import homeassistant.util.uuid as uuid_util
|
||||||
|
|
||||||
@ -420,10 +420,14 @@ class DeviceRegistry:
|
|||||||
"""Update device attributes."""
|
"""Update device attributes."""
|
||||||
old = self.devices[device_id]
|
old = self.devices[device_id]
|
||||||
|
|
||||||
changes: dict[str, Any] = {}
|
new_values: dict[str, Any] = {} # Dict with new key/value pairs
|
||||||
|
old_values: dict[str, Any] = {} # Dict with old key/value pairs
|
||||||
|
|
||||||
config_entries = old.config_entries
|
config_entries = old.config_entries
|
||||||
|
|
||||||
|
if merge_identifiers is not UNDEFINED and new_identifiers is not UNDEFINED:
|
||||||
|
raise HomeAssistantError()
|
||||||
|
|
||||||
if isinstance(disabled_by, str) and not isinstance(
|
if isinstance(disabled_by, str) and not isinstance(
|
||||||
disabled_by, DeviceEntryDisabler
|
disabled_by, DeviceEntryDisabler
|
||||||
):
|
):
|
||||||
@ -462,7 +466,8 @@ class DeviceRegistry:
|
|||||||
config_entries = config_entries - {remove_config_entry_id}
|
config_entries = config_entries - {remove_config_entry_id}
|
||||||
|
|
||||||
if config_entries != old.config_entries:
|
if config_entries != old.config_entries:
|
||||||
changes["config_entries"] = config_entries
|
new_values["config_entries"] = config_entries
|
||||||
|
old_values["config_entries"] = old.config_entries
|
||||||
|
|
||||||
for attr_name, setvalue in (
|
for attr_name, setvalue in (
|
||||||
("connections", merge_connections),
|
("connections", merge_connections),
|
||||||
@ -471,10 +476,12 @@ class DeviceRegistry:
|
|||||||
old_value = getattr(old, attr_name)
|
old_value = getattr(old, attr_name)
|
||||||
# If not undefined, check if `value` contains new items.
|
# If not undefined, check if `value` contains new items.
|
||||||
if setvalue is not UNDEFINED and not setvalue.issubset(old_value):
|
if setvalue is not UNDEFINED and not setvalue.issubset(old_value):
|
||||||
changes[attr_name] = old_value | setvalue
|
new_values[attr_name] = old_value | setvalue
|
||||||
|
old_values[attr_name] = old_value
|
||||||
|
|
||||||
if new_identifiers is not UNDEFINED:
|
if new_identifiers is not UNDEFINED:
|
||||||
changes["identifiers"] = new_identifiers
|
new_values["identifiers"] = new_identifiers
|
||||||
|
old_values["identifiers"] = old.identifiers
|
||||||
|
|
||||||
for attr_name, value in (
|
for attr_name, value in (
|
||||||
("configuration_url", configuration_url),
|
("configuration_url", configuration_url),
|
||||||
@ -491,25 +498,27 @@ class DeviceRegistry:
|
|||||||
("via_device_id", via_device_id),
|
("via_device_id", via_device_id),
|
||||||
):
|
):
|
||||||
if value is not UNDEFINED and value != getattr(old, attr_name):
|
if value is not UNDEFINED and value != getattr(old, attr_name):
|
||||||
changes[attr_name] = value
|
new_values[attr_name] = value
|
||||||
|
old_values[attr_name] = getattr(old, attr_name)
|
||||||
|
|
||||||
if old.is_new:
|
if old.is_new:
|
||||||
changes["is_new"] = False
|
new_values["is_new"] = False
|
||||||
|
|
||||||
if not changes:
|
if not new_values:
|
||||||
return old
|
return old
|
||||||
|
|
||||||
new = attr.evolve(old, **changes)
|
new = attr.evolve(old, **new_values)
|
||||||
self._update_device(old, new)
|
self._update_device(old, new)
|
||||||
self.async_schedule_save()
|
self.async_schedule_save()
|
||||||
|
|
||||||
self.hass.bus.async_fire(
|
data: dict[str, Any] = {
|
||||||
EVENT_DEVICE_REGISTRY_UPDATED,
|
"action": "create" if old.is_new else "update",
|
||||||
{
|
"device_id": new.id,
|
||||||
"action": "create" if "is_new" in changes else "update",
|
}
|
||||||
"device_id": new.id,
|
if not old.is_new:
|
||||||
},
|
data["changes"] = old_values
|
||||||
)
|
|
||||||
|
self.hass.bus.async_fire(EVENT_DEVICE_REGISTRY_UPDATED, data)
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
@ -96,8 +96,12 @@ async def test_get_or_create_returns_same_entry(
|
|||||||
assert len(update_events) == 2
|
assert len(update_events) == 2
|
||||||
assert update_events[0]["action"] == "create"
|
assert update_events[0]["action"] == "create"
|
||||||
assert update_events[0]["device_id"] == entry.id
|
assert update_events[0]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[0]
|
||||||
assert update_events[1]["action"] == "update"
|
assert update_events[1]["action"] == "update"
|
||||||
assert update_events[1]["device_id"] == entry.id
|
assert update_events[1]["device_id"] == entry.id
|
||||||
|
assert update_events[1]["changes"] == {
|
||||||
|
"connections": {("mac", "12:34:56:ab:cd:ef")}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_requirement_for_identifier_or_connection(registry):
|
async def test_requirement_for_identifier_or_connection(registry):
|
||||||
@ -518,14 +522,19 @@ async def test_removing_config_entries(hass, registry, update_events):
|
|||||||
assert len(update_events) == 5
|
assert len(update_events) == 5
|
||||||
assert update_events[0]["action"] == "create"
|
assert update_events[0]["action"] == "create"
|
||||||
assert update_events[0]["device_id"] == entry.id
|
assert update_events[0]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[0]
|
||||||
assert update_events[1]["action"] == "update"
|
assert update_events[1]["action"] == "update"
|
||||||
assert update_events[1]["device_id"] == entry2.id
|
assert update_events[1]["device_id"] == entry2.id
|
||||||
|
assert update_events[1]["changes"] == {"config_entries": {"123"}}
|
||||||
assert update_events[2]["action"] == "create"
|
assert update_events[2]["action"] == "create"
|
||||||
assert update_events[2]["device_id"] == entry3.id
|
assert update_events[2]["device_id"] == entry3.id
|
||||||
|
assert "changes" not in update_events[2]
|
||||||
assert update_events[3]["action"] == "update"
|
assert update_events[3]["action"] == "update"
|
||||||
assert update_events[3]["device_id"] == entry.id
|
assert update_events[3]["device_id"] == entry.id
|
||||||
|
assert update_events[3]["changes"] == {"config_entries": {"456", "123"}}
|
||||||
assert update_events[4]["action"] == "remove"
|
assert update_events[4]["action"] == "remove"
|
||||||
assert update_events[4]["device_id"] == entry3.id
|
assert update_events[4]["device_id"] == entry3.id
|
||||||
|
assert "changes" not in update_events[4]
|
||||||
|
|
||||||
|
|
||||||
async def test_deleted_device_removing_config_entries(hass, registry, update_events):
|
async def test_deleted_device_removing_config_entries(hass, registry, update_events):
|
||||||
@ -568,14 +577,19 @@ async def test_deleted_device_removing_config_entries(hass, registry, update_eve
|
|||||||
assert len(update_events) == 5
|
assert len(update_events) == 5
|
||||||
assert update_events[0]["action"] == "create"
|
assert update_events[0]["action"] == "create"
|
||||||
assert update_events[0]["device_id"] == entry.id
|
assert update_events[0]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[0]
|
||||||
assert update_events[1]["action"] == "update"
|
assert update_events[1]["action"] == "update"
|
||||||
assert update_events[1]["device_id"] == entry2.id
|
assert update_events[1]["device_id"] == entry2.id
|
||||||
|
assert update_events[1]["changes"] == {"config_entries": {"123"}}
|
||||||
assert update_events[2]["action"] == "create"
|
assert update_events[2]["action"] == "create"
|
||||||
assert update_events[2]["device_id"] == entry3.id
|
assert update_events[2]["device_id"] == entry3.id
|
||||||
|
assert "changes" not in update_events[2]["device_id"]
|
||||||
assert update_events[3]["action"] == "remove"
|
assert update_events[3]["action"] == "remove"
|
||||||
assert update_events[3]["device_id"] == entry.id
|
assert update_events[3]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[3]
|
||||||
assert update_events[4]["action"] == "remove"
|
assert update_events[4]["action"] == "remove"
|
||||||
assert update_events[4]["device_id"] == entry3.id
|
assert update_events[4]["device_id"] == entry3.id
|
||||||
|
assert "changes" not in update_events[4]
|
||||||
|
|
||||||
registry.async_clear_config_entry("123")
|
registry.async_clear_config_entry("123")
|
||||||
assert len(registry.devices) == 0
|
assert len(registry.devices) == 0
|
||||||
@ -892,7 +906,7 @@ async def test_format_mac(registry):
|
|||||||
assert list(invalid_mac_entry.connections)[0][1] == invalid
|
assert list(invalid_mac_entry.connections)[0][1] == invalid
|
||||||
|
|
||||||
|
|
||||||
async def test_update(registry):
|
async def test_update(hass, registry, update_events):
|
||||||
"""Verify that we can update some attributes of a device."""
|
"""Verify that we can update some attributes of a device."""
|
||||||
entry = registry.async_get_or_create(
|
entry = registry.async_get_or_create(
|
||||||
config_entry_id="1234",
|
config_entry_id="1234",
|
||||||
@ -940,6 +954,24 @@ async def test_update(registry):
|
|||||||
|
|
||||||
assert registry.async_get(updated_entry.id) is not None
|
assert registry.async_get(updated_entry.id) is not None
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(update_events) == 2
|
||||||
|
assert update_events[0]["action"] == "create"
|
||||||
|
assert update_events[0]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[0]
|
||||||
|
assert update_events[1]["action"] == "update"
|
||||||
|
assert update_events[1]["device_id"] == entry.id
|
||||||
|
assert update_events[1]["changes"] == {
|
||||||
|
"area_id": None,
|
||||||
|
"disabled_by": None,
|
||||||
|
"identifiers": {("bla", "123"), ("hue", "456")},
|
||||||
|
"manufacturer": None,
|
||||||
|
"model": None,
|
||||||
|
"name_by_user": None,
|
||||||
|
"via_device_id": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_update_remove_config_entries(hass, registry, update_events):
|
async def test_update_remove_config_entries(hass, registry, update_events):
|
||||||
"""Make sure we do not get duplicate entries."""
|
"""Make sure we do not get duplicate entries."""
|
||||||
@ -989,17 +1021,22 @@ async def test_update_remove_config_entries(hass, registry, update_events):
|
|||||||
assert len(update_events) == 5
|
assert len(update_events) == 5
|
||||||
assert update_events[0]["action"] == "create"
|
assert update_events[0]["action"] == "create"
|
||||||
assert update_events[0]["device_id"] == entry.id
|
assert update_events[0]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[0]
|
||||||
assert update_events[1]["action"] == "update"
|
assert update_events[1]["action"] == "update"
|
||||||
assert update_events[1]["device_id"] == entry2.id
|
assert update_events[1]["device_id"] == entry2.id
|
||||||
|
assert update_events[1]["changes"] == {"config_entries": {"123"}}
|
||||||
assert update_events[2]["action"] == "create"
|
assert update_events[2]["action"] == "create"
|
||||||
assert update_events[2]["device_id"] == entry3.id
|
assert update_events[2]["device_id"] == entry3.id
|
||||||
|
assert "changes" not in update_events[2]
|
||||||
assert update_events[3]["action"] == "update"
|
assert update_events[3]["action"] == "update"
|
||||||
assert update_events[3]["device_id"] == entry.id
|
assert update_events[3]["device_id"] == entry.id
|
||||||
|
assert update_events[3]["changes"] == {"config_entries": {"456", "123"}}
|
||||||
assert update_events[4]["action"] == "remove"
|
assert update_events[4]["action"] == "remove"
|
||||||
assert update_events[4]["device_id"] == entry3.id
|
assert update_events[4]["device_id"] == entry3.id
|
||||||
|
assert "changes" not in update_events[4]
|
||||||
|
|
||||||
|
|
||||||
async def test_update_sw_version(registry):
|
async def test_update_sw_version(hass, registry, update_events):
|
||||||
"""Verify that we can update software version of a device."""
|
"""Verify that we can update software version of a device."""
|
||||||
entry = registry.async_get_or_create(
|
entry = registry.async_get_or_create(
|
||||||
config_entry_id="1234",
|
config_entry_id="1234",
|
||||||
@ -1016,8 +1053,18 @@ async def test_update_sw_version(registry):
|
|||||||
assert updated_entry != entry
|
assert updated_entry != entry
|
||||||
assert updated_entry.sw_version == sw_version
|
assert updated_entry.sw_version == sw_version
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
async def test_update_hw_version(registry):
|
assert len(update_events) == 2
|
||||||
|
assert update_events[0]["action"] == "create"
|
||||||
|
assert update_events[0]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[0]
|
||||||
|
assert update_events[1]["action"] == "update"
|
||||||
|
assert update_events[1]["device_id"] == entry.id
|
||||||
|
assert update_events[1]["changes"] == {"sw_version": None}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_update_hw_version(hass, registry, update_events):
|
||||||
"""Verify that we can update hardware version of a device."""
|
"""Verify that we can update hardware version of a device."""
|
||||||
entry = registry.async_get_or_create(
|
entry = registry.async_get_or_create(
|
||||||
config_entry_id="1234",
|
config_entry_id="1234",
|
||||||
@ -1034,8 +1081,18 @@ async def test_update_hw_version(registry):
|
|||||||
assert updated_entry != entry
|
assert updated_entry != entry
|
||||||
assert updated_entry.hw_version == hw_version
|
assert updated_entry.hw_version == hw_version
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
async def test_update_suggested_area(registry, area_registry):
|
assert len(update_events) == 2
|
||||||
|
assert update_events[0]["action"] == "create"
|
||||||
|
assert update_events[0]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[0]
|
||||||
|
assert update_events[1]["action"] == "update"
|
||||||
|
assert update_events[1]["device_id"] == entry.id
|
||||||
|
assert update_events[1]["changes"] == {"hw_version": None}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_update_suggested_area(hass, registry, area_registry, update_events):
|
||||||
"""Verify that we can update the suggested area version of a device."""
|
"""Verify that we can update the suggested area version of a device."""
|
||||||
entry = registry.async_get_or_create(
|
entry = registry.async_get_or_create(
|
||||||
config_entry_id="1234",
|
config_entry_id="1234",
|
||||||
@ -1061,6 +1118,16 @@ async def test_update_suggested_area(registry, area_registry):
|
|||||||
assert updated_entry.area_id == pool_area.id
|
assert updated_entry.area_id == pool_area.id
|
||||||
assert len(area_registry.areas) == 1
|
assert len(area_registry.areas) == 1
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(update_events) == 2
|
||||||
|
assert update_events[0]["action"] == "create"
|
||||||
|
assert update_events[0]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[0]
|
||||||
|
assert update_events[1]["action"] == "update"
|
||||||
|
assert update_events[1]["device_id"] == entry.id
|
||||||
|
assert update_events[1]["changes"] == {"area_id": None, "suggested_area": None}
|
||||||
|
|
||||||
|
|
||||||
async def test_cleanup_device_registry(hass, registry):
|
async def test_cleanup_device_registry(hass, registry):
|
||||||
"""Test cleanup works."""
|
"""Test cleanup works."""
|
||||||
@ -1221,12 +1288,16 @@ async def test_restore_device(hass, registry, update_events):
|
|||||||
assert len(update_events) == 4
|
assert len(update_events) == 4
|
||||||
assert update_events[0]["action"] == "create"
|
assert update_events[0]["action"] == "create"
|
||||||
assert update_events[0]["device_id"] == entry.id
|
assert update_events[0]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[0]
|
||||||
assert update_events[1]["action"] == "remove"
|
assert update_events[1]["action"] == "remove"
|
||||||
assert update_events[1]["device_id"] == entry.id
|
assert update_events[1]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[1]
|
||||||
assert update_events[2]["action"] == "create"
|
assert update_events[2]["action"] == "create"
|
||||||
assert update_events[2]["device_id"] == entry2.id
|
assert update_events[2]["device_id"] == entry2.id
|
||||||
|
assert "changes" not in update_events[2]
|
||||||
assert update_events[3]["action"] == "create"
|
assert update_events[3]["action"] == "create"
|
||||||
assert update_events[3]["device_id"] == entry3.id
|
assert update_events[3]["device_id"] == entry3.id
|
||||||
|
assert "changes" not in update_events[3]
|
||||||
|
|
||||||
|
|
||||||
async def test_restore_simple_device(hass, registry, update_events):
|
async def test_restore_simple_device(hass, registry, update_events):
|
||||||
@ -1266,12 +1337,16 @@ async def test_restore_simple_device(hass, registry, update_events):
|
|||||||
assert len(update_events) == 4
|
assert len(update_events) == 4
|
||||||
assert update_events[0]["action"] == "create"
|
assert update_events[0]["action"] == "create"
|
||||||
assert update_events[0]["device_id"] == entry.id
|
assert update_events[0]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[0]
|
||||||
assert update_events[1]["action"] == "remove"
|
assert update_events[1]["action"] == "remove"
|
||||||
assert update_events[1]["device_id"] == entry.id
|
assert update_events[1]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[1]
|
||||||
assert update_events[2]["action"] == "create"
|
assert update_events[2]["action"] == "create"
|
||||||
assert update_events[2]["device_id"] == entry2.id
|
assert update_events[2]["device_id"] == entry2.id
|
||||||
|
assert "changes" not in update_events[2]
|
||||||
assert update_events[3]["action"] == "create"
|
assert update_events[3]["action"] == "create"
|
||||||
assert update_events[3]["device_id"] == entry3.id
|
assert update_events[3]["device_id"] == entry3.id
|
||||||
|
assert "changes" not in update_events[3]
|
||||||
|
|
||||||
|
|
||||||
async def test_restore_shared_device(hass, registry, update_events):
|
async def test_restore_shared_device(hass, registry, update_events):
|
||||||
@ -1358,18 +1433,31 @@ async def test_restore_shared_device(hass, registry, update_events):
|
|||||||
assert len(update_events) == 7
|
assert len(update_events) == 7
|
||||||
assert update_events[0]["action"] == "create"
|
assert update_events[0]["action"] == "create"
|
||||||
assert update_events[0]["device_id"] == entry.id
|
assert update_events[0]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[0]
|
||||||
assert update_events[1]["action"] == "update"
|
assert update_events[1]["action"] == "update"
|
||||||
assert update_events[1]["device_id"] == entry.id
|
assert update_events[1]["device_id"] == entry.id
|
||||||
|
assert update_events[1]["changes"] == {
|
||||||
|
"config_entries": {"123"},
|
||||||
|
"identifiers": {("entry_123", "0123")},
|
||||||
|
}
|
||||||
assert update_events[2]["action"] == "remove"
|
assert update_events[2]["action"] == "remove"
|
||||||
assert update_events[2]["device_id"] == entry.id
|
assert update_events[2]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[2]
|
||||||
assert update_events[3]["action"] == "create"
|
assert update_events[3]["action"] == "create"
|
||||||
assert update_events[3]["device_id"] == entry.id
|
assert update_events[3]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[3]
|
||||||
assert update_events[4]["action"] == "remove"
|
assert update_events[4]["action"] == "remove"
|
||||||
assert update_events[4]["device_id"] == entry.id
|
assert update_events[4]["device_id"] == entry.id
|
||||||
|
assert "changes" not in update_events[4]
|
||||||
assert update_events[5]["action"] == "create"
|
assert update_events[5]["action"] == "create"
|
||||||
assert update_events[5]["device_id"] == entry.id
|
assert update_events[5]["device_id"] == entry.id
|
||||||
assert update_events[1]["action"] == "update"
|
assert "changes" not in update_events[5]
|
||||||
assert update_events[1]["device_id"] == entry.id
|
assert update_events[6]["action"] == "update"
|
||||||
|
assert update_events[6]["device_id"] == entry.id
|
||||||
|
assert update_events[6]["changes"] == {
|
||||||
|
"config_entries": {"234"},
|
||||||
|
"identifiers": {("entry_234", "2345")},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_get_or_create_empty_then_set_default_values(hass, registry):
|
async def test_get_or_create_empty_then_set_default_values(hass, registry):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user