From 7e20a8f59f1b172bf25c093228172124f3e996e3 Mon Sep 17 00:00:00 2001 From: TheJulianJES Date: Wed, 26 Nov 2025 02:26:04 +0100 Subject: [PATCH 1/4] Use quirks v2 exposed features --- zha/zigbee/device.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/zha/zigbee/device.py b/zha/zigbee/device.py index 642421526..5282c37d8 100644 --- a/zha/zigbee/device.py +++ b/zha/zigbee/device.py @@ -272,6 +272,11 @@ def __init__( qid: set[str] | str = getattr(self._zigpy_device, ATTR_QUIRK_ID, set()) self.exposes_features: set[str] = {qid} if isinstance(qid, str) else set(qid) + # add v2 quirk exposed features + if self.quirk_metadata is not None: + for feature in self.quirk_metadata.exposes_features: + self.exposes_features.add(feature.feature) + self._power_config_ch: ClusterHandler | None = None self._identify_ch: ClusterHandler | None = None self._basic_ch: ClusterHandler | None = None From c6f4bc3c7079dcb242278990c21f09ec090322c2 Mon Sep 17 00:00:00 2001 From: TheJulianJES Date: Wed, 26 Nov 2025 02:27:21 +0100 Subject: [PATCH 2/4] Use `set.update` with generator expression --- zha/zigbee/device.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zha/zigbee/device.py b/zha/zigbee/device.py index 5282c37d8..f33fb1b1f 100644 --- a/zha/zigbee/device.py +++ b/zha/zigbee/device.py @@ -274,8 +274,9 @@ def __init__( # add v2 quirk exposed features if self.quirk_metadata is not None: - for feature in self.quirk_metadata.exposes_features: - self.exposes_features.add(feature.feature) + self.exposes_features.update( + f.feature for f in self.quirk_metadata.exposes_features + ) self._power_config_ch: ClusterHandler | None = None self._identify_ch: ClusterHandler | None = None From 547f4dffe4de8b726cce4ec121b9a06e6d5eb781 Mon Sep 17 00:00:00 2001 From: TheJulianJES Date: Wed, 26 Nov 2025 02:34:08 +0100 Subject: [PATCH 3/4] Add test --- tests/test_device.py | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/tests/test_device.py b/tests/test_device.py index 7609010ef..0f1876a67 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -11,7 +11,12 @@ from zigpy.exceptions import ZigbeeException import zigpy.profiles.zha from zigpy.quirks.registry import DeviceRegistry -from zigpy.quirks.v2 import DeviceAlertLevel, DeviceAlertMetadata, QuirkBuilder +from zigpy.quirks.v2 import ( + DeviceAlertLevel, + DeviceAlertMetadata, + ExposesFeatureMetadata, + QuirkBuilder, +) from zigpy.quirks.v2.homeassistant import EntityType from zigpy.quirks.v2.homeassistant.sensor import SensorDeviceClass, SensorStateClass import zigpy.types @@ -1123,6 +1128,36 @@ async def test_quirks_v2_translation_placeholders(zha_gateway: Gateway) -> None: ) +async def test_quirks_v2_exposed_features(zha_gateway: Gateway) -> None: + """Test quirks v2 exposed features.""" + registry = DeviceRegistry() + + ( + QuirkBuilder("CentraLite", "3405-L", registry=registry) + .exposes_feature("some_feature") + .exposes_feature("another_feature", config={"option": True}) + .add_to_registry() + ) + + zigpy_dev = registry.get_device( + await zigpy_device_from_json( + zha_gateway.application_controller, + "tests/data/devices/centralite-3405-l.json", + ) + ) + + zha_device = await join_zigpy_device(zha_gateway, zigpy_dev) + + # can access the set of exposed features, similar to v1 quirks + assert zha_device.exposes_features == {"some_feature", "another_feature"} + + # can access the quirk metadata for config features for now + assert zha_device.quirk_metadata.exposes_features == ( + ExposesFeatureMetadata(feature="some_feature"), + ExposesFeatureMetadata(feature="another_feature", config={"option": True}), + ) + + async def test_join_binding_reporting(zha_gateway: Gateway) -> None: """Test that new joins go through binding and attribute reporting.""" From 046b34cae30b4d847e6a82a6dbba511010c7d5cf Mon Sep 17 00:00:00 2001 From: TheJulianJES Date: Wed, 26 Nov 2025 03:10:23 +0100 Subject: [PATCH 4/4] Adjust comment --- tests/test_device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_device.py b/tests/test_device.py index 0f1876a67..050bce943 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -1151,7 +1151,7 @@ async def test_quirks_v2_exposed_features(zha_gateway: Gateway) -> None: # can access the set of exposed features, similar to v1 quirks assert zha_device.exposes_features == {"some_feature", "another_feature"} - # can access the quirk metadata for config features for now + # can access the quirk metadata for config features assert zha_device.quirk_metadata.exposes_features == ( ExposesFeatureMetadata(feature="some_feature"), ExposesFeatureMetadata(feature="another_feature", config={"option": True}),