mirror of
https://github.com/home-assistant/core.git
synced 2026-08-15 17:52:59 +01:00
Update MQTT device registry event handling (#176965)
This commit is contained in:
@@ -959,9 +959,7 @@ class MqttDiscoveryDeviceUpdateMixin(ABC):
|
||||
self, event: Event[EventDeviceRegistryUpdatedData]
|
||||
) -> None:
|
||||
"""Handle the manual removal of a device."""
|
||||
if self._skip_device_removal or not async_removed_from_device(
|
||||
self.hass, event, cast(str, self._device_id), self._config_entry_id
|
||||
):
|
||||
if self._skip_device_removal or not async_removed_from_device(event):
|
||||
return
|
||||
# Prevent a second cleanup round after the device is removed
|
||||
self._remove_device_updated()
|
||||
@@ -1747,20 +1745,11 @@ def update_device(
|
||||
|
||||
@callback
|
||||
def async_removed_from_device(
|
||||
hass: HomeAssistant,
|
||||
event: Event[EventDeviceRegistryUpdatedData],
|
||||
mqtt_device_id: str,
|
||||
config_entry_id: str,
|
||||
) -> bool:
|
||||
"""Check if the passed event indicates MQTT was removed from a device."""
|
||||
if event.data["action"] == "update":
|
||||
if "config_entries" not in event.data["changes"]:
|
||||
return False
|
||||
device_registry = dr.async_get(hass)
|
||||
if (
|
||||
device_entry := device_registry.async_get(mqtt_device_id)
|
||||
) and config_entry_id in device_entry.config_entries:
|
||||
# Not removed from device
|
||||
return False
|
||||
"""Check if the passed event indicates MQTT was removed from a device.
|
||||
|
||||
return True
|
||||
A device is associated with a single config entry, so MQTT is removed from a
|
||||
device only when the device itself is removed.
|
||||
"""
|
||||
return event.data["action"] == "remove"
|
||||
|
||||
@@ -26,6 +26,7 @@ from homeassistant.components.mqtt.discovery import (
|
||||
MQTTDiscoveryPayload,
|
||||
async_start,
|
||||
)
|
||||
from homeassistant.components.mqtt.entity import async_removed_from_device
|
||||
from homeassistant.components.mqtt.models import ReceiveMessage
|
||||
from homeassistant.components.mqtt.schemas import (
|
||||
DEVICE_DISCOVERY_SCHEMA,
|
||||
@@ -3495,3 +3496,40 @@ async def test_shared_qos_with_device_discovery(
|
||||
mqtt_mock.async_subscribe.assert_has_calls(
|
||||
[call("foobar/sensors/bla2/state", ANY, qos, "utf-8", ANY)]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("event_data", "expected"),
|
||||
[
|
||||
pytest.param(
|
||||
{"action": "remove", "device_id": "abc", "device": {}},
|
||||
True,
|
||||
id="remove",
|
||||
),
|
||||
pytest.param(
|
||||
{
|
||||
"action": "update",
|
||||
"device_id": "abc",
|
||||
"changes": {"config_entry_id": "mqtt_entry_id"},
|
||||
},
|
||||
False,
|
||||
id="update-config-entry",
|
||||
),
|
||||
pytest.param(
|
||||
{"action": "update", "device_id": "abc", "changes": {"name": "New name"}},
|
||||
False,
|
||||
id="update-other",
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_async_removed_from_device(
|
||||
event_data: dr.EventDeviceRegistryUpdatedData,
|
||||
expected: bool,
|
||||
) -> None:
|
||||
"""MQTT leaves a device only when the device is removed.
|
||||
|
||||
A device belongs to a single config entry, so a config-entry change on an update
|
||||
event is not a removal; only a 'remove' action is.
|
||||
"""
|
||||
event = Event(dr.EVENT_DEVICE_REGISTRY_UPDATED, event_data)
|
||||
assert async_removed_from_device(event) is expected
|
||||
|
||||
Reference in New Issue
Block a user