zigpy / zha-device-handlers

ZHA device handlers bridge the functionality gap created when manufacturers deviate from the ZCL specification, handling deviations and exceptions by parsing custom messages to and from Zigbee devices.
Apache License 2.0
684 stars 637 forks source link

[BUG] TS0211 by _TZ1800_ladpngdx does not work correctly #2096

Open moritzbeck13 opened 1 year ago

moritzbeck13 commented 1 year ago

Describe the bug As mentioned in https://github.com/zigpy/zha-device-handlers/issues/1168: It seems like pressing the normal button reports true, but releasing it reports nothing. In contrast, pressing the tamper button changes the same entity to false, releasing it does nothing aswell.

To Reproduce

  1. Doorbell entity is false
  2. Press the doorbell button
  3. Doorbell entity changes to true
  4. Release the doorbell button
  5. Doorbell entity does not change to false
  6. Press the tamper button
  7. Doorbell entity changes to false
  8. Release the tamper button

Expected behavior I press the doorbell button, the doorbell entity reports true. I release it, it reports false. There is no tamper entity (why?), but I would expect the same behavior with the tamper button and a potential tamper entity.

Device signature ```yaml { "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4619, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)", "endpoints": { "1": { "profile_id": 260, "device_type": "0x0402", "in_clusters": [ "0x0000", "0x0001", "0x0003", "0x0500", "0x0b05" ], "out_clusters": [ "0x0019" ] } }, "manufacturer": "_TZ1800_ladpngdx", "model": "TS0211", "class": "zhaquirks.tuya.ts0211.TuyaDoorbell0211" } ```
Diagnostic information ```yaml { "home_assistant": { "installation_type": "Home Assistant OS", "version": "2023.1.2", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.10.7", "docker": true, "arch": "x86_64", "timezone": "Europe/Berlin", "os_name": "Linux", "os_version": "5.15.80", "supervisor": "2022.12.1", "host_os": "Home Assistant OS 9.4", "docker_version": "20.10.19", "chassis": "vm", "run_as_root": true }, "custom_components": { "hacs": { "version": "1.29.1", "requirements": [ "aiogithubapi>=22.10.1" ] }, "homematicip_local": { "version": "1.26.1", "requirements": [ "hahomematic==2023.1.2" ] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/zha", "requirements": [ "bellows==0.34.6", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.90", "zigpy-deconz==0.19.2", "zigpy==0.53.0", "zigpy-xbee==0.16.2", "zigpy-zigate==0.10.3", "zigpy-znp==0.9.2" ], "usb": [ { "vid": "10C4", "pid": "EA60", "description": "*2652*", "known_devices": [ "slae.sh cc2652rb stick" ] }, { "vid": "1A86", "pid": "55D4", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus v2" ] }, { "vid": "10C4", "pid": "EA60", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus" ] }, { "vid": "10C4", "pid": "EA60", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*zigstar*", "known_devices": [ "ZigStar Coordinators" ] }, { "vid": "1CF1", "pid": "0030", "description": "*conbee*", "known_devices": [ "Conbee II" ] }, { "vid": "10C4", "pid": "8A2A", "description": "*zigbee*", "known_devices": [ "Nortek HUSBZB-1" ] }, { "vid": "0403", "pid": "6015", "description": "*zigate*", "known_devices": [ "ZiGate+" ] }, { "vid": "10C4", "pid": "EA60", "description": "*zigate*", "known_devices": [ "ZiGate" ] }, { "vid": "10C4", "pid": "8B34", "description": "*bv 2010/10*", "known_devices": [ "Bitron Video AV2010/10" ] } ], "codeowners": [ "@dmulcahey", "@adminiuga", "@puddly" ], "zeroconf": [ { "type": "_esphomelib._tcp.local.", "name": "tube*" }, { "type": "_zigate-zigbee-gateway._tcp.local.", "name": "*zigate*" }, { "type": "_zigstar_gw._tcp.local.", "name": "*zigstar*" }, { "type": "_slzb-06._tcp.local.", "name": "slzb-06*" } ], "dependencies": [ "file_upload" ], "after_dependencies": [ "onboarding", "usb", "zeroconf" ], "iot_class": "local_polling", "loggers": [ "aiosqlite", "bellows", "crccheck", "pure_pcapy3", "zhaquirks", "zigpy", "zigpy_deconz", "zigpy_xbee", "zigpy_zigate", "zigpy_znp" ], "is_built_in": true }, "data": { "ieee": "**REDACTED**", "nwk": 46036, "manufacturer": "_TZ1800_ladpngdx", "model": "TS0211", "name": "_TZ1800_ladpngdx TS0211", "quirk_applied": true, "quirk_class": "zhaquirks.tuya.ts0211.TuyaDoorbell0211", "manufacturer_code": 4619, "power_source": "Battery or Unknown", "lqi": 255, "rssi": -61, "last_seen": "2023-01-15T01:00:26", "available": true, "device_type": "EndDevice", "signature": { "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4619, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)", "endpoints": { "1": { "profile_id": 260, "device_type": "0x0402", "in_clusters": [ "0x0000", "0x0001", "0x0003", "0x0500", "0x0b05" ], "out_clusters": [ "0x0019" ] } } }, "active_coordinator": false, "entities": [ { "entity_id": "binary_sensor.schalter_alarmanlage_iaszone", "name": "_TZ1800_ladpngdx TS0211" }, { "entity_id": "button.schalter_alarmanlage_identify", "name": "_TZ1800_ladpngdx TS0211" }, { "entity_id": "sensor.schalter_alarmanlage_battery", "name": "_TZ1800_ladpngdx TS0211" } ], "neighbors": [], "routes": [], "endpoint_names": [ { "name": "IAS_ZONE" } ], "user_given_name": "Schalter Alarmanlage", "device_reg_id": "f461037a8c12c5b0b35b665927357440", "area_id": "alarmanlage", "cluster_details": { "1": { "device_type": { "name": "IAS_ZONE", "id": 1026 }, "profile_id": 260, "in_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0004": { "attribute_name": "manufacturer", "value": "_TZ1800_ladpngdx" }, "0x0005": { "attribute_name": "model", "value": "TS0211" } }, "unsupported_attributes": {} }, "0x0001": { "endpoint_attribute": "power", "attributes": { "0x0020": { "attribute_name": "battery_voltage", "value": 29 }, "0x0021": { "attribute_name": "battery_percentage_remaining", "value": 170 } }, "unsupported_attributes": { "0x0031": { "attribute_name": "battery_size" }, "0x0033": { "attribute_name": "battery_quantity" } } }, "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0500": { "endpoint_attribute": "ias_zone", "attributes": { "0x0000": { "attribute_name": "zone_state", "value": 1 }, "0x0001": { "attribute_name": "zone_type", "value": 21 }, "0x0002": { "attribute_name": "zone_status", "value": 0 }, "0x0010": { "attribute_name": "cie_addr", "value": "00:21:2e:ff:ff:07:7f:4e" } }, "unsupported_attributes": {} }, "0x0b05": { "endpoint_attribute": "diagnostic", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": { "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} } } } } } } ```
Additional logs Event 0: ``` event_type: zha_event data: device_ieee: 84:2e:14:ff:fe:f6:d3:9b unique_id: 84:2e:14:ff:fe:f6:d3:9b:1:0x0500 device_id: f461037a8c12c5b0b35b665927357440 endpoint_id: 1 cluster_id: 1280 command: single args: [] params: {} origin: LOCAL time_fired: "2023-01-04T20:07:14.527905+00:00" context: id: 01GNZ6A7TZR278TNNSFC2AFT2Z parent_id: null user_id: null ``` Event 1: ``` event_type: zha_event data: device_ieee: 84:2e:14:ff:fe:f6:d3:9b unique_id: 84:2e:14:ff:fe:f6:d3:9b:1:0x0500 device_id: f461037a8c12c5b0b35b665927357440 endpoint_id: 1 cluster_id: 1280 command: single args: [] params: {} origin: LOCAL time_fired: "2023-01-04T20:07:16.646759+00:00" context: id: 01GNZ6A9X6QZHBA42GH0MQP32A parent_id: null user_id: null ``` Event 2: ``` event_type: zha_event data: device_ieee: 84:2e:14:ff:fe:f6:d3:9b unique_id: 84:2e:14:ff:fe:f6:d3:9b:1:0x0500 device_id: f461037a8c12c5b0b35b665927357440 endpoint_id: 1 cluster_id: 1280 command: single args: [] params: {} origin: LOCAL time_fired: "2023-01-04T20:07:19.666115+00:00" context: id: 01GNZ6ACVJQJQXJSJCQ1QDDZHV parent_id: null user_id: null ```
javicalle commented 1 year ago

It seems that device triggers 3 events for every button press:

I'm not sure why it behaves that way, but I'll suggest this change to the quirk:

ts0211.py ```python """Tuya Doorbell.""" from typing import Optional, Tuple, Union from zigpy.profiles import zha from zigpy.quirks import CustomDevice import zigpy.types as t from zigpy.zcl import foundation from zigpy.zcl.clusters.general import Basic, Identify, Ota, PowerConfiguration from zigpy.zcl.clusters.homeautomation import Diagnostic from zigpy.zcl.clusters.security import IasZone from zhaquirks import CustomCluster from zhaquirks.const import ( COMMAND_SINGLE, DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODEL, OUTPUT_CLUSTERS, PROFILE_ID, ZHA_SEND_EVENT, ) class IasZoneDoorbellCluster(CustomCluster, IasZone): """Custom IasZone cluster for the doorbell.""" cluster_id = IasZone.cluster_id def handle_cluster_request( self, hdr: foundation.ZCLHeader, args: Tuple[IasZone.ZoneStatus], *, dst_addressing: Optional[ Union[t.Addressing.Group, t.Addressing.IEEE, t.Addressing.NWK] ] = None, ) -> None: """Handle cluster request.""" # args looks like [, , 0, 0] # we are only interested in 3 bits of the ZoneStatus item # with thanks to # https://github.com/Koenkk/zigbee-herdsman-converters/blob/26553bfa9d747c1a8b6322090429c04cf612c3c1/converters/fromZigbee.js#L2193-L2206 arg = args[0] if arg & IasZone.ZoneStatus.Alarm_1: self.listener_event(ZHA_SEND_EVENT, COMMAND_SINGLE, []) # the doorbell also sets (arg & IasZone.ZoneStatus.Tamper) and # (arg & IasZone.ZoneStatus.Battery) but those should eventually # be handled by a more generic IasZone handling super().handle_cluster_request(hdr, args, dst_addressing=dst_addressing) class TuyaDoorbell0211(CustomDevice): """Tuya doorbell.""" # { # "node_descriptor": "NodeDescriptor( # logical_type=, # complex_descriptor_available=0, # user_descriptor_available=0, # reserved=0, # aps_flags=0, # frequency_band=, # mac_capability_flags=, # manufacturer_code=4619, # maximum_buffer_size=82, # maximum_incoming_transfer_size=82, # server_mask=11264, # maximum_outgoing_transfer_size=82, # descriptor_capability_field=, # *allocate_address=True, # *is_alternate_pan_coordinator=False, # *is_coordinator=False, # *is_end_device=True, # *is_full_function_device=False, # *is_mains_powered=False, # *is_receiver_on_when_idle=False, # *is_router=False, # *is_security_capable=False)", # "endpoints": { # "1": { # "profile_id": 260, # "device_type": "0x0402", # "in_clusters": [ # "0x0000", # "0x0001", # "0x0003", # "0x0500", # "0x0b05" # ], # "out_clusters": [ # "0x0019" # ] # } # }, # "manufacturer": "_TZ1800_ladpngdx", # "model": "TS0211", # "class": "zhaquirks.tuya.ts0211.TuyaDoorbell0211" # } signature = { MODEL: "TS0211", ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.IAS_ZONE, INPUT_CLUSTERS: [ Basic.cluster_id, PowerConfiguration.cluster_id, Identify.cluster_id, IasZone.cluster_id, Diagnostic.cluster_id, ], OUTPUT_CLUSTERS: [Ota.cluster_id], }, }, } replacement = { ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.IAS_ZONE, INPUT_CLUSTERS: [ Basic.cluster_id, PowerConfiguration.cluster_id, Identify.cluster_id, IasZoneDoorbellCluster, Diagnostic.cluster_id, ], OUTPUT_CLUSTERS: [Ota.cluster_id], }, }, } ```
moritzbeck13 commented 1 year ago

@javicalle Can you open a PR for this?

javicalle commented 1 year ago

Not until there is confirmation that the quirk works as it should. Were you able to validate the quirk on your device?

moritzbeck13 commented 1 year ago

Not until there is confirmation that the quirk works as it should. Were you able to validate the quirk on your device?

After repairing the device with the new quirk enabled, the behaviour is as follows:

Just for clarity, this is what I expected to happen:

javicalle commented 1 year ago

Please attach the debug logs for button and tamper indicating the sequence of events. You can do it by enabling the debug logs from the device view.

moritzbeck13 commented 1 year ago

error_log-1.txt

  1. press bell
  2. release bell
  3. press bell
  4. release bell
  5. press tamper
  6. release tamper
  7. press tamper
  8. release tamper
  9. press bell
  10. press tamper
  11. release tamper
  12. release bell
  13. press bell
  14. press tamper
  15. release bell
  16. release tamper

I'm not sure if every event came through, because the light didn't blink on every action, even though I actively waited a second or so between every action.

With regards to my previous comment, I have to correct something: The entity also sets and resets on releasing the bell/tamper button. So both pressing and releasing the bell button sets the entity to true and both pressing and releasing the tamper button resets the entity to false. Sorry for the confusion, I didn't test for this exact scenario (pressing/releasing intertwined), even though it makes much sense.

moritzbeck13 commented 1 year ago

Is there any further information I can provide?

github-actions[bot] commented 9 months ago

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. Please make sure to update to the latest version and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue has now been marked as stale and will be closed if no further activity occurs. Thank you for your contributions.

moritzbeck13 commented 9 months ago

Not stale

github-actions[bot] commented 3 months ago

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. Please make sure to update to the latest version and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue has now been marked as stale and will be closed if no further activity occurs. Thank you for your contributions.

moritzbeck13 commented 3 months ago

Not stale