New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Match ZHA Custom ClusterHandler on a Custom Cluster using a unique id for the quirk #101709
Match ZHA Custom ClusterHandler on a Custom Cluster using a unique id for the quirk #101709
Conversation
Hey there @dmulcahey, @Adminiuga, @puddly, mind taking a look at this pull request as it has been labeled with an integration ( Code owner commandsCode owners of
|
I haven't forgotten about your Danfoss PR. Like you already know, ZHA currently provides "quirk matching" which isn't ideal at all, as it matches per part of a path (which doesn't even have to be unique now) and refactoring can easily change that path. It also doesn't allow two quirks to provide the same entities without registering the quirk twice in ZHA. I've already worked a bit on what I proposed in your other PR regarding quirk ID matching (which replaces the currently unused quirk path matching):
puddly mentioned that he'd like to allow creating entities from zha-quirks directly, but I'm not sure what the status is on that at the moment. If that approach is fine, it should unblock your Danfoss PR, as well as allowing us to tidy up stuff like this (one quirk ID for all plugs sharing this functionaltiy): core/homeassistant/components/zha/core/cluster_handlers/manufacturerspecific.py Lines 76 to 97 in 66f43eb
core/homeassistant/components/zha/select.py Lines 255 to 275 in 66f43eb
|
What I wrote above doesn't invalidate this PR though (from looking at it), as yours allows "overriding cluster handlers matches" for quirks. |
Looking at TheJulianJES Design Doc and Code, it seems like this PR follows the same format for the quirk_id. That is nice. |
Instead of using shared strings between quirks and ZHA, what do you think about directly importing and registering based on the quirk class itself? import zhaquirks.xiaomi.aqara
...
@registries.CUSTOM_CLUSTER_HANDLER_REGISTRY.register(
DoorLock.cluster_id, quirk=zhaquirks.xiaomi.aqara.XiaomiVibrationAQ1
)
class XiaomiVibrationAQ1ClusterHandler(MultistateInput): That way, any breaking changes in zha-quirks will cause HA Core's unit tests to fail. This will also let us more easily, in the future, to migrate entity registration into the same file as the quirk itself. |
On the other hand, non breaking changes to quirks, like re-shuffling module structure (e.g. having all tuya trv quirks moved into tuya.trv.sitterwel_trv) becomes a breaking change |
Yeah. And -- especially common for Tuya -- devices have slightly differing quirk classes that expose the same custom attributes. When matching via quirk class or path, those new quirk classes would also need to be added to HA. Having a string allows multiple quirks to share the same "ID" (from here):
Although not all, many of the Tuya plugs expose the same custom attributes: |
I agree and like this idea. My vote goes for this. |
I think IDs would be the most intuitive as most things right now are matched on IDs/Strings: attribute name with a cluster name. A drawback to this however is: this requires knowledge of other quirks to not accidentally duplicate an ID and these IDs are completely fictional. I think it is important to allow multiple CustomDevice definitions to match on a single ClusterHandler or entity. Importing would be too restrictive for this purpose. For example: path.startswith("tuya.tuya_plugs_type1"). "tuya/tuya_plugs_type1.py" could contain all CustomDevice definitions for all tuya plugs that have the same attributes exposed to home assistant. If wanting to refactor this, it could become all quirks in the directory "tuya/tuya_plugs_type1/" and all quirks could be defined in different files. A drawback to this is however that it requires strict hierarchies to be maintained in zha-quirks, while right now it is quite free as far as I can see. Both would solve the problem in my opinion, but I don't have a very strong preference. |
I think this is mostly fine. This still requires a quirks bump though, as the quirk ID for the Aqara vibration sensor isn't merged into HA yet. Also, we have tests for custom ZHA entity matches (via quirk ID) to check if the quirk ID exists in any quirk: core/tests/components/zha/test_registries.py Lines 552 to 582 in e755dd8
Should we also do the same for custom cluster handlers? |
There hasn't been a new release yet, or should I assume the new version number is going to be 0.0.107? |
@TheJulianJES I have added tests for checking whether the quirk ids and cluster ids exist. When the version bump is done, this passes the tests. |
I think the bump will be in anothet PR, as there are more changes unrelated to this PR. For Danfoss, we have to merge the quirks bump before the Danfoss PR, then rebase your Danfoss PR to use the quirk ID constant, then finally merge the Danfoss PR shortly afterwards. Maybe it would be better if we have another library bump with just the Danfoss quirk changed and then combine that secondary bump with your Danfoss PR? Also, put your PR in draft until the bump is done and it can be merged. (I'll still take a look at the test changes later) |
I forgot. Done.
I think it would be fine to merge both the Danfoss quirk PR and the Xiaomi quirk PR in the same version bump. I can test it locally with some hacks and when the version bump is done, I can use "Update Branch" and it will do the online tests too. |
As time was running a bit short, the quirks bump doesn't include the Danfoss PR for now. |
I don't quite understand what |
I can have a closer look later, but it likely means Codecov thinks your patch isn't covered by tests fully. Try to rebase the PR onto the latest changes from |
Rebase fixed it. Ready for merge. |
@TheJulianJES do we wanna get this in the beta? |
@dmulcahey Yeah, should be fine IMO. It's a requirement for a Danfoss-related PR in the future. This can be merged standalone though. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
@balloob can we get @TheJulianJES added as a HA org member please? |
Because some devices implement Standard Zigbee Clusters differently than the standard prescribes (examples: Xiaomi Vibration AQ1 and Danfoss Ally TRV), there is a need to match ClusterHandlers on a Specific Quirk. Additionally it is conceivable that at some point certain manufacturers use the same Manufacturer Specific Cluster IDs.
This is now done for Vibration AQ1 using an "Ugly Hack" as it is called in the comment. The code for the Danfoss Ally TRV has not been merged as of yet, but an approach explored there overwrites the ClusterHandler in the ZIGBEE_CLUSTER_HANDLER_REGISTRY. Then it only performs certain actions if the ClusterHandler has a specific quirk_class. This has however as a consequence that all Standard Clusters have a custom type, which I consider to be ugly. This PR would implement that functionality without hacks.
Proposed change
Change ZIGBEE_CLUSTER_HANDLER_REGISTRY to type: dict[ClusterId, dict[QuirkId, ClusterHandler]].
Change ProbeEndpoint.discover_by_cluster_id(self, endpoint: Endpoint) and Endpoint.add_all_cluster_handlers(self) to get a CustomCluster from the new ZIGBEE_CLUSTER_HANDLER_REGISTRY.
Remove "Ugly Hack" from ProbeEndpoint.discover_by_cluster_id(self, endpoint: Endpoint) and fulfill that functionality with the new registry.
Currently it creates a new decorator (DictOfDictRegistry) and a new registry (CUSTOM_CLUSTER_HANDLER_REGISTRY), an alternative would be to merge the CUSTOM_CLUSTER_HANDLER_REGISTRY and ZIGBEE_CLUSTER_HANDLER_REGISTRY and have all Standard Clusters be quirk_name=None. This would reduce LOC Added, but increase Lines Changed in this PR.Edit: It does now change the original registry to accomodate the custom cluster handlers.
Because this PR requires a unique ID for a quirk requiring a Custom ClusterHandler, this PR would depend on the addition of this id to zigpy.quirks.__init__.CustomDevice and zhaquirks.xiaomi.aqara.vibration_aq1.VibrationAQ1.
It would also be possible to simply match on the quirk_class as is done in the entity matching code (this is however to my knowledge unused and as TheJulianJES said, not very resistant against refactoring).Edit: Quirk ID matching is now merged.Type of change
Additional information
Checklist
black --fast homeassistant tests
)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest
.requirements_all.txt
.Updated by running
python3 -m script.gen_requirements_all
..coveragerc
.To help with the load of incoming pull requests: