diff --git a/homeassistant/helpers/device_registry.py b/homeassistant/helpers/device_registry.py index cb009efeb07..c45b7d5f37b 100644 --- a/homeassistant/helpers/device_registry.py +++ b/homeassistant/helpers/device_registry.py @@ -43,6 +43,8 @@ CONNECTION_ZIGBEE = "zigbee" ORPHANED_DEVICE_KEEP_SECONDS = 86400 * 30 +RUNTIME_ONLY_ATTRS = {"suggested_area"} + class _DeviceIndex(NamedTuple): identifiers: dict[tuple[str, str], str] @@ -509,6 +511,15 @@ class DeviceRegistry: new = attr.evolve(old, **new_values) self._update_device(old, new) + + # If its only run time attributes (suggested_area) + # that do not get saved we do not want to write + # to disk or fire an event as we would end up + # firing events for data we have nothing to compare + # against since its never saved on disk + if RUNTIME_ONLY_ATTRS.issuperset(new_values): + return new + self.async_schedule_save() data: dict[str, Any] = { diff --git a/tests/helpers/test_device_registry.py b/tests/helpers/test_device_registry.py index 4e4150fe504..38632ba6545 100644 --- a/tests/helpers/test_device_registry.py +++ b/tests/helpers/test_device_registry.py @@ -1128,6 +1128,16 @@ async def test_update_suggested_area(hass, registry, area_registry, update_event assert update_events[1]["device_id"] == entry.id assert update_events[1]["changes"] == {"area_id": None, "suggested_area": None} + # Do not save or fire the event if the suggested + # area does not result in a change of area + # but still update the actual entry + with patch.object(registry, "async_schedule_save") as mock_save_2: + updated_entry = registry.async_update_device(entry.id, suggested_area="Other") + assert len(update_events) == 2 + assert mock_save_2.call_count == 0 + assert updated_entry != entry + assert updated_entry.suggested_area == "Other" + async def test_cleanup_device_registry(hass, registry): """Test cleanup works."""