Repository: zigpy/zha-device-handlers

Issue:
Slow startup with xbee
When an xbee or xbee3 device is added to HA, it causes startup time to significantly increase (by about 1 minute). Probably something is waiting for a timeout.
I plan to also look at it myself later.


Discussion:
I think it because it shows as a multi endpoint `on_off` cluster device so HA queries on_off state for each endpoint?
It's something more complicated than that. It looks like it queries something and waits for the response which it wouldn't get. I will investigate a bit later when I have some time.

Resolving patch:
diff --git a/zhaquirks/xbee/__init__.py b/zhaquirks/xbee/__init__.py
--- a/zhaquirks/xbee/__init__.py
+++ b/zhaquirks/xbee/__init__.py
@@ -19,7 +19,7 @@
 import logging
 import struct
 
-from zigpy.quirks import CustomCluster, CustomDevice
+from zigpy.quirks import CustomDevice
 import zigpy.types as t
 from zigpy.zcl import foundation
 from zigpy.zcl.clusters.general import (
@@ -148,7 +148,7 @@ def deserialize(cls, data):
 }
 
 
-class XBeeOnOff(CustomCluster, OnOff):
+class XBeeOnOff(LocalDataCluster, OnOff):
     """XBee on/off cluster."""
 
     async def command(self, command, *args, manufacturer=None, expect_reply=True):
@@ -164,6 +164,10 @@ async def command(self, command, *args, manufacturer=None, expect_reply=True):
         return 0, foundation.Status.SUCCESS
 
 
+class XBeeAnalogInput(LocalDataCluster, AnalogInput):
+    """XBee Analog Input Cluster."""
+
+
 class XBeePWM(LocalDataCluster, AnalogOutput):
     """XBee PWM Cluster."""
 
@@ -216,7 +220,7 @@ def remote_at(self, command, *args, **kwargs):
             )
         _LOGGER.warning("Remote At Command not supported by this coordinator")
 
-    class DigitalIOCluster(CustomCluster, BinaryInput):
+    class DigitalIOCluster(LocalDataCluster, BinaryInput):
         """Digital IO Cluster for the XBee."""
 
         cluster_id = XBEE_IO_CLUSTER
@@ -249,7 +253,7 @@ def handle_cluster_request(self, tsn, command_id, args):
                         # pylint: disable=W0212
                         self._endpoint.device.__getitem__(
                             ENDPOINT_MAP[pin]
-                        ).__getattr__(AnalogInput.ep_attribute)._update_attribute(
+                        ).__getattr__(XBeeAnalogInput.ep_attribute)._update_attribute(
                             ATTR_PRESENT_VALUE,
                             values["analog_samples"][pin]
                             / (10.23 if pin != 7 else 1000),  # supply voltage is in mV
@@ -304,7 +308,8 @@ def deserialize(self, data):
         client_commands = {0x0000: ("io_sample", (IOSample,), False)}
         server_commands = {0x0000: ("io_sample", (IOSample,), False)}
 
-    class EventRelayCluster(EventableCluster, LevelControl):
+    # pylint: disable=too-many-ancestors
+    class EventRelayCluster(EventableCluster, LocalDataCluster, LevelControl):
         """A cluster with cluster_id which is allowed to send events."""
 
         attributes = {}
diff --git a/zhaquirks/xbee/xbee3_io.py b/zhaquirks/xbee/xbee3_io.py
--- a/zhaquirks/xbee/xbee3_io.py
+++ b/zhaquirks/xbee/xbee3_io.py
@@ -1,9 +1,8 @@
 """Class to control Xbee3 device."""
 
 from zigpy.profiles import zha
-from zigpy.zcl.clusters.general import AnalogInput
 
-from . import XBEE_PROFILE_ID, XBeeCommon, XBeeOnOff, XBeePWM
+from . import XBEE_PROFILE_ID, XBeeAnalogInput, XBeeCommon, XBeeOnOff, XBeePWM
 from ..const import DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, OUTPUT_CLUSTERS, PROFILE_ID
 
 
@@ -19,7 +18,7 @@ def __init__(self, application, ieee, nwk, replaces):
                     "model": "AD0/DIO0/Commissioning",
                     DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
                     PROFILE_ID: XBEE_PROFILE_ID,
-                    INPUT_CLUSTERS: [XBeeOnOff, AnalogInput],
+                    INPUT_CLUSTERS: [XBeeOnOff, XBeeAnalogInput],
                     OUTPUT_CLUSTERS: [],
                 },
                 0xD1: {
@@ -27,7 +26,7 @@ def __init__(self, application, ieee, nwk, replaces):
                     "model": "AD1/DIO1/SPI_nATTN",
                     DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
                     PROFILE_ID: XBEE_PROFILE_ID,
-                    INPUT_CLUSTERS: [XBeeOnOff, AnalogInput],
+                    INPUT_CLUSTERS: [XBeeOnOff, XBeeAnalogInput],
                     OUTPUT_CLUSTERS: [],
                 },
                 0xD2: {
@@ -35,7 +34,7 @@ def __init__(self, application, ieee, nwk, replaces):
                     "model": "AD2/DIO2/SPI_CLK",
                     DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
                     PROFILE_ID: XBEE_PROFILE_ID,
-                    INPUT_CLUSTERS: [XBeeOnOff, AnalogInput],
+                    INPUT_CLUSTERS: [XBeeOnOff, XBeeAnalogInput],
                     OUTPUT_CLUSTERS: [],
                 },
                 0xD3: {
@@ -43,7 +42,7 @@ def __init__(self, application, ieee, nwk, replaces):
                     "model": "AD3/DIO3",
                     DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
                     PROFILE_ID: XBEE_PROFILE_ID,
-                    INPUT_CLUSTERS: [XBeeOnOff, AnalogInput],
+                    INPUT_CLUSTERS: [XBeeOnOff, XBeeAnalogInput],
                     OUTPUT_CLUSTERS: [],
                 },
                 0xD4: {
@@ -67,7 +66,7 @@ def __init__(self, application, ieee, nwk, replaces):
                     "model": "SupplyVoltage",
                     DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
                     PROFILE_ID: XBEE_PROFILE_ID,
-                    INPUT_CLUSTERS: [AnalogInput],
+                    INPUT_CLUSTERS: [XBeeAnalogInput],
                     OUTPUT_CLUSTERS: [],
                 },
                 0xD8: {
diff --git a/zhaquirks/xbee/xbee_io.py b/zhaquirks/xbee/xbee_io.py
--- a/zhaquirks/xbee/xbee_io.py
+++ b/zhaquirks/xbee/xbee_io.py
@@ -1,9 +1,8 @@
 """Class to control Xbee device."""
 
 from zigpy.profiles import zha
-from zigpy.zcl.clusters.general import AnalogInput
 
-from . import XBEE_PROFILE_ID, XBeeCommon, XBeeOnOff
+from . import XBEE_PROFILE_ID, XBeeAnalogInput, XBeeCommon, XBeeOnOff
 from ..const import DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, OUTPUT_CLUSTERS, PROFILE_ID
 
 
@@ -19,7 +18,7 @@ def __init__(self, application, ieee, nwk, replaces):
                     "model": "AD0/DIO0/Commissioning",
                     DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
                     PROFILE_ID: XBEE_PROFILE_ID,
-                    INPUT_CLUSTERS: [XBeeOnOff, AnalogInput],
+                    INPUT_CLUSTERS: [XBeeOnOff, XBeeAnalogInput],
                     OUTPUT_CLUSTERS: [],
                 },
                 0xD1: {
@@ -27,7 +26,7 @@ def __init__(self, application, ieee, nwk, replaces):
                     "model": "AD1/DIO1/SPI_nATTN",
                     DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
                     PROFILE_ID: XBEE_PROFILE_ID,
-                    INPUT_CLUSTERS: [XBeeOnOff, AnalogInput],
+                    INPUT_CLUSTERS: [XBeeOnOff, XBeeAnalogInput],
                     OUTPUT_CLUSTERS: [],
                 },
                 0xD2: {
@@ -35,7 +34,7 @@ def __init__(self, application, ieee, nwk, replaces):
                     "model": "AD2/DIO2/SPI_CLK",
                     DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
                     PROFILE_ID: XBEE_PROFILE_ID,
-                    INPUT_CLUSTERS: [XBeeOnOff, AnalogInput],
+                    INPUT_CLUSTERS: [XBeeOnOff, XBeeAnalogInput],
                     OUTPUT_CLUSTERS: [],
                 },
                 0xD3: {
@@ -43,7 +42,7 @@ def __init__(self, application, ieee, nwk, replaces):
                     "model": "AD3/DIO3",
                     DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
                     PROFILE_ID: XBEE_PROFILE_ID,
-                    INPUT_CLUSTERS: [XBeeOnOff, AnalogInput],
+                    INPUT_CLUSTERS: [XBeeOnOff, XBeeAnalogInput],
                     OUTPUT_CLUSTERS: [],
                 },
                 0xD4: {
@@ -67,7 +66,7 @@ def __init__(self, application, ieee, nwk, replaces):
                     "model": "SupplyVoltage",
                     DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
                     PROFILE_ID: XBEE_PROFILE_ID,
-                    INPUT_CLUSTERS: [AnalogInput],
+                    INPUT_CLUSTERS: [XBeeAnalogInput],
                     OUTPUT_CLUSTERS: [],
                 },
                 0xDA: {


Test patch: