Repository: zigpy/zha-device-handlers

Issue:
Some pins is missed in XBee quirks.
/zhaquirks/xbee/__init__.py 
ENDPOINT_MAP = {
    0: 0xD0,
    1: 0xD1,
    2: 0xD2,
    3: 0xD3,
    4: 0xD4,
    5: 0xD5,
    7: 0xD7,
    8: 0xD8,
    9: 0xD9,
    10: 0xDA,
    11: 0xDB,
    12: 0xDC,
}
6 pin is missed;

ENDPOINT_TO_AT = {
    0xD0: "D0",
    0xD1: "D1",
    0xD2: "D2",
    0xD3: "D3",
    0xD4: "D4",
    0xD5: "D5",
    0xD8: "D8",
    0xD9: "D9",
    0xDA: "P0",
    0xDB: "P1",
    0xDC: "P2",
}
D6 and D7 pinns is missed. Why? Is it some serious reason to do that?



Discussion:
Reserved for RTS/CTS?
tagging @Shulyaka 
> 
> 
> Reserved for RTS/CTS?

You may configure it as Input/Output pins in XCTU, it is not denied. Almost all pins in XBee can be configured for something else except of Input/Output. Why that 2 pins must be excluded?
Hi @MaximumSU, what XBee device do you have and with which firmware?
> 
> 
> Hi @MaximumSU, what XBee device do you have and with which firmware?

XBee S2C 
Product Family: XB24C
Function Set: ZIGBEE TH Reg
Firmware version: 4061
I checked the  [zigpy/zigpy-xbee](https://github.com/zigpy/zigpy-xbee/issues/78)  also - it is even worst :-( 
D6, D7, D9, D10, D11, D12, D13, D14 in api.py not exists.
I can see no problem adding more pins, but zigpy-xbee have to add the corresponding commands it first
> I can see no problem adding more pins, but zigpy-xbee have to add the corresponding commands it first

I already opened the issue in zigpy-xbee. Only one quetion for me not cleare - IR IO Sampling Rate. For IC we have bitmask, but not for IR . From the Help of XCTU:

> Set the IO sampling rate to enable periodic sampling. If set >0, all enabled digital IO and analog inputs will be sampled and transmitted every IR milliseconds.

How do you think - they mean, what pin must be not disabled (any role from the list), or it assigned to Input/Output role only? 

> How do you think - they mean, what pin must be not disabled (any role from the list), or it assigned to Input/Output role only?

If a pin is configured as digital i/o, its logical value will be sent in the sample report. If its role is not digital i/o (RSSI PWM, analog input, etc) its status will not be reported. That's what they mean.
> all enabled digital IO and analog inputs will be sampled 

So, analog inputs also sampled...
Sorry, I was incorrect. Analog inputs are also sampled
> I checked the [zigpy/zigpy-xbee](https://github.com/zigpy/zigpy-xbee/issues/78) also - it is even worst :-(
> D6, D7, D9, D10, D11, D12, D13, D14 in api.py not exists.

I'm sorry, it is not correct. Only D9 and D14 is missing in api, all another pins available. I expected to see, for example, "D10" but it is named "P0" in AT commands, so i'm not detected them.

> I can see no problem adding more pins, but zigpy-xbee have to add the corresponding commands it first

The changes for api.py was [commited](https://github.com/zigpy/zigpy-xbee/commit/09fd091a618d382fc4d05757fa554b93ebbb6996).

Resolving patch:
diff --git a/zhaquirks/xbee/__init__.py b/zhaquirks/xbee/__init__.py
--- a/zhaquirks/xbee/__init__.py
+++ b/zhaquirks/xbee/__init__.py
@@ -56,22 +56,6 @@
 # device_type=1 device_version=0 input_clusters=[] output_clusters=[]>
 
 
-ENDPOINT_MAP = {
-    0: 0xD0,
-    1: 0xD1,
-    2: 0xD2,
-    3: 0xD3,
-    4: 0xD4,
-    5: 0xD5,
-    7: 0xD7,
-    8: 0xD8,
-    9: 0xD9,
-    10: 0xDA,
-    11: 0xDB,
-    12: 0xDC,
-}
-
-
 ENDPOINT_TO_AT = {
     0xD0: "D0",
     0xD1: "D1",
@@ -79,11 +63,15 @@
     0xD3: "D3",
     0xD4: "D4",
     0xD5: "D5",
+    0xD6: "D6",
+    0xD7: "D7",
     0xD8: "D8",
     0xD9: "D9",
     0xDA: "P0",
     0xDB: "P1",
     0xDC: "P2",
+    0xDD: "P3",
+    0xDE: "P4",
 }
 
 
@@ -259,9 +247,7 @@ def handle_cluster_request(self, tsn, command_id, args):
                     ]
                     for pin in active_pins:
                         # pylint: disable=W0212
-                        self._endpoint.device.__getitem__(
-                            ENDPOINT_MAP[pin]
-                        ).__getattr__(OnOff.ep_attribute)._update_attribute(
+                        self._endpoint.device[0xD0 + pin].on_off._update_attribute(
                             ATTR_ON_OFF, values["digital_samples"][pin]
                         )
                 if "analog_pins" in values and "analog_samples" in values:
@@ -271,9 +257,9 @@ def handle_cluster_request(self, tsn, command_id, args):
                     ]
                     for pin in active_pins:
                         # pylint: disable=W0212
-                        self._endpoint.device.__getitem__(
-                            ENDPOINT_MAP[pin]
-                        ).__getattr__(XBeeAnalogInput.ep_attribute)._update_attribute(
+                        self._endpoint.device[
+                            0xD0 + pin
+                        ].analog_input._update_attribute(
                             ATTR_PRESENT_VALUE,
                             values["analog_samples"][pin]
                             / (10.23 if pin != 7 else 1000),  # supply voltage is in mV
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
@@ -61,12 +61,20 @@ def __init__(self, application, ieee, nwk, replaces):
                     INPUT_CLUSTERS: [XBeeOnOff],
                     OUTPUT_CLUSTERS: [],
                 },
+                0xD6: {
+                    "manufacturer": "XBEE",
+                    "model": "DIO6/RTS",
+                    DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
+                    PROFILE_ID: XBEE_PROFILE_ID,
+                    INPUT_CLUSTERS: [XBeeOnOff],
+                    OUTPUT_CLUSTERS: [],
+                },
                 0xD7: {
                     "manufacturer": "XBEE",
-                    "model": "SupplyVoltage",
+                    "model": "DIO7/CTS",
                     DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
                     PROFILE_ID: XBEE_PROFILE_ID,
-                    INPUT_CLUSTERS: [XBeeAnalogInput],
+                    INPUT_CLUSTERS: [XBeeOnOff, XBeeAnalogInput],
                     OUTPUT_CLUSTERS: [],
                 },
                 0xD8: {
@@ -109,6 +117,22 @@ def __init__(self, application, ieee, nwk, replaces):
                     INPUT_CLUSTERS: [XBeeOnOff],
                     OUTPUT_CLUSTERS: [],
                 },
+                0xDD: {
+                    "manufacturer": "XBEE",
+                    "model": "DIO13/DOUT",
+                    DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
+                    PROFILE_ID: XBEE_PROFILE_ID,
+                    INPUT_CLUSTERS: [XBeeOnOff],
+                    OUTPUT_CLUSTERS: [],
+                },
+                0xDE: {
+                    "manufacturer": "XBEE",
+                    "model": "DIO14/DIN",
+                    DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
+                    PROFILE_ID: XBEE_PROFILE_ID,
+                    INPUT_CLUSTERS: [XBeeOnOff],
+                    OUTPUT_CLUSTERS: [],
+                },
             }
         )
 
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
@@ -61,12 +61,36 @@ def __init__(self, application, ieee, nwk, replaces):
                     INPUT_CLUSTERS: [XBeeOnOff],
                     OUTPUT_CLUSTERS: [],
                 },
+                0xD6: {
+                    "manufacturer": "XBEE",
+                    "model": "DIO6/RTS",
+                    DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
+                    PROFILE_ID: XBEE_PROFILE_ID,
+                    INPUT_CLUSTERS: [XBeeOnOff],
+                    OUTPUT_CLUSTERS: [],
+                },
                 0xD7: {
                     "manufacturer": "XBEE",
-                    "model": "SupplyVoltage",
+                    "model": "DIO7/CTS",
+                    DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
+                    PROFILE_ID: XBEE_PROFILE_ID,
+                    INPUT_CLUSTERS: [XBeeOnOff, XBeeAnalogInput],
+                    OUTPUT_CLUSTERS: [],
+                },
+                0xD8: {
+                    "manufacturer": "XBEE",
+                    "model": "DIO8",
                     DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
                     PROFILE_ID: XBEE_PROFILE_ID,
-                    INPUT_CLUSTERS: [XBeeAnalogInput],
+                    INPUT_CLUSTERS: [XBeeOnOff],
+                    OUTPUT_CLUSTERS: [],
+                },
+                0xD9: {
+                    "manufacturer": "XBEE",
+                    "model": "DIO9",
+                    DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
+                    PROFILE_ID: XBEE_PROFILE_ID,
+                    INPUT_CLUSTERS: [XBeeOnOff],
                     OUTPUT_CLUSTERS: [],
                 },
                 0xDA: {
@@ -93,6 +117,22 @@ def __init__(self, application, ieee, nwk, replaces):
                     INPUT_CLUSTERS: [XBeeOnOff],
                     OUTPUT_CLUSTERS: [],
                 },
+                0xDD: {
+                    "manufacturer": "XBEE",
+                    "model": "DIO13/DOUT",
+                    DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
+                    PROFILE_ID: XBEE_PROFILE_ID,
+                    INPUT_CLUSTERS: [XBeeOnOff],
+                    OUTPUT_CLUSTERS: [],
+                },
+                0xDE: {
+                    "manufacturer": "XBEE",
+                    "model": "DIO14/DIN",
+                    DEVICE_TYPE: zha.DeviceType.LEVEL_CONTROL_SWITCH,
+                    PROFILE_ID: XBEE_PROFILE_ID,
+                    INPUT_CLUSTERS: [XBeeOnOff],
+                    OUTPUT_CLUSTERS: [],
+                },
             }
         )
 


Test patch: