-
Notifications
You must be signed in to change notification settings - Fork 69
Fix configuring attribute reporting #648
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
Changes from 11 commits
b954341
3da1161
1e96ec6
b2c551e
def5a7a
6d3269c
c697339
295872b
ac89d9b
5e04a5b
fa797c3
182a8bc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,7 @@ | |
| Status, | ||
| ZCLAttributeDef, | ||
| ) | ||
| from zigpy.zcl.helpers import ReportingConfig | ||
|
|
||
| from zha.application.const import ( | ||
| ZHA_CLUSTER_HANDLER_MSG, | ||
|
|
@@ -369,12 +370,6 @@ async def configure_reporting(self) -> None: | |
| devices are unreachable. | ||
| """ | ||
| event_data = {} | ||
| kwargs = {} | ||
| if ( | ||
| self.cluster.cluster_id >= 0xFC00 | ||
| and self._endpoint.device.manufacturer_code | ||
| ): | ||
| kwargs["manufacturer"] = self._endpoint.device.manufacturer_code | ||
|
|
||
| for attr_report in self.REPORT_CONFIG: | ||
| attr, config = attr_report["attr"], attr_report["config"] | ||
|
|
@@ -399,12 +394,17 @@ async def configure_reporting(self) -> None: | |
| to_configure[REPORT_CONFIG_ATTR_PER_REQ:], | ||
| ) | ||
| while chunk: | ||
| reports = {rec["attr"]: rec["config"] for rec in chunk} | ||
| reports = { | ||
| self.cluster.find_attribute(rec["attr"]): ReportingConfig( | ||
| *rec["config"] | ||
| ) | ||
| for rec in chunk | ||
| } | ||
| try: | ||
| res = await RETRYABLE_REQUEST_DECORATOR( | ||
| self.cluster.configure_reporting_multiple | ||
| )(reports, **kwargs) | ||
| self._configure_reporting_status(reports, res[0], event_data) | ||
| )(reports) | ||
| self._configure_reporting_status(reports, res, event_data) | ||
| except (zigpy.exceptions.ZigbeeException, TimeoutError) as ex: | ||
| self.debug( | ||
| "failed to set reporting on '%s' cluster for: %s", | ||
|
|
@@ -429,26 +429,27 @@ async def configure_reporting(self) -> None: | |
|
|
||
| def _configure_reporting_status( | ||
| self, | ||
| attrs: dict[str, tuple[int, int, float | int]], | ||
| res: list | tuple, | ||
| attrs: dict[ZCLAttributeDef, ReportingConfig], | ||
| res: list[ConfigureReportingResponseRecord], | ||
| event_data: dict[str, dict[str, Any]], | ||
| ) -> None: | ||
| """Parse configure reporting result.""" | ||
| if isinstance(res, (Exception, ConfigureReportingResponseRecord)): | ||
| attr_names = {attr_def.name for attr_def in attrs} | ||
| if not res or isinstance(res, (Exception, ConfigureReportingResponseRecord)): | ||
|
||
| # assume default response | ||
| self.debug( | ||
| "attr reporting for '%s' on '%s': %s", | ||
| attrs, | ||
| attr_names, | ||
| self.name, | ||
| res, | ||
| ) | ||
| for attr in attrs: | ||
| event_data[attr]["status"] = Status.FAILURE.name | ||
| for attr_name in attr_names: | ||
| event_data[attr_name]["status"] = Status.FAILURE.name | ||
| return | ||
|
Comment on lines
+438
to
447
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Technically, zigpy should also never return an empty list. Do we want to keep this failure case in case zigpy breaks again, so we report all attributes as failed to configure then? If we remove this, they'd report as being successfully configured otherwise, which also isn't great. But this should never happen (again), soo..
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can keep it in. In the near future I'd like to persist the attribute configuration state in the database so this code likely will be reworked anyways. |
||
| if res[0].status == Status.SUCCESS and len(res) == 1: | ||
TheJulianJES marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if len(res) == 1 and res[0].status == Status.SUCCESS: | ||
| self.debug( | ||
| "Successfully configured reporting for '%s' on '%s' cluster: %s", | ||
| attrs, | ||
| attr_names, | ||
| self.name, | ||
| res, | ||
| ) | ||
|
|
@@ -458,8 +459,8 @@ def _configure_reporting_status( | |
| # attributes, in order to save bandwidth. In the case of successful configuration of all attributes, | ||
| # only a single attribute status record SHALL be included in the command, with the status field set to | ||
| # SUCCESS and the direction and attribute identifier fields omitted. | ||
| for attr in attrs: | ||
| event_data[attr]["status"] = Status.SUCCESS.name | ||
| for attr_name in attr_names: | ||
| event_data[attr_name]["status"] = Status.SUCCESS.name | ||
| return | ||
|
|
||
| for record in res: | ||
|
|
@@ -477,14 +478,14 @@ def _configure_reporting_status( | |
| self.name, | ||
| res, | ||
| ) | ||
| success = set(attrs) - set(failed) | ||
| success = attr_names - set(failed) | ||
| self.debug( | ||
| "Successfully configured reporting for '%s' on '%s' cluster", | ||
| set(attrs) - set(failed), | ||
| success, | ||
| self.name, | ||
| ) | ||
| for attr in success: | ||
| event_data[attr]["status"] = Status.SUCCESS.name | ||
| for attr_name in success: | ||
| event_data[attr_name]["status"] = Status.SUCCESS.name | ||
TheJulianJES marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| async def async_configure(self) -> None: | ||
| """Set cluster binding and attribute reporting.""" | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.