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 Inovelli VZM36 support and rework manufacturer clusters #2960

Merged
merged 13 commits into from
Feb 12, 2024

Conversation

codyhackw
Copy link
Contributor

@codyhackw codyhackw commented Jan 31, 2024

Proposed change

This change adds support for the Inovelli VZM36 canopy module and re-organizes the __init__.py file to simplify the parameters across devices.

Additional information

I believe the ep_attribute has to stay pointed to the inovelli_vzm31sn_cluster as that's what's referenced within ZHA so changing that would result in a breaking change. In the interest of avoiding that, I've kept it in place.

Checklist

  • The changes are tested and work correctly
  • pre-commit checks pass / the code has been formatted using Black
  • Tests have been added to verify that the new code works

Copy link

codecov bot commented Feb 1, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (97d2734) 87.68% compared to head (1db1cc0) 87.72%.
Report is 4 commits behind head on dev.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #2960      +/-   ##
==========================================
+ Coverage   87.68%   87.72%   +0.04%     
==========================================
  Files         297      298       +1     
  Lines        9084     9119      +35     
==========================================
+ Hits         7965     8000      +35     
  Misses       1119     1119              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@TheJulianJES TheJulianJES added the new quirk Adds support for a new device label Feb 1, 2024
@TheJulianJES TheJulianJES changed the title Adding VZM36 Support and Inovelli cluster rework Add Inovelli VZM36 support and rework manufacturer clusters Feb 1, 2024
cluster_id = 0xFC31
name = "InovelliVZM31SNCluster"
ep_attribute = "inovelli_vzm31sn_cluster"
class Inovelli_Cluster(CustomCluster):
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's preferred to use "CamelCase" / "CapWords" for class names.

Copy link
Collaborator

Choose a reason for hiding this comment

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

From what I can see, cluster_id and ep_attribute is the same for all Inovelli cluster classes.
Can we just put it in this base class then?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Re the class name, are you saying the preference would be to do "InovelliCluster" as opposed to "Inovelli_Cluster"? This was staying consistent to the existing naming, but can definitely change it if needed. Just have to change it in the device-specific imports as well.

Putting cluster_id and ep_attribute in the base class is giving async_initialize errors...it all appears to work, but putting them across each cluster resolved that and is why I ended up splitting them out.

Copy link
Collaborator

Choose a reason for hiding this comment

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

saying the preference would be to do "InovelliCluster" as opposed to "Inovelli_Cluster"?

Yes. That's preferred.

Putting cluster_id and ep_attribute in the base class is giving async_initialize errors...it all appears to work, but putting them across each cluster resolved that and is why I ended up splitting them out.

Weird. There shouldn't be any difference. Are you sure it wasn't just some connectivity issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updating all the classes, thanks for the clarification!

And yeah agreed it's weird, just re-tested. In 2024.2.0 it no longer shows up as a warning, but it's still in the logs -

2024-02-09 08:05:45.026 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0x90CF:1:0xfc31]: failed to get attributes '['power_type', 'switch_type', 'button_delay', 'smart_bulb_mode', 'local_protection']' on 'inovelli_vzm31sn_cluster' cluster: 
2024-02-09 08:05:45.027 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0x90CF:1:0x0019]: initializing cluster handler: from_cache: False
2024-02-09 08:05:45.027 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0x90CF:1:0x0019]: initializing cached cluster handler attributes: ['current_file_version']
2024-02-09 08:05:45.027 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0x90CF:1:0x0019]: Reading attributes in chunks: ['current_file_version']
2024-02-09 08:05:45.027 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0x90CF:1:0x0019]: finished cluster handler initialization
2024-02-09 08:05:45.082 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0x90CF:1:0x0006]: 'async_initialize' stage succeeded
2024-02-09 08:05:45.082 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0x90CF:1:0x0008]: 'async_initialize' stage succeeded
2024-02-09 08:05:45.082 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0x90CF:1:0x0000]: 'async_initialize' stage succeeded
2024-02-09 08:05:45.082 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0x90CF:1:0x0b04]: 'async_initialize' stage succeeded
2024-02-09 08:05:45.082 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0x90CF:1:0x0003]: 'async_initialize' stage succeeded
2024-02-09 08:05:45.083 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0x90CF:1:0x0702]: 'async_initialize' stage succeeded
2024-02-09 08:05:45.083 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0x90CF:1:0x0019]: 'async_initialize' stage succeeded
2024-02-09 08:05:45.083 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0x90CF:1:0xfc31]: 'async_initialize' stage failed: 

Copy link
Collaborator

Choose a reason for hiding this comment

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

The log level was changed indeed. Are there more (debug) log messages when zigpy is also set to debug level?
There's no reason I can see why this could happen. Setting cluster_id, name, and ep_attribute in the "base class" vs the one inheriting that doesn't make a difference.
Can you double-confirm that the error happens every time? And not every time when set in the base classes?

Also, did you check that all attributes set here are correct?
https://github.com/home-assistant/core/blob/567a179084e0226a45d1db01ffb5d4e2e37f3d8c/homeassistant/components/zha/core/cluster_handlers/manufacturerspecific.py#L249-L253
(There might be more info in zigpy debug logs)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've had both zigpy and zhaquirks set to debug while trying to figure out what's going on and haven't seen anything relevant from zigpy unfortunately. Confirmed I end up with at least one Inovelli device giving that error every time. It's not all of them, and the devices do still seem to work, but I do get at least one log message in 100% of my tests but I don't when I have them set as in the current PR state. I'm not certain why that is because I'd expect it to be the same.

I did also double check the attributes, those all check out, I do find it interesting that the attributes that error are split between the base and one inheriting, but not sure if that's relevant?

Copy link
Collaborator

@TheJulianJES TheJulianJES Feb 11, 2024

Choose a reason for hiding this comment

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

Possibly related comment: #2960 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to that and was still getting them, however when flipping back to how the PR is currently, I also replicated it once...so I'm just going to chalk it up to my network? Not entirely sure what's causing it, but if it happens in both scenarios it's likely unrelated. I'll move these to the base class and thanks for the ideas in trying to narrow it down.

name = "InovelliVZM31SNCluster"
ep_attribute = "inovelli_vzm31sn_cluster"
class Inovelli_Cluster(CustomCluster):
"""Inovelli base cluster."""

attributes = {
0x0001: ("dimming_speed_up_remote", t.uint8_t, True),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not for this PR, but we need to switch to the new zigpy AttributeDefs style at some point.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Again, no need to do it in this PR already, but saving a code sample here for reference how it would look:

class LegrandCluster(CustomCluster):
"""LegrandCluster."""
cluster_id = MANUFACTURER_SPECIFIC_CLUSTER_ID
name = "LegrandCluster"
ep_attribute = "legrand_cluster"
class AttributeDefs(BaseAttributeDefs):
device_mode = ZCLAttributeDef(
id=0x0000,
type=t.data16, # DeviceMode
is_manufacturer_specific=True,
)
led_dark = ZCLAttributeDef(
id=0x0001,
type=t.Bool,
is_manufacturer_specific=True,
)

Comment on lines 203 to 205
attributes = {
key: InovelliCluster.attributes[key] for key in InovelliCluster.attributes
}
Copy link
Collaborator

@TheJulianJES TheJulianJES Feb 11, 2024

Choose a reason for hiding this comment

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

Can you use:

attributes = InovelliCluster.attributes.copy()

Please also test if you still have the initialization error then.
... although there shouldn't be a difference I think. But still, use the .copy() one now that attributes no longer need to removed, as it's what we're using "everywhere" already.

name = "InovelliVZM31SNCluster"

attributes = InovelliCluster.attributes.copy()

Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you also remove this empty line between attributes = ... and attributes.update(... everywhere?
(To follow what other quirks do)

Comment on lines 80 to 82
AUX_ON = "Aux Up"
AUX_OFF = "Aux Down"
AUX_CONFIG = "Aux Config"
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think these should follow HA standards and be "Aux up", "Aux down", "Aux config"?

Copy link
Collaborator

@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, thanks!

@TheJulianJES TheJulianJES merged commit 0df6f2b into zigpy:dev Feb 12, 2024
14 checks passed
lgraf pushed a commit to lgraf/zha-device-handlers that referenced this pull request May 6, 2024
@codyhackw codyhackw deleted the Inovelli-VZM36 branch June 26, 2024 12:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new quirk Adds support for a new device
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants