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
744 stars 678 forks source link

[Device Support Request] _TZE200_bh3n6gk8 PIR sensor #1606

Closed Sh4d closed 1 year ago

Sh4d commented 2 years ago

Device shows up but has no sensors that change when motion is detected.

https://www.aliexpress.com/item/1005004095233195.html

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=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, 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", "0xef00" ], "out_clusters": [ "0x000a", "0x0019" ] } }, "manufacturer": "_TZE200_bh3n6gk8", "model": "TS0601", "class": "pir.PirMotion" } ```
Diagnostic information ```yaml { "home_assistant": { "installation_type": "Home Assistant Container", "version": "2022.6.2", "dev": false, "hassio": false, "virtualenv": false, "python_version": "3.9.12", "docker": true, "arch": "x86_64", "timezone": "America/Vancouver", "os_name": "Linux", "os_version": "4.15.0-171-generic", "run_as_root": true }, "custom_components": { "govee": { "version": "0.2.2", "requirements": [ "govee-api-laggat==0.2.2", "dacite==1.6.0" ] }, "smartthinq_sensors": { "version": "0.22.0", "requirements": [ "pycountry>=20.7.3", "xmltodict>=0.12.0", "chardet>=4.0.0" ] }, "hacs": { "version": "1.25.5", "requirements": [ "aiogithubapi>=22.2.4" ] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/zha", "requirements": [ "bellows==0.30.0", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.75", "zigpy-deconz==0.16.0", "zigpy==0.45.1", "zigpy-xbee==0.14.0", "zigpy-zigate==0.7.4", "zigpy-znp==0.7.0" ], "usb": [ { "vid": "10C4", "pid": "EA60", "description": "*2652*", "known_devices": [ "slae.sh cc2652rb stick" ] }, { "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" ], "zeroconf": [ { "type": "_esphomelib._tcp.local.", "name": "tube*" }, { "type": "_zigate-zigbee-gateway._tcp.local.", "name": "*zigate*" } ], "after_dependencies": [ "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": 7406, "manufacturer": "_TZE200_bh3n6gk8", "model": "TS0601", "name": "_TZE200_bh3n6gk8 TS0601", "quirk_applied": true, "quirk_class": "pir.PirMotion", "manufacturer_code": 4417, "power_source": "Battery or Unknown", "lqi": 199, "rssi": -69, "last_seen": "2022-06-05T19:40:02", "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=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, 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", "0xef00" ], "out_clusters": [ "0x000a", "0x0019" ] } } }, "entities": [ { "entity_id": "sensor.motion_2_power", "name": "_TZE200_bh3n6gk8 TS0601" } ], "neighbors": [], "endpoint_names": [ { "name": "IAS_ZONE" } ], "user_given_name": "Guest Bathroom Motion", "device_reg_id": "93813274d6467791bbb4904348ee469a", "area_id": "guest_bathroom" } } ```
Additional logs ``` ```
javicalle commented 2 years ago

I seems that you have a local quirk that match your device. Is the device signature the same without the quirk?

Can you try with the quirk from:

Debug logs from the device operation are welcomed.

Sh4d commented 2 years ago

Oops sorry, that's actually the quirk I installed. The only change I made was to the model name, but it didn't seem to make a difference. I don't get any kind of motion sensor in HA.

Here's the details without that quirk

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=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, 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", "0x0500" ], "out_clusters": [ "0x000a", "0x0019" ] } }, "manufacturer": "_TZE200_bh3n6gk8", "model": "TS0601", "class": "zigpy.device.Device" } ```
Diagnostic information ```yaml { "home_assistant": { "installation_type": "Home Assistant Container", "version": "2022.6.2", "dev": false, "hassio": false, "virtualenv": false, "python_version": "3.9.12", "docker": true, "arch": "x86_64", "timezone": "America/Vancouver", "os_name": "Linux", "os_version": "4.15.0-171-generic", "run_as_root": true }, "custom_components": { "govee": { "version": "0.2.2", "requirements": [ "govee-api-laggat==0.2.2", "dacite==1.6.0" ] }, "smartthinq_sensors": { "version": "0.22.0", "requirements": [ "pycountry>=20.7.3", "xmltodict>=0.12.0", "chardet>=4.0.0" ] }, "hacs": { "version": "1.25.5", "requirements": [ "aiogithubapi>=22.2.4" ] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/zha", "requirements": [ "bellows==0.30.0", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.75", "zigpy-deconz==0.16.0", "zigpy==0.45.1", "zigpy-xbee==0.14.0", "zigpy-zigate==0.7.4", "zigpy-znp==0.7.0" ], "usb": [ { "vid": "10C4", "pid": "EA60", "description": "*2652*", "known_devices": [ "slae.sh cc2652rb stick" ] }, { "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" ], "zeroconf": [ { "type": "_esphomelib._tcp.local.", "name": "tube*" }, { "type": "_zigate-zigbee-gateway._tcp.local.", "name": "*zigate*" } ], "after_dependencies": [ "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": 7406, "manufacturer": "_TZE200_bh3n6gk8", "model": "TS0601", "name": "_TZE200_bh3n6gk8 TS0601", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "manufacturer_code": 4417, "power_source": "Battery or Unknown", "lqi": null, "rssi": null, "last_seen": "2022-06-06T13:28:01", "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=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, 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", "0x0500" ], "out_clusters": [ "0x000a", "0x0019" ] } } }, "entities": [ { "entity_id": "binary_sensor.motion_2_ias_zone", "name": "_TZE200_bh3n6gk8 TS0601" }, { "entity_id": "sensor.motion_2_power", "name": "_TZE200_bh3n6gk8 TS0601" } ], "neighbors": [], "endpoint_names": [ { "name": "IAS_ZONE" } ], "user_given_name": "Guest Bathroom Motion", "device_reg_id": "93813274d6467791bbb4904348ee469a", "area_id": "guest_bathroom" } } ```
javicalle commented 2 years ago

Can you test with that quirk:

Not fully functional. Logs from the device are welcomed.

Sh4d commented 2 years ago

Did you mean to paste the same link again? That's the same quirk I had installed previously.

Is there a way to get additional logs you can point me to? Happy to provide anything I can. I'll try unpairing + re-pairing to see what logs I can get.

javicalle commented 2 years ago

Sorry, my fault. I misread your previous comment. Did you get any HA entity with the quirk? Maybe the battery status?

In order to advance, it is necessary the device logs when interacting with it. To do this, you must first enable the debug traces:

These can be too verbose so it is necessary to identify each of the events (detected motion, no motion, near motion, far motion, etc.) with their traces. First detect your device ID, that will allow to target the logs. In a trace like this one:

2022-05-28 19:56:18 DEBUG (MainThread) [zigpy.zcl] [0x711F:1:0xef00] Received ZCL frame: b'\t\x0c\x02\x00\x0be\x02\x00\x04\x00\x00\x03^'

the [0x711F:1:0xef00] tuple is [device:endpoint:cluster]. All the logs from your device [0x711F:N:0xABCD] are usefull. And some of the sorounding ones probably too.

Providing the traces without the relationship with the related events will not be useful to us.

If you need some help I can try to guide you.

Regards.

Sh4d commented 2 years ago

I retested the quirk, and this time it worked. I'm not sure what I was doing wrong before.

The smoke detection and luminance don't report anything, and the motion sensor reports its status backwards (triggering it sets the state to cleared). Otherwise it seems to work fine.

javicalle commented 2 years ago

In the other post it has been discussed if it was more appropriate to configure it as an IasZone than as an occupancy sensor, offering an alternative implementation for that. Not sure if that would fix the status backwards issue, if not it would be aesy to fix, but not sure if just in your device or for all the devices.

If I'm not wrong, it is only possible to detect movement and luminance (and not smoke detection). To find out what can happen with the luminance sensor, I need someone to provide the debug logs of the device.

github-actions[bot] commented 1 year 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.

ivan-gj commented 1 year ago

Hello! Hi, hopefully I can bring back some attention to this issue again!

I used the ZG-204ZL quirk, eliminating any trace of the illuminance sensor part, and I get proper occupancy readings (no issues with inverted values or anything like that), but:

Here are the relevant logs:

2023-08-09 14:08:46.396 DEBUG (MainThread) [zigpy.zcl] [0x3931:1:0xef00] Received ZCL frame: b'\t\xa6\x02\x00\x11\x01\x04\x00\x01\x00'
2023-08-09 14:08:46.397 DEBUG (MainThread) [zigpy.zcl] [0x3931:1:0xef00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, direction=<Direction.Client_to_Server: 1>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=166, command_id=2, *direction=<Direction.Client_to_Server: 1>)
2023-08-09 14:08:46.400 DEBUG (MainThread) [zigpy.zcl] [0x3931:1:0xef00] Decoded ZCL frame: PirMotionNoIlluminanceManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=17, datapoints=[TuyaDatapointData(dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x00', *payload=<enum8.undefined_0x00: 0>))]))
2023-08-09 14:08:46.401 DEBUG (MainThread) [zigpy.zcl] [0x3931:1:0xef00] Received command 0x02 (TSN 166): set_data_response(data=TuyaCommand(status=0, tsn=17, datapoints=[TuyaDatapointData(dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x00', *payload=<enum8.undefined_0x00: 0>))]))

2023-08-09 14:08:46.410 DEBUG (MainThread) [zigpy.zcl] [0x3931:1:0xef00] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 1>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=166, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>)
2023-08-09 14:08:46.411 DEBUG (MainThread) [zigpy.zcl] [0x3931:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.SUCCESS: 0>)

2023-08-09 14:08:56.413 DEBUG (MainThread) [zigpy.zcl] [0x3931:1:0xef00] Received ZCL frame: b'\t\xa7\x02\x00\x12\x01\x04\x00\x01\x01'
2023-08-09 14:08:56.413 DEBUG (MainThread) [zigpy.zcl] [0x3931:1:0xef00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, direction=<Direction.Client_to_Server: 1>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=167, command_id=2, *direction=<Direction.Client_to_Server: 1>)
2023-08-09 14:08:56.415 DEBUG (MainThread) [zigpy.zcl] [0x3931:1:0xef00] Decoded ZCL frame: PirMotionNoIlluminanceManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=18, datapoints=[TuyaDatapointData(dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x01', *payload=<enum8.undefined_0x01: 1>))]))
2023-08-09 14:08:56.416 DEBUG (MainThread) [zigpy.zcl] [0x3931:1:0xef00] Received command 0x02 (TSN 167): set_data_response(data=TuyaCommand(status=0, tsn=18, datapoints=[TuyaDatapointData(dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x01', *payload=<enum8.undefined_0x01: 1>))]))

2023-08-09 14:08:56.424 DEBUG (MainThread) [zigpy.zcl] [0x3931:1:0xef00] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 1>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=167, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>)
2023-08-09 14:08:56.425 DEBUG (MainThread) [zigpy.zcl] [0x3931:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.SUCCESS: 0>)

I hope I can help on getting this device fully working!

ivan-gj commented 1 year ago

Okay, not sure how it happened, because I tried a bunch of stuff, but maybe it was a re-pair that now shows all device data without issues!! No more smoke sensor, battery shows now at 100 %.

I don't exactly know how it happened, but here's some things one can try:

  1. fully restart Home Assistant
  2. delete device (it actually took me a few tries until I saw it disappearing from the list of devices)
  3. pair it back in

Here's the code:

ts0601_pirmotion_no_illuminance.py ```python """Tuya motion rechargeable occupancy sensor.""" from typing import Dict from zigpy.profiles import zha from zigpy.quirks import CustomDevice import zigpy.types as t from zigpy.zcl.clusters.general import Basic, Ota, Time from zigpy.zcl.clusters.measurement import OccupancySensing from zigpy.zcl.clusters.security import IasZone from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODELS_INFO, OUTPUT_CLUSTERS, PROFILE_ID, ) from zhaquirks.tuya import TuyaLocalCluster from zhaquirks.tuya.mcu import ( DPToAttributeMapping, TuyaMCUCluster, TuyaPowerConfigurationCluster, ) class TuyaOccupancySensing(OccupancySensing, TuyaLocalCluster): """Tuya local OccupancySensing cluster.""" class SensitivityLevel(t.enum8): """Sensitivity level enum.""" LOW = 0x00 MEDIUM = 0x01 HIGH = 0x02 class OnTimeValues(t.enum8): """Sensitivity level enum.""" _10_SEC = 0x00 _30_SEC = 0x01 _60_SEC = 0x02 _120_SEC = 0x03 class PirMotionNoIlluminanceManufCluster(TuyaMCUCluster): """Neo manufacturer cluster.""" attributes = TuyaMCUCluster.attributes.copy() attributes.update({0xEF09: ("sensitivity_level", SensitivityLevel)}) attributes.update({0xEF0A: ("keep_time", OnTimeValues)}) dp_to_attribute: Dict[int, DPToAttributeMapping] = { 1: DPToAttributeMapping( TuyaOccupancySensing.ep_attribute, "occupancy", converter=lambda x: IasZone.ZoneStatus.Alarm_1 if not x else 0, ), 4: DPToAttributeMapping( TuyaPowerConfigurationCluster.ep_attribute, "battery_percentage_remaining", ), 9: DPToAttributeMapping( TuyaMCUCluster.ep_attribute, "sensitivity_level", converter=lambda x: SensitivityLevel(x), ), 10: DPToAttributeMapping( TuyaMCUCluster.ep_attribute, "keep_time", converter=lambda x: OnTimeValues(x), ) } data_point_handlers = { 1: "_dp_2_attr_update", 4: "_dp_2_attr_update", 9: "_dp_2_attr_update", 10: "_dp_2_attr_update", } class PirMotionNoIlluminance(CustomDevice): """Tuya PIR motion sensor.""" signature = { MODELS_INFO: [("_TZE200_bh3n6gk8", "TS0601")], ENDPOINTS: { # endpoints=1 profile=260 device_type=0x0402 # in_clusters=[0x0000, 0x0001, 0x0500], # out_clusters=[0x000a, 0x0019] 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.IAS_ZONE, INPUT_CLUSTERS: [ Basic.cluster_id, TuyaPowerConfigurationCluster.cluster_id, IasZone.cluster_id, ], OUTPUT_CLUSTERS: [ Time.cluster_id, Ota.cluster_id, ], } }, } replacement = { ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.IAS_ZONE, INPUT_CLUSTERS: [ Basic.cluster_id, TuyaPowerConfigurationCluster, PirMotionNoIlluminanceManufCluster, TuyaOccupancySensing, ], OUTPUT_CLUSTERS: [ Time.cluster_id, Ota.cluster_id, ], } } } ```