From a02a6ad6b6525c3b8d009f122fc4df62ce070ddd Mon Sep 17 00:00:00 2001 From: David Mulcahey Date: Tue, 14 Jul 2026 08:41:20 -0400 Subject: [PATCH] Do not bind clusters for suppressed entities --- tests/test_device.py | 25 +++++++++++++++++++++++++ zha/zigbee/device.py | 10 ++++------ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/tests/test_device.py b/tests/test_device.py index 8c9703555..d35f50fd5 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -1200,6 +1200,31 @@ async def test_join_binding_reporting(zha_gateway: Gateway) -> None: ] +async def test_quirks_v2_prevent_entity_excludes_cluster_configuration( + zha_gateway: Gateway, +) -> None: + """Test a quirk-suppressed entity does not configure its cluster.""" + zigpy_dev = await zigpy_device_from_json( + zha_gateway.application_controller, + "tests/data/devices/innr-sp-240-0x191e3685.json", + ) + + level = zigpy_dev.endpoints[1].level + on_off = zigpy_dev.endpoints[1].on_off + + zha_device = await join_zigpy_device(zha_gateway, zigpy_dev) + + assert zha_device.quirk_applied + + assert level.bind.mock_calls == [] + assert level.configure_reporting_multiple.mock_calls == [] + assert level.read_attributes.mock_calls == [] + + assert on_off.bind.mock_calls == [call()] + assert on_off.configure_reporting_multiple.call_count == 1 + assert on_off.read_attributes.call_count == 2 + + async def test_endpoint_none_profile( zha_gateway: Gateway, caplog: pytest.LogCaptureFixture, diff --git a/zha/zigbee/device.py b/zha/zigbee/device.py index d9a6a1cb0..e0ecd94d8 100644 --- a/zha/zigbee/device.py +++ b/zha/zigbee/device.py @@ -371,10 +371,8 @@ def __init__( self._platform_entities: dict[tuple[Platform, str], PlatformEntity] = {} self._pending_entities: list[PlatformEntity] = [] - # All entities discovered for this device, including ones removed by a quirk. - # Used for aggregating cluster configs so binding/reporting matches the - # legacy claim-during-discovery flow (which configured handlers even when - # the visible entity was filtered out later). + # Entities retained after quirk suppression, including virtual entities. + # Used for aggregating cluster configs for binding, reporting, and reads. self._discovered_entities: list[PlatformEntity] = [] self._initialized: bool = False self.semaphore: asyncio.Semaphore = asyncio.Semaphore(3) @@ -1087,11 +1085,11 @@ def _discover_new_entities(self) -> None: _LOGGER.exception("Failed to create entity during discovery") continue - self._discovered_entities.append(entity) - if self._is_entity_removed_by_quirk(entity): continue + self._discovered_entities.append(entity) + # Apply any metadata changes from quirks v2 self._apply_entity_metadata_changes(entity)