From 0e4e703b64da4f18f73a94563fb6dc9653fe9900 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 4 Mar 2026 14:24:28 +0100 Subject: [PATCH] Ignore transient empty segments in Matter vacuum (#164737) Co-authored-by: Claude Opus 4.6 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- homeassistant/components/matter/vacuum.py | 16 ++++++++-- tests/components/matter/test_vacuum.py | 37 +++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/matter/vacuum.py b/homeassistant/components/matter/vacuum.py index 722e432e381..30fa8a7fde3 100644 --- a/homeassistant/components/matter/vacuum.py +++ b/homeassistant/components/matter/vacuum.py @@ -4,6 +4,7 @@ from __future__ import annotations from dataclasses import dataclass from enum import IntEnum +import logging from typing import TYPE_CHECKING, Any from chip.clusters import Objects as clusters @@ -26,6 +27,8 @@ from .entity import MatterEntity, MatterEntityDescription from .helpers import get_matter from .models import MatterDiscoverySchema +_LOGGER = logging.getLogger(__name__) + class OperationalState(IntEnum): """Operational State of the vacuum cleaner. @@ -254,9 +257,18 @@ class MatterVacuum(MatterEntity, StateVacuumEntity): VacuumEntityFeature.CLEAN_AREA in self.supported_features and self.registry_entry is not None and (last_seen_segments := self.last_seen_segments) is not None - and self._current_segments != {s.id: s for s in last_seen_segments} + # Ignore empty segments; some devices transiently + # report an empty list before sending the real one. + and (current_segments := self._current_segments) ): - self.async_create_segments_issue() + last_seen_by_id = {s.id: s for s in last_seen_segments} + if current_segments != last_seen_by_id: + _LOGGER.debug( + "Vacuum segments changed: last_seen=%s, current=%s", + last_seen_by_id, + current_segments, + ) + self.async_create_segments_issue() @callback def _calculate_features(self) -> None: diff --git a/tests/components/matter/test_vacuum.py b/tests/components/matter/test_vacuum.py index baefba7cc18..49d889d94ca 100644 --- a/tests/components/matter/test_vacuum.py +++ b/tests/components/matter/test_vacuum.py @@ -474,6 +474,43 @@ async def test_vacuum_clean_area_select_areas_failure( ) +@pytest.mark.parametrize("node_fixture", ["mock_vacuum_cleaner"]) +async def test_vacuum_no_issue_on_transient_empty_segments( + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + matter_client: MagicMock, + matter_node: MatterNode, +) -> None: + """Test that no issue is raised when device transiently reports empty segments.""" + entity_id = "vacuum.mock_vacuum" + entity_entry = entity_registry.async_get(entity_id) + assert entity_entry is not None + + entity_registry.async_update_entity_options( + entity_id, + VACUUM_DOMAIN, + { + "last_seen_segments": [ + { + "id": "7", + "name": "My Location A", + "group": None, + } + ] + }, + ) + + # Simulate transient empty SupportedAreas (cluster 336, attribute 0) + set_node_attribute(matter_node, 1, 336, 0, []) + await trigger_subscription_callback(hass, matter_client) + + issue_reg = ir.async_get(hass) + issue = issue_reg.async_get_issue( + VACUUM_DOMAIN, f"segments_changed_{entity_entry.id}" + ) + assert issue is None + + @pytest.mark.parametrize("node_fixture", ["mock_vacuum_cleaner"]) async def test_vacuum_raise_segments_changed_issue( hass: HomeAssistant,