Repository: zigpy/zha-device-handlers

Issue:
Gen1 SmartThings water leak sensor (CentraLite 3315-S) battery reported as Unknown
**Describe the bug**
When a water leak sensor is paired, the battery reported is unknown

**To Reproduce**
Steps to reproduce the behavior:
1. Pair a Gen1 SmartThings water leak sensor to homeassistant
2. Wait until pairing is complete
3. Inspect battery status

**Actual
State is unknown
I can repro this with 4 out 5 sensors in my setup, all of the same model CentraLite 3315-S

**Expected behavior**
Battery state should be close to 99

**Additional context**
```
[0x0000:zdo] ZDO request ZDOCmd.Mgmt_Permit_Joining_req: [60, <Bool.false: 0>]
Device 0x67ca (00:0d:6f:00:0a:95:70:ea) joined the network
[0x67ca:zdo] ZDO request ZDOCmd.Device_annce: [0x67ca, 00:0d:6f:00:0a:95:70:ea, 128]
[0x67ca] Requesting 'Node Descriptor'
[0x67ca] Extending timeout for 0x09 request
[0x67ca] Node Descriptor: <Optional byte1=2 byte2=64 mac_capability_flags=128 manufacturer_code=4174 maximum_buffer_size=82 maximum_incoming_transfer_size=82 server_mask=0 maximum_outgoing_transfer_size=82 descriptor_capability_field=0>
[0x67ca] Discovering endpoints
[0x67ca] Extending timeout for 0x0b request
[0x67ca] Discovered endpoints: [1, 2]
[0x67ca:1] Discovering endpoint information
[0x67ca] Extending timeout for 0x0d request
[0x67ca:1] Discovered endpoint information: <SimpleDescriptor endpoint=1 profile=260 device_type=1026 device_version=0 input_clusters=[0, 1, 3, 32, 1026, 1280, 2821] output_clusters=[25]>
[0x67ca] Extending timeout for 0x0f request
[0x67ca:1:0x0000] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=15 command_id=Command.Read_Attributes_rsp>
[0x67ca:1] Manufacturer: CentraLite
[0x67ca:1] Model: 3315-S
[0x67ca:2] Discovering endpoint information
[0x67ca] Extending timeout for 0x11 request
[0x67ca:2] Discovered endpoint information: <SimpleDescriptor endpoint=2 profile=49887 device_type=12 device_version=0 input_clusters=[0, 1, 3, 15, 2821] output_clusters=[3]>
Checking quirks for CentraLite 3315-S (00:0d:6f:00:0a:95:70:ea)
Considering <class 'zhaquirks.centralite.ias.CentraLiteIASSensor'>
Fail because input cluster mismatch on at least one endpoint
Considering <class 'zhaquirks.centralite.ias.CentraLiteIASSensorV2'>
Fail because input cluster mismatch on at least one endpoint
Considering <class 'bellows.zigbee.application.EZSPCoordinator'>
Fail because endpoint list mismatch: {1} {1, 2}
Considering <class 'zhaquirks.gledopto.soposhgu10.SoposhGU10'>
Fail because endpoint list mismatch: {11, 13} {1, 2}
Considering <class 'zhaquirks.lutron.lzl4bwhl01remote.LutronLZL4BWHL01Remote2'>
Fail because endpoint list mismatch: {1} {1, 2}
Considering <class 'zhaquirks.netvox.z308e3ed.Z308E3ED'>
Fail because endpoint list mismatch: {1} {1, 2}
Considering <class 'zhaquirks.osram.a19twhite.A19TunableWhite'>
Fail because endpoint list mismatch: {3} {1, 2}
Considering <class 'zhaquirks.philips.rom001.PhilipsROM001'>
Fail because endpoint list mismatch: {1} {1, 2}
Considering <class 'zhaquirks.philips.rwl020.PhilipsRWL020'>
Fail because profile_id mismatch on at least one endpoint
Considering <class 'zhaquirks.philips.rwl021.PhilipsRWL021'>
Fail because profile_id mismatch on at least one endpoint
Considering <class 'zhaquirks.smartthings.multi.SmartthingsMultiPurposeSensor'>
Fail because endpoint list mismatch: {1} {1, 2}
Considering <class 'zhaquirks.smartthings.tag_v4.SmartThingsTagV4'>
Fail because endpoint list mismatch: {1} {1, 2}
Considering <class 'zhaquirks.xbee.xbee3_io.XBee3Sensor'>
Fail because endpoint list mismatch: {232, 230} {1, 2}
Considering <class 'zhaquirks.xbee.xbee_io.XBeeSensor'>
Fail because endpoint list mismatch: {232, 230} {1, 2}
Considering <class 'zhaquirks.xiaomi.mija.smoke.MijiaHoneywellSmokeDetectorSensor'>
Fail because endpoint list mismatch: {1} {1, 2}
device - 0x67ca:00:0d:6f:00:0a:95:70:ea entering async_device_initialized - is_new_join: True
device - 0x67ca:00:0d:6f:00:0a:95:70:ea has joined the ZHA zigbee network
[0x67ca](3315-S): started configuration
[0x67ca:ZDO](3315-S): 'async_configure' stage succeeded
[0x67ca] Extending timeout for 0x13 request
[0x67ca] Extending timeout for 0x15 request
[0x67ca] Extending timeout for 0x17 request
[0x67ca:1:0x0000]: bound 'basic' cluster: Status.SUCCESS
[0x67ca:1:0x0000]: finished channel configuration
[0x67ca] Extending timeout for 0x19 request
[0x67ca:1:0x0001]: bound 'power' cluster: Status.SUCCESS
[0x67ca] Extending timeout for 0x1b request
[0x67ca:1:0x0500] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=21 command_id=Command.Read_Attributes_rsp>
[0x67ca:1:0x0500]: started IASZoneChannel configuration
[0x67ca] Extending timeout for 0x1d request
[0x67ca:1:0x0000] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=25 command_id=Command.Read_Attributes_rsp>
[0x67ca:1:0x0000]: initializing channel: from_cache: False
[0x67ca] Extending timeout for 0x1f request
[0x67ca:1:0x0001] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=27 command_id=Command.Configure_Reporting_rsp>
[0x67ca:1:0x0001]: reporting 'battery_voltage' attr on 'power' cluster: 3600/10800/1: Result: '[[<ConfigureReportingResponseRecord status=Status.SUCCESS>]]'
[0x67ca] Extending timeout for 0x21 request
[0x67ca:1:0x0500]: bound 'ias_zone' cluster: Status.SUCCESS
[0x67ca] Extending timeout for 0x23 request
[0x67ca:1:0x0020] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=31 command_id=Command.Write_Attributes_rsp>
[0x67ca:1:0x0020]: 3300.0s check-in interval set: [[<WriteAttributesStatusRecord status=Status.SUCCESS>]]
[0x67ca] Extending timeout for 0x25 request
[0x67ca:1:0x0001] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=33 command_id=Command.Configure_Reporting_rsp>
[0x67ca:1:0x0001]: reporting 'battery_percentage_remaining' attr on 'power' cluster: 3600/10800/1: Result: '[[<ConfigureReportingResponseRecord status=Status.UNSUPPORTED_ATTRIBUTE direction=ReportingDirection.SendReports attrid=33>]]'
[0x67ca:1:0x0001]: finished channel configuration
[0x67ca] Extending timeout for 0x27 request
[0x67ca:1:0x0500] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=35 command_id=Command.Write_Attributes_rsp>
[0x67ca:1:0x0500]: wrote cie_addr: 00:0d:6f:00:0b:5e:1d:93 to 'ias_zone' cluster: [<WriteAttributesStatusRecord status=Status.SUCCESS>]
[0x67ca:1:0x0500]: finished IASZoneChannel configuration
[0x67ca] Extending timeout for 0x29 request
[0x67ca:1:0x0020]: bound 'poll_control' cluster: Status.SUCCESS
[0x67ca:1:0x0020]: finished channel configuration
[0x67ca] Extending timeout for 0x2b request
[0x67ca:1:0x0402]: bound 'temperature' cluster: Status.SUCCESS
[0x67ca] Extending timeout for 0x2d request
[0x67ca:1:0x0019]: bound 'ota' cluster: Status.SUCCESS
[0x67ca:1:0x0019]: finished channel configuration
[0x67ca:2:0x0000]: bound 'basic' cluster: Status.SUCCESS
[0x67ca:2:0x0000]: finished channel configuration
[0x67ca] Extending timeout for 0x2f request
[0x67ca:1:0x0402] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=45 command_id=Command.Configure_Reporting_rsp>
[0x67ca:2:0x0000] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=47 command_id=Command.Read_Attributes_rsp>
[0x67ca:1:0x0402]: reporting 'measured_value' attr on 'temperature' cluster: 30/900/50: Result: '[[<ConfigureReportingResponseRecord status=Status.SUCCESS>]]'
[0x67ca:1:0x0402]: finished channel configuration
[0x67ca:2:0x0000]: initializing channel: from_cache: False
[0x67ca:1:0x0000]: 'async_configure' stage succeeded
[0x67ca:1:0x0500]: 'async_configure' stage succeeded
[0x67ca:1:0x0001]: 'async_configure' stage succeeded
[0x67ca:1:0x0020]: 'async_configure' stage succeeded
[0x67ca:1:0x0402]: 'async_configure' stage succeeded
[0x67ca:1:0x0019]: 'async_configure' stage succeeded
[0x67ca:2:0x0000]: 'async_configure' stage succeeded
[0x67ca](3315-S): completed configuration
[0x67ca](3315-S): stored in registry: ZhaDeviceEntry(name='CentraLite 3315-S', ieee='00:0d:6f:00:0a:95:70:ea', last_seen=1587245010.367165)
[0x67ca] Extending timeout for 0x31 request
[0x67ca:1:0x0003] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=49 command_id=Command.Default_Response>
[0x67ca:1:0x0003]: executed 'trigger_effect' command with args: '(2, 0)' kwargs: '{}' result: [64, <Status.UNSUP_CLUSTER_COMMAND: 129>]
[0x67ca](3315-S): started initialization
[0x67ca:ZDO](3315-S): 'async_initialize' stage succeeded
[0x67ca] Extending timeout for 0x33 request
[0x67ca] Extending timeout for 0x35 request
[0x67ca] Extending timeout for 0x37 request
[0x67ca:1:0x0000] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=51 command_id=Command.Read_Attributes_rsp>
[0x67ca:1:0x0000]: initializing channel: from_cache: False
[0x67ca:1:0x0020]: initializing channel: from_cache: False
[0x67ca:1:0x0402]: initializing channel: from_cache: False
[0x67ca] Extending timeout for 0x39 request
[0x67ca:1:0x0500] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=53 command_id=Command.Read_Attributes_rsp>
[0x67ca:1:0x0001] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=55 command_id=Command.Read_Attributes_rsp>
[0x67ca:1:0x0500]: initializing channel: from_cache: False
[0x67ca:1:0x0001]: initializing channel: from_cache: False
[0x67ca] Extending timeout for 0x3b request
[0x67ca:1:0x0019]: initializing channel: from_cache: False
[0x67ca] Extending timeout for 0x3d request
[0x67ca:1:0x0402] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=57 command_id=Command.Read_Attributes_rsp>
[0x67ca:1:0x0001] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=59 command_id=Command.Read_Attributes_rsp>
[0x67ca:2:0x0000] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=61 command_id=Command.Read_Attributes_rsp>
[0x67ca:2:0x0000]: initializing channel: from_cache: False
[0x67ca:1:0x0000]: 'async_initialize' stage succeeded
[0x67ca:1:0x0500]: 'async_initialize' stage succeeded
[0x67ca:1:0x0001]: 'async_initialize' stage succeeded
[0x67ca:1:0x0020]: 'async_initialize' stage succeeded
[0x67ca:1:0x0402]: 'async_initialize' stage succeeded
[0x67ca:1:0x0019]: 'async_initialize' stage succeeded
[0x67ca:2:0x0000]: 'async_initialize' stage succeeded
[0x67ca](3315-S): power source: Battery or Unknown
[0x67ca](3315-S): completed initialization
[0x67ca:1:0x0402] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=3 command_id=Command.Report_Attributes>
[0x67ca:1:0x0402] ZCL request 0x000a: [[<Attribute attrid=0 value=<TypeValue type=int16s, value=2115>>]]
[0x67ca:1:0x0402] Attribute report received: measured_value=2115
[0x67ca:zdo] ZDO request ZDOCmd.Match_Desc_req: [0xfffd, 260, [25], []]
[0x67ca:1:0x0019] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=CLUSTER_COMMAND manufacturer_specific=False is_reply=False disable_default_response=False> manufacturer=None tsn=4 command_id=1>
[0x67ca:1:0x0019] ZCL request 0x0001: [0, 4174, 11, 520573712, None]
[0x67ca:1:0x0019] OTA query_next_image handler for 'CentraLite 3315-S': field_control=0, manufacture_id=4174, image_type=11, current_file_version=520573712, hardware_version=None
[0x67ca:1:0x0019] No OTA image is available
```


Discussion:
`battery_percent_remaining` is an unsupported attribute, so this devices requires a quirk:
```
0x67ca:1:0x0001]: reporting 'battery_percentage_remaining' attr on 'power' cluster: 3600/10800/1: Result: '[[<ConfigureReportingResponseRecord status=Status.UNSUPPORTED_ATTRIBUTE direction=ReportingDirection.SendReports attrid=33>]]'
```

Signature
```
[0x67ca] Node Descriptor: <Optional byte1=2 byte2=64 mac_capability_flags=128 manufacturer_code=4174 maximum_buffer_size=82 maximum_incoming_transfer_size=82 server_mask=0 maximum_outgoing_transfer_size=82 descriptor_capability_field=0>

[0x67ca] Discovered endpoints: [1, 2]

[0x67ca:1] Discovered endpoint information: <SimpleDescriptor endpoint=1 profile=260 device_type=1026 device_version=0 input_clusters=[0, 1, 3, 32, 1026, 1280, 2821] output_clusters=[25]>

[0x67ca:1] Manufacturer: CentraLite
[0x67ca:1] Model: 3315-S

[0x67ca:2] Discovered endpoint information: <SimpleDescriptor endpoint=2 profile=49887 device_type=12 device_version=0 input_clusters=[0, 1, 3, 15, 2821] output_clusters=[3]>

```


Resolving patch:
diff --git a/zhaquirks/centralite/ias.py b/zhaquirks/centralite/ias.py
--- a/zhaquirks/centralite/ias.py
+++ b/zhaquirks/centralite/ias.py
@@ -132,3 +132,36 @@ class CentraLiteIASSensorV2(CustomDevice):
     }
 
     replacement = CentraLiteIASSensor.replacement
+
+
+class CentraLiteIASSensorV3(CustomDevice):
+    """Custom device representing centralite ias sensors."""
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=260 device_type=1026
+        #  device_version=0
+        #  input_clusters=[0, 1, 3, 32, 1026, 1280, 2821]
+        #  output_clusters=[25]>
+        MODELS_INFO: CentraLiteIASSensor.signature[MODELS_INFO],
+        ENDPOINTS: {
+            1: CentraLiteIASSensor.signature[ENDPOINTS][1],
+            #  <SimpleDescriptor endpoint=2 profile=49887 device_type=12
+            #  device_version=0
+            #  input_clusters=[0, 1, 3, 15, 2821]
+            #  output_clusters=[3]>
+            2: {
+                PROFILE_ID: MANUFACTURER_SPECIFIC_PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.SIMPLE_SENSOR,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    BinaryInput.cluster_id,
+                    PowerConfigurationCluster.cluster_id,
+                    Identify.cluster_id,
+                    DIAGNOSTICS_CLUSTER_ID,
+                ],
+                OUTPUT_CLUSTERS: [Identify.cluster_id],
+            },
+        },
+    }
+
+    replacement = CentraLiteIASSensor.replacement


Test patch: