Skip to content
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

Add support for ZHA entities exposed by Zigpy quirks #111176

Merged
merged 44 commits into from
Feb 29, 2024

Conversation

dmulcahey
Copy link
Contributor

@dmulcahey dmulcahey commented Feb 23, 2024

Proposed change

This PR adds support for entities exposed by the next iteration of Zigpy quirks. Needs to be rebased after #111175 and #111159 are merged.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

  • This PR fixes or closes issue: fixes #
  • This PR is related to issue:
  • Link to documentation pull request:

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies - a link to the changelog, or at minimum a diff between library versions is added to the PR description.
  • Untested files have been added to .coveragerc.

To help with the load of incoming pull requests:

@home-assistant
Copy link

Hey there @Adminiuga, @puddly, @TheJulianJES, mind taking a look at this pull request as it has been labeled with an integration (zha) you are listed as a code owner for? Thanks!

Code owner commands

Code owners of zha can trigger bot actions by commenting:

  • @home-assistant close Closes the pull request.
  • @home-assistant rename Awesome new title Renames the pull request.
  • @home-assistant reopen Reopen the pull request.
  • @home-assistant unassign zha Removes the current integration label and assignees on the pull request, add the integration domain after the command.
  • @home-assistant add-label needs-more-information Add a label (needs-more-information, problem in dependency, problem in custom component) to the pull request.
  • @home-assistant remove-label needs-more-information Remove a label (needs-more-information, problem in dependency, problem in custom component) on the pull request.

@dmulcahey dmulcahey marked this pull request as ready for review February 28, 2024 22:02
tests/components/zha/test_discover.py Outdated Show resolved Hide resolved
homeassistant/components/zha/core/discovery.py Outdated Show resolved Hide resolved
homeassistant/components/zha/switch.py Outdated Show resolved Hide resolved
homeassistant/components/zha/select.py Outdated Show resolved Hide resolved
tests/components/zha/test_sensor.py Outdated Show resolved Hide resolved
homeassistant/components/zha/entity.py Show resolved Hide resolved
homeassistant/components/zha/core/discovery.py Outdated Show resolved Hide resolved
tests/components/zha/test_switch.py Show resolved Hide resolved
tests/components/zha/test_discover.py Outdated Show resolved Hide resolved
Copy link
Member

@TheJulianJES TheJulianJES left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but would appreciate if puddly can also have a look 😄

@balloob balloob merged commit 73b6e2b into home-assistant:dev Feb 29, 2024
19 checks passed
balloob pushed a commit that referenced this pull request Feb 29, 2024
* Add counter entities to the ZHA coordinator device

* rework to prepare for non coordinator device counters

* Initial scaffolding to support quirks v2 entities

* update for zigpy changes

* add assertion error message

* clean up test

* update group entity discovery kwargs

* constants and clearer names

* apply custom device configuration

* quirks switches

* quirks select entities

* quirks sensor entities

* update discovery

* move call to super

* add complex quirks v2 discovery test

* remove duplicate replaces

* add quirks v2 button entity support

* add quirks v2 binary sensor entity support

* fix exception in counter entitiy discovery

* oops

* update formatting

* support custom on and off values

* logging

* don't filter out entities quirks says should be created

* fix type alias warnings

* sync up with zigpy changes and additions

* add a binary sensor test

* button coverage

* switch coverage

* initial select coverage

* number coverage

* sensor coverage

* update discovery after rebase

* coverage

* single line

* line lengths

* fix double underscore

* review comments

* set category from quirks in base entity

* line lengths

* move comment

* imports

* simplify

* simplify
@github-actions github-actions bot locked and limited conversation to collaborators Mar 1, 2024
Copy link
Member

@MartinHjelmare MartinHjelmare left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the design of this feature is questionable. We want to review the data that is used for the Home Assistant Entity API where the Entity API doesn't allow arbitrary values. That data is now hidden in many cases in a 3rd party library.

self._attr_entity_registry_enabled_default = False

if entity_metadata.translation_key:
self._attr_translation_key = entity_metadata.translation_key
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The translation key must be set with a string from the integration since it must map to a string in the strings.json file. We don't allow setting it directly with data from a 3rd party library.

if number_metadata.step is not None:
self._attr_native_step = number_metadata.step
if number_metadata.unit is not None:
self._attr_native_unit_of_measurement = number_metadata.unit
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Units are preferred to use the Home Assistant constants as far as possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are using clones of the HA units in the lib

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still prefer using the Home Assistant constants when possible.

ZhaEntity._init_from_quirks_metadata(self, entity_metadata) # pylint: disable=protected-access
sensor_metadata: ZCLEnumMetadata = entity_metadata.entity_metadata
self._attribute_name = sensor_metadata.attribute_name
self._enum = sensor_metadata.enum
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Side note: Where is the options property set for the enum sensors with device class enum?

https://developers.home-assistant.io/docs/core/entity/sensor#available-device-classes

Copy link
Contributor Author

@dmulcahey dmulcahey Mar 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Options are computed from the enum values and that has not been changed by this PR

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the options set?

"""Init this entity from the quirks metadata."""
ZhaEntity._init_from_quirks_metadata(self, entity_metadata) # pylint: disable=protected-access
sensor_metadata: ZCLEnumMetadata = entity_metadata.entity_metadata
self._attribute_name = sensor_metadata.attribute_name
Copy link
Member

@MartinHjelmare MartinHjelmare Mar 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will create extra state attributes that we don't see the name of. We want to review all extra attributes before they are added. There must at minimum be a map in the integration for these.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the ZCL attribute for the sensor and has nothing to do with HA state extra attributes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The attribute name is at least used here for an extra state attribute:

max_attr_name = f"{self._attribute_name}_max"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That’s in a completely different concrete class… and the attribute name is hard coded in it:

_attribute_name = "active_power"

Copy link
Member

@MartinHjelmare MartinHjelmare Mar 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class constructor, the __init__ method, will overwrite the set class attributes if an instance attribute with the same name is set. It looks like we could potentially overwrite all entity classes that inherit a constructor with the quirks interface. I don't see any guard for that.

Copy link
Contributor Author

@dmulcahey dmulcahey Mar 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There won’t be any metadata in these cases. I can add a check to them that if it is present they also throw a hard error… Or I can move the metadata handling to a new extension of the base and point all quirks stuff at that so none of the other classes have to worry about this… couple ways to solve it.

@home-assistant home-assistant unlocked this conversation Mar 4, 2024
@dmulcahey
Copy link
Contributor Author

dmulcahey commented Mar 4, 2024

I think the design of this feature is questionable. We want to review the data that is used for the Home Assistant Entity API where the Entity API doesn't allow arbitrary values. That data is now hidden in many cases in a 3rd party library.

How do you review this for mqtt? It seems to work similarly to what is done here? These changes were made to simplify user contributions and to remove boilerplate code. For instance:

@MULTI_MATCH(cluster_handler_names="ikea_airpurifier")
what is the benefit in having someone define every class below this point when it can be handled the way we have in this PR.

I think some further work can be done to validate that we aren’t using arbitrary values for unit and device classes / state classes and throwing a hard error if they aren’t part of the HA enums. The only thing we can’t solve like that is translation key. For that I think we can add a unit test in ZHA that ensures every supplied key from quirks is in strings.json. Wouldn’t that solve the other issue?

I’d rather drop the feature in its entirety If we are saying we are going to be forced to maintain boilerplate maps in every platform in ZHA to essentially copy this info to HA. It defeats the entire purpose of what we were trying to accomplish. We are trying to make it easier to contribute for users on the Zigpy side (similar to how easy it is to contribute to z2m they also don’t have these requirements…)

@MartinHjelmare
Copy link
Member

I understand the reason behind the feature, but I don't think this solution is in line with how we want to review integrations in Home Assistant. We want to make sure that every integration follows our design and does the right thing. That's not possible if all the data is hidden in a 3rd party library.

Although we validate many things today, we can't validate everything automatically. Some things still require a reviewer to be able to read the code and check that the guidelines are followed. Examples include using entity category and extra state attributes.

@dmulcahey
Copy link
Contributor Author

I understand the reason behind the feature, but I don't think this solution is in line with how we want to review integrations in Home Assistant. We want to make sure that every integration follows our design and does the right thing. That's not possible if all the data is hidden in a 3rd party library.

Although we validate many things today, we can't validate everything automatically. Some things still require a reviewer to be able to read the code and check that the guidelines are followed. Examples include using entity category and extra state attributes.

How is this done today for z2m (or any mqtt integration)? We can’t have it both ways… ZHA is immediately at a disadvantage with contributions if we have to jump through hoops that they don’t for user contributions. I’m willing to do the work to lock this down with validation etc… but if we are saying this isn’t possible (I fail to see how it isn’t) 🤷🏻‍♂️

@MartinHjelmare
Copy link
Member

The MQTT integration is an exception since it's configured by the user and not written by the developer.

@dmulcahey
Copy link
Contributor Author

I think I can shield all of this in the classes… I can validate all units, classes, categories, etc against the enums in HA, I can add a unit test to ensure all supported metadata translation keys exist, I can split the class hierarchies so that entities derived from metadata can’t “change” things in extensions. What is still a problem at that point?

@MartinHjelmare
Copy link
Member

The problem is that we can't review what entities are created and how the entity API is used. Ie the final combination of all the features of the entity is hidden from the reviewer. Home Assistant is no longer in control of how the entity is created.

@dmulcahey
Copy link
Contributor Author

The problem is that we can't review what entities are created and how the entity API is used. Ie the final combination of all the features of the entity is hidden from the reviewer.

Sure the final combination of unit, translation key, enabled / disabled by default may not always be visible… but why would it need to be? None of that would violate / abuse HA’s architecture in any way. The entity classes in ZHA still control everything and they are reviewed…

Home Assistant is no longer in control of how the entity is created.

This is patently false. The entity classes are still in HA and nothing can be done w/o changing them. There is nothing magical in the metadata coming from the library and I have offered to validate everything on the HA side.

This entire discussion boils down to just not liking how this is done. I have yet to read anything concrete in the form of solutions other than duplicate all possible combinations of the metadata into HA which defeats the purpose. Let’s take the remainder of this discussion offline as I don’t think we are getting anywhere useful like this.

@github-actions github-actions bot locked and limited conversation to collaborators Mar 5, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants