Repository: zigpy/zha-device-handlers

Issue:
[Device Support Request] Schwaiger ZHS 20 Smoke Detector  (HEIMAN SMOK_YDLV10)
Not sure if Bug or not supported right now.
I've paired the smoke detector, and it detects smoke when tested. But it doesn't report battery status.

According to z2mqtt
https://github.com/ioBroker/ioBroker.zigbee/issues/137
https://github.com/Koenkk/zigbee2mqtt/issues/384
It should also report battery percentage. 

According to deconz:
https://github.com/dresden-elektronik/deconz-rest-plugin/issues/352
It should report state.fire config.battery state.lowbattery state.tampered too.

Maybe related to https://github.com/zigpy/zha-device-handlers/issues/518 ?

**Device signature**
```
{
  "node_descriptor": "NodeDescriptor(byte1=2, byte2=64, mac_capability_flags=132, manufacturer_code=48042, maximum_buffer_size=64, maximum_incoming_transfer_size=0, server_mask=0, maximum_outgoing_transfer_size=0, descriptor_capability_field=3)",
  "endpoints": {
    "1": {
      "profile_id": 260,
      "device_type": "0x0402",
      "in_clusters": [
        "0x0000",
        "0x0001",
        "0x0003",
        "0x0009",
        "0x0500",
        "0x0502"
      ],
      "out_clusters": [
        "0x0019"
      ]
    }
  },
  "manufacturer": "Heiman",
  "model": "SMOK_YDLV10",
  "class": "zigpy.device.Device"
}
```

Pairing Log:

```
[0x0000:zdo] ZDO request ZDOCmd.Mgmt_Permit_Joining_req: [60, <Bool.false: 0>]
[0x1ff6] Delivery error for seq # 0x7b, on endpoint id 1 cluster 0x0500: message send failure
[0x1FF6:1:0x0500]: Failed to send pro-active IAS enroll response: [0x1ff6:1:0x0500]: Message send failure
[0x1FF6:1:0x0500]: finished IASZoneChannel configuration
[0xa666:1:0xef00] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=CLUSTER_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=116 command_id=2>
[0xa666:1:0xef00] Unknown cluster-specific command 2
[0xa666:1:0xef00] ZCL request 0x0002: b'\x00\x18\x18\x02\x00\x04\x00\x00\x00\xd2'
[0xa666:1:0xef00] No handler for cluster command 2
Device 0xad3b (00:50:43:c9:03:37:19:41) joined the network
[0xad3b] Requesting 'Node Descriptor'
Tries remaining: 2
[0xad3b] Extending timeout for 0x7f request
Device 0xad3b (00:50:43:c9:03:37:19:41) joined the network
Skip initialization for existing device 00:50:43:c9:03:37:19:41
[0xad3b:zdo] ZDO request ZDOCmd.Device_annce: [0xAD3B, 00:50:43:c9:03:37:19:41, 132]
[0x6073:3:0x0b04]: async_update
[0xad3b] Node Descriptor: NodeDescriptor(byte1=2, byte2=64, mac_capability_flags=132, manufacturer_code=48042, maximum_buffer_size=64, maximum_incoming_transfer_size=0, server_mask=0, maximum_outgoing_transfer_size=0, descriptor_capability_field=3)
[0xad3b] Discovering endpoints
Tries remaining: 3
[0xad3b] Extending timeout for 0x83 request
[0x6073:3:0x0b04] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=129 command_id=Command.Read_Attributes_rsp>
Received frame on uninitialized device 00:50:43:c9:03:37:19:41 (Status.NEW) for endpoint: 1
[0xad3b] Received ZCL while uninitialized on endpoint id 1, cluster 0x0500 id, hdr: <ZCLHeader frame_control=<FrameControl frame_type=CLUSTER_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=0 command_id=1>, payload: b'(\x00\xff\xff'
[0xad3b] Discovered endpoints: [1]
[0xad3b:1] Discovering endpoint information
Tries remaining: 3
[0xad3b] Extending timeout for 0x85 request
[0x1FF6:1:0x0000]: initializing channel: from_cache: False
[0x1FF6:1:0x0000]: 'async_configure' stage succeeded
[0x1FF6:1:0x0500]: 'async_configure' stage succeeded
[0x1FF6:1:0x0502]: 'async_configure' stage succeeded
[0x1FF6:1:0x0019]: 'async_configure' stage succeeded
[0x1FF6](SMOK_YDLV10): completed configuration
[0x1FF6](SMOK_YDLV10): stored in registry: ZhaDeviceEntry(name='Heiman SMOK_YDLV10', ieee='00:50:43:c9:03:37:19:41', last_seen=1609347410.7951658)
[0x1ff6] Extending timeout for 0x87 request
[0xad3b:1] Discovered endpoint information: SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=1026, device_version=0, input_clusters=[0, 3, 1280, 1, 9, 1282], output_clusters=[25])
[0xad3b] Extending timeout for 0x89 request
[0xad3b:1:0x0000] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=137 command_id=Command.Read_Attributes_rsp>
[0xad3b:1] Manufacturer: Heiman
[0xad3b:1] Model: SMOK_YDLV10
Checking quirks for Heiman SMOK_YDLV10 (00:50:43:c9:03:37:19:41)
Considering <class 'bellows.zigbee.application.EZSPCoordinator'>
Fail because device_type mismatch on at least one endpoint
Considering <class 'zhaquirks.gledopto.soposhgu10.SoposhGU10'>
Fail because endpoint list mismatch: {11, 13} {1}
Considering <class 'zhaquirks.netvox.z308e3ed.Z308E3ED'>
Fail because input cluster mismatch on at least one endpoint
Considering <class 'zhaquirks.philips.rom001.PhilipsROM001'>
Fail because device_type mismatch on at least one endpoint
Considering <class 'zhaquirks.philips.rwl020.PhilipsRWL020'>
Fail because endpoint list mismatch: {1, 2} {1}
Considering <class 'zhaquirks.philips.rwl021.PhilipsRWL021'>
Fail because endpoint list mismatch: {1, 2} {1}
Considering <class 'zhaquirks.smartthings.multi.SmartthingsMultiPurposeSensor'>
Fail because input cluster mismatch on at least one endpoint
Considering <class 'zhaquirks.smartthings.tag_v4.SmartThingsTagV4'>
Fail because device_type mismatch on at least one endpoint
Considering <class 'zhaquirks.xbee.xbee3_io.XBee3Sensor'>
Fail because endpoint list mismatch: {232, 230} {1}
Considering <class 'zhaquirks.xbee.xbee_io.XBeeSensor'>
Fail because endpoint list mismatch: {232, 230} {1}
device - 0xAD3B:00:50:43:c9:03:37:19:41 entering async_device_initialized - is_new_join: True
device - 0xAD3B:00:50:43:c9:03:37:19:41 has joined the ZHA zigbee network
[0xAD3B](SMOK_YDLV10): started configuration
[0xAD3B:ZDO](SMOK_YDLV10): 'async_configure' stage succeeded
[0xad3b] Extending timeout for 0x8b request
[0xad3b] Extending timeout for 0x8d request
[0xad3b] Extending timeout for 0x8f request
[0xAD3B:1:0x0000]: bound 'basic' cluster: Status.SUCCESS
[0xAD3B:1:0x0000]: finished channel configuration
[0xad3b] Extending timeout for 0x91 request
[0xad3b:1:0x0500] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=141 command_id=Command.Read_Attributes_rsp>
[0xAD3B:1:0x0500]: started IASZoneChannel configuration
[0xad3b] Extending timeout for 0x93 request
[0xAD3B:1:0x0502]: bound 'ias_wd' cluster: Status.SUCCESS
[0xAD3B:1:0x0502]: finished channel configuration
[0xad3b] Extending timeout for 0x95 request
[0xa666:1:0xef00] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=CLUSTER_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=120 command_id=2>
[0xa666:1:0xef00] Unknown cluster-specific command 2
[0xa666:1:0xef00] ZCL request 0x0002: b'\x00\x18\x18\x02\x00\x04\x00\x00\x00\xd2'
[0xa666:1:0xef00] No handler for cluster command 2
[0x1ff6] Delivery error for seq # 0x87, on endpoint id 1 cluster 0x0003: message send failure
[0x1FF6:1:0x0003]: command failed: 'trigger_effect' args: '(2, 0)' kwargs '{}' exception: '[0x1ff6:1:0x0003]: Message send failure'
[0xad3b:1:0x0000] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=145 command_id=Command.Read_Attributes_rsp>
[0xAD3B:1:0x0000]: initializing channel: from_cache: False
[0xAD3B:1:0x0500]: bound 'ias_zone' cluster: Status.SUCCESS
[0xad3b] Extending timeout for 0x97 request
[0xAD3B:1:0x0019]: bound 'ota' cluster: Status.SUCCESS
[0xAD3B:1:0x0019]: finished channel configuration
[0xad3b:1:0x0500] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=151 command_id=Command.Write_Attributes_rsp>
[0xAD3B:1:0x0500]: wrote cie_addr: 00:0d:6f:00:0d:cf:a2:6b to 'ias_zone' cluster: [WriteAttributesStatusRecord(status=<Status.SUCCESS: 0>)]
[0xAD3B:1:0x0500]: Sending pro-active IAS enroll response
[0xad3b] Extending timeout for 0x99 request
[0xad3b:1:0x0500] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=153 command_id=Command.Default_Response>
[0xAD3B:1:0x0500]: finished IASZoneChannel configuration
[0xAD3B:1:0x0000]: 'async_configure' stage succeeded
[0xAD3B:1:0x0500]: 'async_configure' stage succeeded
[0xAD3B:1:0x0502]: 'async_configure' stage succeeded
[0xAD3B:1:0x0019]: 'async_configure' stage succeeded
[0xAD3B](SMOK_YDLV10): completed configuration
[0xAD3B](SMOK_YDLV10): stored in registry: ZhaDeviceEntry(name='Heiman SMOK_YDLV10', ieee='00:50:43:c9:03:37:19:41', last_seen=1609347446.701465)
[0xad3b] Extending timeout for 0x9b request
[0xad3b:1:0x0003] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=155 command_id=Command.Default_Response>
[0xAD3B:1:0x0003]: executed 'trigger_effect' command with args: '(2, 0)' kwargs: '{}' result: [64, <Status.UNSUP_CLUSTER_COMMAND: 129>]
[0xAD3B](SMOK_YDLV10): started initialization
[0xAD3B:ZDO](SMOK_YDLV10): 'async_initialize' stage succeeded
[0xad3b] Extending timeout for 0x9d request
[0xad3b] Extending timeout for 0x9f request
[0xAD3B:1:0x0502]: initializing channel: from_cache: False
[0xAD3B:1:0x0019]: initializing channel: from_cache: False
[0xad3b:1:0x0000] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=157 command_id=Command.Read_Attributes_rsp>
[0xAD3B:1:0x0000]: initializing channel: from_cache: False
[0xad3b:1:0x0500] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=159 command_id=Command.Read_Attributes_rsp>
[0xAD3B:1:0x0500]: initializing channel: from_cache: False
[0xAD3B:1:0x0000]: 'async_initialize' stage succeeded
[0xAD3B:1:0x0500]: 'async_initialize' stage succeeded
[0xAD3B:1:0x0502]: 'async_initialize' stage succeeded
[0xAD3B:1:0x0019]: 'async_initialize' stage succeeded
[0xAD3B](SMOK_YDLV10): power source: Mains
[0xAD3B](SMOK_YDLV10): completed initialization
[0xa666:1:0xef00] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=CLUSTER_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=124 command_id=2>
[0xa666:1:0xef00] Unknown cluster-specific command 2
[0xa666:1:0xef00] ZCL request 0x0002: b'\x00\x18\x18\x02\x00\x04\x00\x00\x00\xd2'
[0xa666:1:0xef00] No handler for cluster command 2
[0xa666:1:0xef00] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=CLUSTER_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=127 command_id=2>
[0xa666:1:0xef00] Unknown cluster-specific command 2
[0xa666:1:0xef00] ZCL request 0x0002: b'\x00\x18\x18\x02\x00\x04\x00\x00\x00\xd2'
[0xa666:1:0xef00] No handler for cluster command 2
[0x6073:3:0x0b04]: async_update
[0x6073:3:0x0b04] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=161 command_id=Command.Read_Attributes_rsp>

```



Discussion:
It reports itself as mains powered, so ZHA does not create the battery entity for it. 
Can this be fixed, or is this permanent? If i understood right, some people got battery stats working with zigbee2mqtt.
doesn't the Plaid moisture sensor report as mains as well so should be fixable with a quirk like it was with that?
what plaid version do you have? the one in my possession does report the battery. 
> what plaid version do you have? the one in my possession does report the battery.

the gen3 I think. #291 I guess it was reporting the voltage over the mains_voltage attribute. fixed in #329 
ah, yes. So plaid battery was a different issue. 
yea, sorry for the sidetrack
All we should have to do is flip a bit in the node descriptor no?
yeah, should replace node descriptor with `NodeDescriptor(2, 64, 132 & 0b1111_1011, 48042, 64, 0, 0, 0, 3)`
I thought we already did this either for Heinman smoke or CO sensor
Opple remotes IIRC
Bingo - https://github.com/zigpy/zha-device-handlers/blob/50f603e80ab57ced3c7aa43101ecbe3c18755a5b/zhaquirks/xiaomi/aqara/opple_remote.py#L203-L205

Resolving patch:
diff --git a/zhaquirks/heiman/__init__.py b/zhaquirks/heiman/__init__.py
new file mode 100644
--- /dev/null
+++ b/zhaquirks/heiman/__init__.py
@@ -0,0 +1,3 @@
+"""Quirks for Heiman devices."""
+
+HEIMAN = "Heiman"
diff --git a/zhaquirks/heiman/smoke.py b/zhaquirks/heiman/smoke.py
new file mode 100644
--- /dev/null
+++ b/zhaquirks/heiman/smoke.py
@@ -0,0 +1,71 @@
+"""Smoke Sensor."""
+
+import zigpy.profiles.zha
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters.general import Alarms, Basic, Identify, Ota, PowerConfiguration
+from zigpy.zcl.clusters.security import IasWd, IasZone
+import zigpy.zdo.types
+
+from . import HEIMAN
+from ..const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    NODE_DESCRIPTOR,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+
+
+class HeimanSmokYDLV10(CustomDevice):
+    """YDLV10 quirk."""
+
+    # NodeDescriptor(byte1=2, byte2=64, mac_capability_flags=132,
+    # manufacturer_code=48042, maximum_buffer_size=64, maximum_incoming_transfer_size=0,
+    # server_mask=0, maximum_outgoing_transfer_size=0, descriptor_capability_field=3)
+    # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=1026,
+    # device_version=0, input_clusters=[0, 3, 1280, 1, 9, 1282], output_clusters=[25])
+    signature = {
+        MODELS_INFO: [(HEIMAN, "SMOK_YDLV10")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zigpy.profiles.zha.PROFILE_ID,
+                DEVICE_TYPE: zigpy.profiles.zha.DeviceType.IAS_ZONE,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    Alarms.cluster_id,
+                    IasZone.cluster_id,
+                    IasWd.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Ota.cluster_id,
+                ],
+            },
+        },
+    }
+
+    replacement = {
+        NODE_DESCRIPTOR: zigpy.zdo.types.NodeDescriptor(
+            0x02, 0x40, 0x84 & 0b1111_1011, 0xBBAA, 0x40, 0x0000, 0x0000, 0x0000, 0x03
+        ),
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zigpy.profiles.zha.PROFILE_ID,
+                DEVICE_TYPE: zigpy.profiles.zha.DeviceType.IAS_ZONE,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    Alarms.cluster_id,
+                    IasZone.cluster_id,
+                    IasWd.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Ota.cluster_id,
+                ],
+            },
+        },
+    }


Test patch: