Experiment (DO NOT MERGE) - Collapse ClusterHandler objects into PlatformEntity objects#653
Experiment (DO NOT MERGE) - Collapse ClusterHandler objects into PlatformEntity objects#653
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #653 +/- ##
==========================================
- Coverage 97.41% 96.74% -0.67%
==========================================
Files 62 49 -13
Lines 10724 10553 -171
==========================================
- Hits 10447 10210 -237
- Misses 277 343 +66 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| ZHA_CLUSTER_HANDLER_CFG_DONE, | ||
| ClusterHandlerConfigurationComplete( | ||
| ZHA_CLUSTER_CFG_DONE, | ||
| ClusterConfigurationComplete( |
| super().__init__(clusters, endpoint, device, **kwargs) | ||
| self._cluster = clusters[0] |
| if ENTITY_METADATA in kwargs: | ||
| self._init_from_quirks_metadata(kwargs[ENTITY_METADATA]) | ||
| super().__init__(cluster_handlers, endpoint, device, **kwargs) | ||
| super().__init__(clusters, endpoint, device, **kwargs) | ||
| self._cluster = clusters[0] |
There was a problem hiding this comment.
different sequencing
| super().__init__(clusters, endpoint, device, **kwargs) | ||
| self._cluster = clusters[0] |
| # this is a cached read to get the value for state mgt so there is no double read | ||
| attr_value = await self._cluster_handler.get_attribute_value(attribute) | ||
| attribute = self._attribute_name |
| @@ -342,18 +423,38 @@ def parse(value: bool | int) -> bool: | |||
| async def async_update(self) -> None: | |||
| """Attempt to retrieve on off state from the IAS Zone sensor.""" | |||
| await PlatformEntity.async_update(self) | |||
| attribute = self._attribute_name | |||
There was a problem hiding this comment.
wonder why it kept creating vars for this...
|
|
||
|
|
||
| def discover_entities_for_endpoint(endpoint: Endpoint) -> Iterator[PlatformEntity]: | ||
| def discover_entities_for_endpoint(endpoint: Endpoint) -> Iterator[PlatformEntity]: # noqa: C901 |
| @@ -173,13 +199,13 @@ class DeviceFirmwareInfoUpdatedEvent: | |||
|
|
|||
|
|
|||
| @dataclass(kw_only=True, frozen=True) | |||
| class ClusterHandlerConfigurationComplete: | |||
| """Event generated when all cluster handlers are configured.""" | |||
| class ClusterConfigurationComplete: | |||
There was a problem hiding this comment.
wonder if this changes event shapes for HA
| def cluster_handlers_by_name(self) -> dict[str, ClusterHandler]: | ||
| """Return cluster handlers indexed by name.""" | ||
| return {ch.name: ch for ch in self._all_cluster_handlers.values()} | ||
| @property |
| def client_cluster_handlers_by_name(self) -> dict[str, ClientClusterHandler]: | ||
| """Return client cluster handlers indexed by name.""" | ||
| return {ch.name: ch for ch in self._client_cluster_handlers.values()} | ||
| @property |
|
|
||
| return f"0x{command_id:02X}" | ||
|
|
||
| def handle_cluster_command( |
There was a problem hiding this comment.
ooh this is kinda ugly... wonder why these were all grouped together...
There was a problem hiding this comment.
I wonder if we may need to implement event entities to avoid remote logic from having to be handled like this... 🤔
zha/zigbee/endpoint.py
Outdated
|
|
||
| async def _execute_handler_tasks( | ||
| self, func_name: str, *args: Any, max_concurrency: int | None = None | ||
| def _handle_smartthings_attribute_event( |
… fallback left for remotes for now
High-Level Summary
This is a major architectural migration from cluster-handler-centric runtime to a direct cluster-native runtime.
It is a systemic refactor that moves ownership of bind/report/init behavior and event wiring away from
zha/zigbee/cluster_handlers/*into endpoint/device/entity flows.What Changed (Core Architecture)
zha/zigbee/cluster_handlers/is deleted.zha/zigbee/cluster_policies.pyzha/zigbee/const.pyZHA_CLUSTER_HANDLER_*toZHA_CLUSTER_*inzha/application/const.py(compat string payloads preserved where needed).ClusterHandlerMatchreplaced byClusterMatchinzha/application/platforms/__init__.py.PlatformEntitynow takesclustersand builds maps directly from in/out cluster collections.clusters(notcluster_handlers) through diagnostics info objects.REPORT_CONFIGZCL_INIT_ATTRSzha/application/discovery.pynow matches entity classes via endpoint cluster names/IDs, not handler registries.claim_clusters(...)path).zha/zigbee/endpoint.pygained cluster-native bind/configure/init orchestration:zha/zigbee/device.pynow aggregates pending entity requirements and applies them before configure/init.zha/application/gateway.pyintroduces initialization generation tokens to prevent stale async completions from mutating current state.zha/zigbee/group.pyadds lock-guarded reconciliation and more defensive subscription/entity cleanup.zha/application/helpers.py.Platform Layer Migration Pattern
Across platform implementations (examples:
zha/application/platforms/fan/__init__.py,zha/application/platforms/climate/__init__.py,zha/application/platforms/binary_sensor/__init__.py,zha/application/platforms/alarm_control_panel/__init__.py,zha/application/platforms/lock/__init__.py,zha/application/platforms/siren.py):cluster_handlerstoclusters._cluster_handler_matchto_cluster_match.AttributeReadEvent,AttributeReportedEvent,AttributeUpdatedEvent,AttributeWrittenEvent).REPORT_CONFIG/ZCL_INIT_ATTRS.This is mostly mechanical in simpler platforms, but in alarm/siren/lock it includes behavioral logic migration that is review-critical.
Tests and Fixture Churn
tests/test_cluster_handlers.pyremoved.tests/test_cluster_lifecycle.pyadded for new endpoint/entity requirement aggregation and compatibility semantics.tests/test_gateway.pyandtests/test_device.pyfor async race hardening, pending entity handling, and cleanup behavior.tests/data/devices/:cluster_handlersfields replaced byclustersThis explains the very large deletion count: fixture reshaping dominates diff volume.
Commit Intent by Sequence (Review Narrative)
Review Focus Areas (Most Risk)
zha/zigbee/endpoint.pyRisk: lifecycle ordering and parity with old handler side effects.
zha/zigbee/device.pyRisk: pending requirement merge semantics, ZDO transition, reconfigure flows.
zha/application/discovery.pyRisk: entity matching/claiming differences and quirks v2 metadata application.
zha/application/gateway.py+zha/zigbee/group.pyRisk: init/reconcile timing behavior and delayed convergence from debouncing.
alarm_control_panel,siren,lock)Risk: command semantics/state translation regressions.
Suggested Review Plan
zha/zigbee/endpoint.py,zha/zigbee/device.py,zha/application/discovery.py.zha/application/gateway.py,zha/zigbee/group.py.alarm_control_panel,siren,lock, then broad mechanical platform files.