From c3222ef733ecbd1325352fcaa52d2c8ab4dd7f06 Mon Sep 17 00:00:00 2001
From: "David F. Mulcahey" <david.mulcahey@me.com>
Date: Sun, 28 Jan 2024 13:28:06 -0500
Subject: [PATCH] Fix statuses for ZHA attribute reporting configuration event
 (#108532)

Co-authored-by: TheJulianJES <TheJulianJES@users.noreply.github.com>
---
 .../zha/core/cluster_handlers/__init__.py     | 38 +++++++++++++------
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/homeassistant/components/zha/core/cluster_handlers/__init__.py b/homeassistant/components/zha/core/cluster_handlers/__init__.py
index c72d84adecd..65137d683de 100644
--- a/homeassistant/components/zha/core/cluster_handlers/__init__.py
+++ b/homeassistant/components/zha/core/cluster_handlers/__init__.py
@@ -262,7 +262,7 @@ class ClusterHandler(LogMixin):
                 "id": attr,
                 "name": attr_name,
                 "change": config[2],
-                "success": False,
+                "status": None,
             }
 
         to_configure = [*self.REPORT_CONFIG]
@@ -274,10 +274,7 @@ class ClusterHandler(LogMixin):
             reports = {rec["attr"]: rec["config"] for rec in chunk}
             try:
                 res = await self.cluster.configure_reporting_multiple(reports, **kwargs)
-                self._configure_reporting_status(reports, res[0])
-                # if we get a response, then it's a success
-                for attr_stat in event_data.values():
-                    attr_stat["success"] = True
+                self._configure_reporting_status(reports, res[0], event_data)
             except (zigpy.exceptions.ZigbeeException, asyncio.TimeoutError) as ex:
                 self.debug(
                     "failed to set reporting on '%s' cluster for: %s",
@@ -304,7 +301,10 @@ class ClusterHandler(LogMixin):
         )
 
     def _configure_reporting_status(
-        self, attrs: dict[str, tuple[int, int, float | int]], res: list | tuple
+        self,
+        attrs: dict[str, tuple[int, int, float | int]],
+        res: list | tuple,
+        event_data: dict[str, dict[str, Any]],
     ) -> None:
         """Parse configure reporting result."""
         if isinstance(res, (Exception, ConfigureReportingResponseRecord)):
@@ -315,6 +315,8 @@ class ClusterHandler(LogMixin):
                 self.name,
                 res,
             )
+            for attr in attrs:
+                event_data[attr]["status"] = Status.FAILURE.name
             return
         if res[0].status == Status.SUCCESS and len(res) == 1:
             self.debug(
@@ -323,24 +325,38 @@ class ClusterHandler(LogMixin):
                 self.name,
                 res,
             )
+            # 2.5.8.1.3 Status Field
+            # The status field specifies the status of the Configure Reporting operation attempted on this attribute, as detailed in 2.5.7.3.
+            # Note that attribute status records are not included for successfully configured 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
             return
 
+        for record in res:
+            event_data[self.cluster.find_attribute(record.attrid).name][
+                "status"
+            ] = record.status.name
         failed = [
             self.cluster.find_attribute(record.attrid).name
             for record in res
             if record.status != Status.SUCCESS
         ]
-        self.debug(
-            "Successfully configured reporting for '%s' on '%s' cluster",
-            set(attrs) - set(failed),
-            self.name,
-        )
         self.debug(
             "Failed to configure reporting for '%s' on '%s' cluster: %s",
             failed,
             self.name,
             res,
         )
+        success = set(attrs) - set(failed)
+        self.debug(
+            "Successfully configured reporting for '%s' on '%s' cluster",
+            set(attrs) - set(failed),
+            self.name,
+        )
+        for attr in success:
+            event_data[attr]["status"] = Status.SUCCESS.name
 
     async def async_configure(self) -> None:
         """Set cluster binding and attribute reporting."""
-- 
GitLab