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
722 stars 670 forks source link

[Device Support Request] MoesHouse Presence sensor #1645

Closed sparkydave1981 closed 11 months ago

sparkydave1981 commented 2 years ago

Is your feature request related to a problem? Please describe. Device support

Describe the solution you'd like Please provide support for MoesHouse (Tuya) Zigbee Presence Sensor

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=4098, 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=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)", "endpoints": { "1": { "profile_id": 260, "device_type": "0x0051", "in_clusters": [ "0x0000", "0x0004", "0x0005", "0xef00" ], "out_clusters": [ "0x000a", "0x0019" ] } }, "manufacturer": "_TZE200_ikvncluo", "model": "TS0601", "class": "zigpy.device.Device" } ```
Diagnostic information ```yaml { "home_assistant": { "installation_type": "Home Assistant OS", "version": "2022.6.7", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.9.12", "docker": true, "arch": "x86_64", "timezone": "Australia/Perth", "os_name": "Linux", "os_version": "5.15.45", "supervisor": "2022.06.2", "host_os": "Home Assistant OS 8.2", "docker_version": "20.10.14", "chassis": "embedded", "run_as_root": true }, "custom_components": { "braviatv_psk": { "version": "0.4.2", "requirements": [ "pySonyBraviaPSK==0.2.4" ] }, "browser_mod": { "version": "1.5.3", "requirements": [] }, "adaptive_lighting": { "version": "1.0.14", "requirements": [] }, "presence_simulation": { "version": "2.2", "requirements": [] }, "tuya_local": { "version": "1.2.3", "requirements": [ "pycryptodome~=3.9", "pytuya~=7.0.5" ] }, "google_home": { "version": "1.9.13", "requirements": [ "glocaltokens==0.6.6" ] }, "netradio": { "version": "2013.3.0", "requirements": [] }, "bureau_of_meteorology": { "version": "1.1.10", "requirements": [] }, "bom_radar": { "version": "1.2.3", "requirements": [] }, "smartir": { "version": "1.17.6", "requirements": [ "aiofiles==0.6.0" ] }, "anniversaries": { "version": "4.5.0", "requirements": [ "python-dateutil>=2.8.1", "integrationhelper>=0.2.2", "voluptuous>=0.12.1" ] }, "feedparser": { "version": "0.1.7", "requirements": [ "feedparser==6.0.8" ] }, "sleep_as_android": { "version": "1.9.2", "requirements": [ "pyhaversion" ] }, "fronius_inverter": { "version": "v0.9.8", "requirements": [] }, "hacs": { "version": "1.25.5", "requirements": [ "aiogithubapi>=22.2.4" ] }, "fullykiosk": { "version": "1.0.2", "requirements": [ "python-fullykiosk==0.0.11" ] }, "localtuya": { "version": "4.0.1", "requirements": [] }, "ytube_music_player": { "version": "20220205.01", "requirements": [ "ytmusicapi==0.19.5", "pytube==10.5.1", "integrationhelper==0.2.2" ] }, "webrtc": { "version": "v2.3.0", "requirements": [] }, "plex_assistant": { "version": "1.1.9", "requirements": [ "gTTs>=2.2.1", "pychromecast>=8.0.0", "rapidfuzz==1.1.1", "plexapi>=4.3.0", "awesomeversion>=21.2.2" ] }, "watchman": { "version": "0.5.1", "requirements": [ "prettytable==3.0.0" ] }, "frigate": { "version": "2.3", "requirements": [] }, "mass": { "version": "2022.6.10", "requirements": [ "music-assistant==1.4.11" ] }, "alarmo": { "version": "v1.9.4", "requirements": [] } }, "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": 63169, "manufacturer": "_TZE200_ikvncluo", "model": "TS0601", "name": "_TZE200_ikvncluo TS0601", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "manufacturer_code": 4098, "power_source": "Mains", "lqi": 239, "rssi": -64, "last_seen": "2022-07-07T10:57:41", "available": true, "device_type": "Router", "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=4098, 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=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)", "endpoints": { "1": { "profile_id": 260, "device_type": "0x0051", "in_clusters": [ "0x0000", "0x0004", "0x0005", "0xef00" ], "out_clusters": [ "0x000a", "0x0019" ] } } }, "entities": [], "neighbors": [], "endpoint_names": [ { "name": "SMART_PLUG" } ], "user_given_name": "Ensuite Presence", "device_reg_id": "af96549acbdde6ed48a449434bf1a679", "area_id": "739384a020964a66982b7f118ece74c1" } } ```
Additional logs ``` Paste any additional debug logs here. Don't remove the extra line breaks outside the ``` marks. ```

Additional context image

javicalle commented 2 years ago

Can you try to add the device to the MmwRadarMotion quirk?

If you are not familiar, there are some guides about it. Maybe the most popular can be:

You will need to copy the ts0601_motion.py file in your local custom_zha_quirks folder:

Add your manufacturer in the MmwRadarMotion MODELS_INFO:

        MODELS_INFO: [
            ("_TZE200_ar0slwnd", "TS0601"),
            ("_TZE200_ikvncluo", "TS0601"),
            ("_TZE200_sfiy5tfs", "TS0601"),
            ("_TZE200_mrf6vtua", "TS0601"),
            ("_TZE200_ztc6ggyl", "TS0601"),
        ],

Save & restart.

Then check if device signature changes, that would mean that the device loads the quirk.

javicalle commented 2 years ago

If the quirk is working, do you mind to create the PR to add your device to the mainstream?

Just edit from the web the file content with the detected changes and follow the instructions:

sparkydave1981 commented 2 years ago

This has been added in another issue: https://github.com/zigpy/zha-device-handlers/pull/1591

However it really needs to be improved such that the GUI has control of the device settings rather than only providing the two sensor entities.

sparkydave1981 commented 2 years ago

At the risk of having this in two locations, the other Issue (1591) has already been merged so any further investigation work probably needds to be done here instead.

I'm happy to do the testing if someone can guide me a little.

This is what I see for that cluster: image image

So I take it we need to line those up with these somehow?

// TuYa Smart Human Presense Sensor tshpsPresenceState: 1, tshpscSensitivity: 2, tshpsMinimumRange: 3, tshpsMaximumRange: 4, tshpsTargetDistance: 9, tshpsDetectionDelay: 101, tshpsFadingTime: 102, tshpsIlluminanceLux: 104, tshpsCLI: 103, // not recognize tshpsSelfTest: 6, // not recognize

sparkydave1981 commented 2 years ago

Looking at the default values of the MmwRadarManufCluster I can see the following: dp_101 = 1 dp_101 = 600 dp_103= blank dp_105 = None dp_106 = None dp_107 = None dp_108 = None dp_2 = 7 (I have a feeling this is the sensitivity which may be between 0 and 9) dp_3 = 0 dp_4 = 600 dp_6 = enum8.undefined_0x01 mcu_version = 2.0.4

smittong commented 2 years ago

Hello

I connected the presence sensor ("_TZE200_ikvncluo") back via the SmartLife app to get the dp_id values from Tuya IOT. This is the resulting debugging decode: If someone could take these to make a configurable quirk for the "_TZE200_ikvncluo" that would be awesome. I'm not sure this is 100% correct from Tuya IOT - also no info on Lux levels for example. Note the example dp_4 is the maximum distance value and as reported by @sparkydave1981 above the value of 600 is for the default value of 6 meters. And dp_3 is the minimum distance and if you wanted that to be 1 meter you would have to enter 100. According to the product specs the max detect range is 6 meters, but the Tuya IOT and SmartLife app allows for a value up to 9.5 meters (950). Could the units be set to "cm" (centimeters) to match the device values?

{ "result": { "category": "hps", "functions": [ { "code": "sensitivity", "dp_id": 2, "type": "Integer", "values": "{\"min\":0,\"max\":9,\"scale\":0,\"step\":1}" }, { "code": "near_detection", "dp_id": 3, "type": "Integer", "values": "{\"unit\":\"m\",\"min\":0,\"max\":950,\"scale\":2,\"step\":15}" }, { "code": "far_detection", "dp_id": 4, "type": "Integer", "values": "{\"unit\":\"m\",\"min\":0,\"max\":950,\"scale\":2,\"step\":15}" } ], "status": [ { "code": "presence_state", "dp_id": 1, "type": "Enum", "values": "{\"range\":[\"none\",\"presence\"]}" }, { "code": "sensitivity", "dp_id": 2, "type": "Integer", "values": "{\"min\":0,\"max\":9,\"scale\":0,\"step\":1}" }, { "code": "near_detection", "dp_id": 3, "type": "Integer", "values": "{\"unit\":\"m\",\"min\":0,\"max\":950,\"scale\":2,\"step\":15}" }, { "code": "far_detection", "dp_id": 4, "type": "Integer", "values": "{\"unit\":\"m\",\"min\":0,\"max\":950,\"scale\":2,\"step\":15}" }, { "code": "checking_result", "dp_id": 6, "type": "Enum", "values": "{\"range\":[\"checking\",\"check_success\",\"check_failure\",\"others\",\"comm_fault\",\"radar_fault\"]}" }, { "code": "target_dis_closest", "dp_id": 9, "type": "Integer", "values": "{\"unit\":\"m\",\"min\":0,\"max\":1000,\"scale\":2,\"step\":1}" } ] }, "success": true, "t": 1658791225182, "tid": "5cce9b550c7011edaf8fbae27635b1d4" }

screenshot from the SmartLife App showing the configurable options for the device:

Screenshot_20220726-115615

PlusPlus-ua commented 2 years ago

I've almost completed a quirk for this device. Here is a source code:

``` """Tuya mmw radar occupancy sensor.""" import math from typing import Dict, 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 ( AnalogInput, AnalogOutput, Basic, GreenPowerProxy, Groups, Identify, Ota, Scenes, Time, ) from zigpy.zcl.clusters.measurement import ( IlluminanceMeasurement, OccupancySensing ) from zigpy.zcl.clusters.security import IasZone from zhaquirks import Bus, LocalDataCluster, MotionOnEvent from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODEL, MOTION_EVENT, OUTPUT_CLUSTERS, PROFILE_ID, ) from zhaquirks.tuya import ( NoManufacturerCluster, TuyaLocalCluster, TuyaNewManufCluster, ) from zhaquirks.tuya.mcu import ( TuyaDPType, DPToAttributeMapping, TuyaAttributesCluster, TuyaMCUCluster, ) class TuyaMmwRadarSelfTest(t.enum8): """Mmw radar self test values.""" TESTING = 0 TEST_SUCCESS = 1 TEST_FAILURE = 2 OTHER = 3 COMM_FAULT = 4 RADAR_FAULT = 5 class TuyaOccupancySensing(OccupancySensing, TuyaLocalCluster): """Tuya local OccupancySensing cluster.""" class TuyaIlluminanceMeasurement(IlluminanceMeasurement, TuyaLocalCluster): """Tuya local IlluminanceMeasurement cluster.""" class TuyaMmwRadarSensitivity(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for sensitivity.""" def __init__(self, *args, **kwargs): """Init.""" super().__init__(*args, **kwargs) self._update_attribute( self.attributes_by_name["description"].id, "Sensitivity" ) self._update_attribute(self.attributes_by_name["min_present_value"].id, 1) self._update_attribute(self.attributes_by_name["max_present_value"].id, 9) self._update_attribute(self.attributes_by_name["resolution"].id, 1) class TuyaMmwRadarMinRange(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for min range.""" def __init__(self, *args, **kwargs): """Init.""" super().__init__(*args, **kwargs) self._update_attribute( self.attributes_by_name["description"].id, "Min range (cm)" ) self._update_attribute(self.attributes_by_name["min_present_value"].id, 0) self._update_attribute(self.attributes_by_name["max_present_value"].id, 950) self._update_attribute(self.attributes_by_name["resolution"].id, 10) self._update_attribute( self.attributes_by_name["engineering_units"].id, 118 ) # 118: centimeters class TuyaMmwRadarMaxRange(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for max range.""" def __init__(self, *args, **kwargs): """Init.""" super().__init__(*args, **kwargs) self._update_attribute( self.attributes_by_name["description"].id, "Max range (cm)" ) self._update_attribute(self.attributes_by_name["min_present_value"].id, 0) self._update_attribute(self.attributes_by_name["max_present_value"].id, 950) self._update_attribute(self.attributes_by_name["resolution"].id, 10) self._update_attribute( self.attributes_by_name["engineering_units"].id, 18 ) # 118: centimeters class TuyaMmwRadarDetectionDelay(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for detection delay.""" def __init__(self, *args, **kwargs): """Init.""" super().__init__(*args, **kwargs) self._update_attribute( self.attributes_by_name["description"].id, "Detection delay" ) self._update_attribute(self.attributes_by_name["min_present_value"].id, 0.1) self._update_attribute(self.attributes_by_name["max_present_value"].id, 30) self._update_attribute(self.attributes_by_name["resolution"].id, 0.1) self._update_attribute( self.attributes_by_name["engineering_units"].id, 73 ) # 73: seconds class TuyaMmwRadarFadingTime(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for fading time.""" def __init__(self, *args, **kwargs): """Init.""" super().__init__(*args, **kwargs) self._update_attribute( self.attributes_by_name["description"].id, "Fading time" ) self._update_attribute(self.attributes_by_name["min_present_value"].id, 0.1) self._update_attribute(self.attributes_by_name["max_present_value"].id, 30) self._update_attribute(self.attributes_by_name["resolution"].id, 0.1) self._update_attribute( self.attributes_by_name["engineering_units"].id, 73 ) # 73: seconds class TuyaMmwRadarTargetDistance(TuyaAttributesCluster, AnalogInput): """AnalogInput cluster for target distance.""" def __init__(self, *args, **kwargs): """Init.""" super().__init__(*args, **kwargs) self._update_attribute( self.attributes_by_name["description"].id, "Target distance" ) self._update_attribute( self.attributes_by_name["engineering_units"].id, 31 ) # 31: meters class TuyaMmwRadarCluster(NoManufacturerCluster, TuyaMCUCluster): """Mmw radar cluster.""" attributes = TuyaMCUCluster.attributes.copy() attributes.update( { # ramdom attribute IDs 0xEF01: ("occupancy", t.uint32_t, True), 0xEF02: ("sensitivity", t.uint32_t, True), 0xEF03: ("min_range", t.uint32_t, True), 0xEF04: ("max_range", t.uint32_t, True), 0xEF06: ("self_test", TuyaMmwRadarSelfTest, True), 0xEF09: ("target_distance", t.uint32_t, True), 0xEF65: ("detection_delay", t.uint32_t, True), 0xEF66: ("fading_time", t.uint32_t, True), 0xEF67: ("cli", t.CharacterString, True), 0xEF68: ("illuminance", t.uint32_t, True), } ) dp_to_attribute: Dict[int, DPToAttributeMapping] = { 1: DPToAttributeMapping( TuyaOccupancySensing.ep_attribute, "occupancy", dp_type=TuyaDPType.BOOL, ), 2: DPToAttributeMapping( TuyaMmwRadarSensitivity.ep_attribute, "present_value", dp_type=TuyaDPType.VALUE, ), 3: DPToAttributeMapping( TuyaMmwRadarMinRange.ep_attribute, "present_value", dp_type=TuyaDPType.VALUE, endpoint_id=2, ), 4: DPToAttributeMapping( TuyaMmwRadarMaxRange.ep_attribute, "present_value", dp_type=TuyaDPType.VALUE, endpoint_id=3, ), 6: DPToAttributeMapping( TuyaMCUCluster.ep_attribute, "self_test", dp_type=TuyaDPType.ENUM, ), 9: DPToAttributeMapping( TuyaMmwRadarTargetDistance.ep_attribute, "present_value", converter=lambda x: x / 100, dp_type=TuyaDPType.VALUE, ), 101: DPToAttributeMapping( TuyaMmwRadarDetectionDelay.ep_attribute, "present_value", dp_type=TuyaDPType.VALUE, converter=lambda x: x / 10, dp_converter=lambda x: x * 10, endpoint_id=4, ), 102: DPToAttributeMapping( TuyaMmwRadarFadingTime.ep_attribute, "present_value", dp_type=TuyaDPType.VALUE, converter=lambda x: x / 10, dp_converter=lambda x: x * 10, endpoint_id=5, ), 103: DPToAttributeMapping( TuyaMCUCluster.ep_attribute, "cli", dp_type=TuyaDPType.STRING, ), 104: DPToAttributeMapping( TuyaIlluminanceMeasurement.ep_attribute, "measured_value", dp_type=TuyaDPType.VALUE, converter=lambda x: 10000 * math.log10(x) + 1, ), } data_point_handlers = { 1: "_dp_2_attr_update", 2: "_dp_2_attr_update", 3: "_dp_2_attr_update", 4: "_dp_2_attr_update", 6: "_dp_2_attr_update", 9: "_dp_2_attr_update", 101: "_dp_2_attr_update", 102: "_dp_2_attr_update", 103: "_dp_2_attr_update", 104: "_dp_2_attr_update", } class TuyaMmwRadarOccupancy(CustomDevice): """Millimeter wave occupancy sensor.""" signature = { MODEL: "TS0601", ENDPOINTS: { # 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaMmwRadarCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, }, } replacement = { ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaMmwRadarCluster, TuyaIlluminanceMeasurement, TuyaOccupancySensing, TuyaMmwRadarTargetDistance, TuyaMmwRadarSensitivity, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, 2: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE, INPUT_CLUSTERS: [ TuyaMmwRadarMinRange, ], OUTPUT_CLUSTERS: [], }, 3: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE, INPUT_CLUSTERS: [ TuyaMmwRadarMaxRange, ], OUTPUT_CLUSTERS: [], }, 4: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE, INPUT_CLUSTERS: [ TuyaMmwRadarDetectionDelay, ], OUTPUT_CLUSTERS: [], }, 5: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE, INPUT_CLUSTERS: [ TuyaMmwRadarFadingTime, ], OUTPUT_CLUSTERS: [], }, } } ```

Here is screenshot of exposed entities: image

Have few questions. I have exposed configuration entities using AnalogOutput cluster. Is it possible to prevent adding "Number" string before entity name? Is it possible to choose which type of user interface will be used for entity (slider or edit box)?

Waiting for testing results.

MattWestb commented 2 years ago

The second question i think its depending of the unit you have configurated is ZHA selecting the type.

For the first one is HA adding its deom the class and its not possible adding any extra information. 2 PR have being made for adding it "information" for displaying in ZHA but both is being discarded also if tagging them with "tuya" or one "ZHA" manufacture number for doing it 100% Zigbee compatible is not helping.

PS: Nice have you back !!!!

PlusPlus-ua commented 2 years ago

The second question i think its depending of the unit you have configurated is ZHA selecting the type.

Have investigated this. It doesn't depend on unit, only on number of "steps". If the number of "steps" is more than 256 it will be edit box.

MattWestb commented 2 years ago

So its with people that cant read code and only speculating ;-((

vietpv89 commented 2 years ago

I've almost completed a quirk for this device. Here is a source code:

Here is screenshot of exposed entities: image

Have few questions. I have exposed configuration entities using AnalogOutput cluster. Is it possible to prevent adding "Number" string before entity name? Is it possible to choose which type of user interface will be used for entity (slider or edit box)?

Waiting for testing results.

Hello PlusPlus-ua, how to use your quirk ? i'm already modify configuration image and copy your code, put it here image But my device still no change any thing, not same your screen shot. image

pls help !

PlusPlus-ua commented 2 years ago

Hi @vietpv89, according to your screenshot, my code is not used. It seems like your ZHA still use file modified as mentioned in https://github.com/zigpy/zha-device-handlers/issues/1645#issuecomment-1192850979 Name of the class in my code TuyaMmwRadarOccupancy. Recheck please content of ts0601_motion.py file.

image

javicalle commented 2 years ago

Also delete the __pycache__ folder every time you modified the file and restart HA.

PlusPlus-ua commented 2 years ago

@vietpv89 Do you have any new response?

sparkydave1981 commented 2 years ago

Any update on this quirk? I'm wanting to try and get the sensor to switch back to "clear" faster after motion stops. Is that ID: 0x0021 ?

javicalle commented 1 year ago

I'm wanting to try and get the sensor to switch back to "clear" faster after motion stops. Is that ID: 0x0021 ?

I would say that is the DP_102 (fading time or hold time)

sparkydave1981 commented 1 year ago

I would say that is the DP_102 (fading time or hold time)

I'm not sure which setting that is... I was thinking it's the pir_o_to_u_delay image

javicalle commented 1 year ago

I was thinking it's the pir_o_to_u_delay

That would be the 'standar' value, but nobody has verified or tested which DP is using Tuya, and nobody has mapped the DP to that attribute. My guess is that the property you want to modify is the dp_102 of the cluster MmwRadarManufCluster. If it works, maybe we can map the DP to that attribute.

sparkydave1981 commented 1 year ago

For that cluster attribute, the default was 600. I tried setting it to 30 to see what happens. This is my first time playing with clusters so I'm not sure I've done it correctly. If I enter 30 into either box and hit 'set attribute', the 'value' box still shows 600. Is that correct? Do I just leave 30 in the 'override' box? image

javicalle commented 1 year ago

You must edit the "Value" value and leave empty the "Manufacturer Code Override". Then push the "Set zigbee attribute".

To check, just push the "get zigbee attribute". If value don't change, the debug logs will be needed.

sparkydave1981 commented 1 year ago

You must edit the "Value" value and leave empty the "Manufacturer Code Override". Then push the "Set zigbee attribute".

Yep, so that's what I initially tried but it still says '600' which is the default value.

How do I get the debug logs? what would I be looking for in the logs?

javicalle commented 1 year ago

Take a look here:

Once enabled, look at the logs when you try to update the value. Call the command several times to be able to identify the generated logs and post it here.

sparkydave1981 commented 1 year ago

With those debug settings my log gets spammed so hard it's impossible to do much at all! I had a 2GB log in a matter of 16 hours or so...

sparkydave1981 commented 1 year ago

Waiting for testing results.

Any update on this? Sending values via the device "manage zigbee device" UI doesn't seem to actually update the device for me. (I haven't tried your quirk as yet as I'm not entirely sure how.... I have an existing quirk that was used to get the device working to it's current level)

PlusPlus-ua commented 1 year ago

Any update on this?

Yes, I've updated version. It looks like TuyaAttributesCluster from zhaquirks.tuya.mcu doesn't support float values, so I've changed all settings to int. So, delays measured now in milisecons and ranges in centimeters. I'ts a bit ugly but works. I also has problem with Illuminance, I not sure in conversation formula, but it may be a defect of mine sensor.

Here is my current code:

"""Tuya mmw radar occupancy sensor."""

import math
from typing import Dict, 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 (
    AnalogInput,
    AnalogOutput,
    Basic,
    GreenPowerProxy,
    Groups,
    Identify,
    Ota,
    Scenes,
    Time,
)
from zigpy.zcl.clusters.measurement import (
    IlluminanceMeasurement,
    OccupancySensing
)
from zigpy.zcl.clusters.security import IasZone

from zhaquirks import Bus, LocalDataCluster, MotionOnEvent
from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODEL,
    MOTION_EVENT,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)
from zhaquirks.tuya import (
    NoManufacturerCluster,
    TuyaLocalCluster,
    TuyaNewManufCluster,
)
from zhaquirks.tuya.mcu import (
    TuyaDPType,
    DPToAttributeMapping,
    TuyaAttributesCluster,
    TuyaMCUCluster,
)

class TuyaMmwRadarSelfTest(t.enum8):
    """Mmw radar self test values."""
    TESTING = 0
    TEST_SUCCESS = 1
    TEST_FAILURE = 2
    OTHER = 3
    COMM_FAULT = 4
    RADAR_FAULT = 5

class TuyaOccupancySensing(OccupancySensing, TuyaLocalCluster):
    """Tuya local OccupancySensing cluster."""

class TuyaIlluminanceMeasurement(IlluminanceMeasurement, TuyaLocalCluster):
    """Tuya local IlluminanceMeasurement cluster."""

class TuyaMmwRadarSensitivity(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for sensitivity."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Sensitivity"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 1)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 9)
        self._update_attribute(self.attributes_by_name["resolution"].id, 1)

class TuyaMmwRadarMinRange(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for min range."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Min range"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 950)
        self._update_attribute(self.attributes_by_name["resolution"].id, 10)
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 118
        )  # 31: meters

class TuyaMmwRadarMaxRange(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for max range."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Max range"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 950)
        self._update_attribute(self.attributes_by_name["resolution"].id, 10)
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 118
        )  # 31: meters

class TuyaMmwRadarDetectionDelay(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for detection delay."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Detection delay"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 100)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 20000)
        self._update_attribute(self.attributes_by_name["resolution"].id, 100)
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 159
        )  # 73: seconds

class TuyaMmwRadarFadingTime(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for fading time."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Fading time"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 1000)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 200000)
        self._update_attribute(self.attributes_by_name["resolution"].id, 1000)
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 159
        )  # 73: seconds

class TuyaMmwRadarTargetDistance(TuyaAttributesCluster, AnalogInput):
    """AnalogInput cluster for target distance."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Target distance"
        )
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 31
        )  # 31: meters

class TuyaMmwRadarCluster(NoManufacturerCluster, TuyaMCUCluster):
    """Mmw radar cluster."""
    attributes = TuyaMCUCluster.attributes.copy()
    attributes.update(
        {
            # ramdom attribute IDs
            0xEF01: ("occupancy", t.uint32_t, True),
            0xEF02: ("sensitivity", t.uint32_t, True),
            0xEF03: ("min_range", t.uint32_t, True),
            0xEF04: ("max_range", t.uint32_t, True),
            0xEF06: ("self_test", TuyaMmwRadarSelfTest, True),
            0xEF09: ("target_distance", t.uint32_t, True),
            0xEF65: ("detection_delay", t.uint32_t, True),
            0xEF66: ("fading_time", t.uint32_t, True),
            0xEF67: ("cli", t.CharacterString, True),
            0xEF68: ("illuminance", t.uint32_t, True),
        }
    )

    dp_to_attribute: Dict[int, DPToAttributeMapping] = {
        1: DPToAttributeMapping(
            TuyaOccupancySensing.ep_attribute,
            "occupancy",
            dp_type=TuyaDPType.BOOL,
        ),
        2: DPToAttributeMapping(
            TuyaMmwRadarSensitivity.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
        ),
        3: DPToAttributeMapping(
            TuyaMmwRadarMinRange.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
            endpoint_id=2,
            #converter=lambda x: x / 100,
            #dp_converter=lambda x: x * 100,
        ),
        4: DPToAttributeMapping(
            TuyaMmwRadarMaxRange.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
            endpoint_id=3,
            #converter=lambda x: x / 100,
            #dp_converter=lambda x: x * 100,
        ),
        6: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "self_test",
            dp_type=TuyaDPType.ENUM,
        ),
        9: DPToAttributeMapping(
            TuyaMmwRadarTargetDistance.ep_attribute,
            "present_value",
            #converter=lambda x: x / 100,
            dp_type=TuyaDPType.VALUE,
        ),
        101: DPToAttributeMapping(
            TuyaMmwRadarDetectionDelay.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: x * 100,
            dp_converter=lambda x: x // 100,
            endpoint_id=4,
        ),
        102: DPToAttributeMapping(
            TuyaMmwRadarFadingTime.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: x * 100,
            dp_converter=lambda x: x // 100,
            endpoint_id=5,
        ),
        103: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "cli",
            dp_type=TuyaDPType.STRING,
        ),
        104: DPToAttributeMapping(
            TuyaIlluminanceMeasurement.ep_attribute,
            "measured_value",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: math.log10(x) * 10000 + 1,
        ),
    }

    data_point_handlers = {
        1: "_dp_2_attr_update",
        2: "_dp_2_attr_update",
        3: "_dp_2_attr_update",
        4: "_dp_2_attr_update",
        6: "_dp_2_attr_update",
        9: "_dp_2_attr_update",
        101: "_dp_2_attr_update",
        102: "_dp_2_attr_update",
        103: "_dp_2_attr_update",
        104: "_dp_2_attr_update",
    }

class TuyaMmwRadarOccupancy(CustomDevice):
    """Millimeter wave occupancy sensor."""

    signature = {
        MODEL: "TS0601",
        ENDPOINTS: {
            # <SimpleDescriptor endpoint=1 profile=260 device_type=81
            # device_version=1
            # input_clusters=[0, 4, 5, 61184]
            # output_clusters=[10, 25]>
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaMmwRadarCluster.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaMmwRadarCluster,
                    TuyaIlluminanceMeasurement,
                    TuyaOccupancySensing,
                    TuyaMmwRadarTargetDistance,
                    TuyaMmwRadarSensitivity,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarMinRange,
                ],
                OUTPUT_CLUSTERS: [],
            },
            3: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarMaxRange,
                ],
                OUTPUT_CLUSTERS: [],
            },
            4: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarDetectionDelay,
                ],
                OUTPUT_CLUSTERS: [],
            },
            5: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarFadingTime,
                ],
                OUTPUT_CLUSTERS: [],
            },
        }
    }
sparkydave1981 commented 1 year ago

Here is my current code:

Thank you. How would I add this to my HA setup? When I first got these sensors I added a custom quirk called ts0601_motion.py in order to get a working sensor with just the basic two entities. Would I add your code as a new file?

sparkydave1981 commented 1 year ago

my log

Not sure how much of this is related but I see a bunch of mmWave stuff in there...

2022-10-28 13:30:10.503 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Decoded ZCL frame: MmwRadarManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=139, datapoints=[TuyaDatapointData(dp=9, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xd6\x01\x00\x00', *payload=470))]))
2022-10-28 13:30:10.503 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Received command 0x02 (TSN 29): set_data_response(data=TuyaCommand(status=0, tsn=139, datapoints=[TuyaDatapointData(dp=9, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xd6\x01\x00\x00', *payload=470))]))
2022-10-28 13:30:10.504 DEBUG (MainThread) [zigpy.zcl] [0x5F29: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, *is_reply=True), tsn=29, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:10.504 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.SUCCESS: 0>)
2022-10-28 13:30:10.505 DEBUG (MainThread) [zigpy_deconz.zigbee.application] Sending packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x5F29), dst_ep=1, source_route=None, extended_timeout=False, tsn=29, profile_id=260, cluster_id=61184, data=Serialized[b'\x18\x1d\x0b\x02\x00'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2022-10-28 13:30:10.505 DEBUG (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, ep: 1, profile: 0x0104, cluster_id: 0xef00, data: b'091d02008b09020004000001d6'
2022-10-28 13:30:10.505 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 183, <DeconzSendDataFlags.NONE: 0>, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, 260, 61184, 1, b'\x18\x1d\x0b\x02\x00', <DeconzTransmitOptions.USE_NWK_KEY_SECURITY: 2>, 0)
2022-10-28 13:30:10.507 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_request[2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 183]
2022-10-28 13:30:10.507 DEBUG (MainThread) [zigpy_deconz.api] APS data request response: [2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 183]
2022-10-28 13:30:10.516 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:10.516 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:10.516 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2022-10-28 13:30:10.517 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_confirm[12, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 183, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, 1, <TXStatus.SUCCESS: 0>, 0, 0, 0, 0]
2022-10-28 13:30:10.517 DEBUG (MainThread) [zigpy_deconz.api] APS data confirm response for request with id 183: 00
2022-10-28 13:30:10.517 DEBUG (MainThread) [zigpy_deconz.api] Request id: 0xb7 'aps_data_confirm' for <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, status: 0x00
2022-10-28 13:30:11.258 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:11.258 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:11.258 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, <DataIndicationFlags.Always_Use_NWK_Source_Addr: 1>)
2022-10-28 13:30:11.260 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_indication[32, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0xc2a8>, 1, 260, 1794, b'\x08U\n\x00\x04*\x1d\x00\x00', 0, 175, 191, 196, 142, 246, 2, -70]
2022-10-28 13:30:11.260 DEBUG (MainThread) [zigpy_deconz.api] APS data indication response: [32, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0xc2a8>, 1, 260, 1794, b'\x08U\n\x00\x04*\x1d\x00\x00', 0, 175, 191, 196, 142, 246, 2, -70]
2022-10-28 13:30:11.260 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0xC2A8), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=None, profile_id=260, cluster_id=1794, data=Serialized[b'\x08U\n\x00\x04*\x1d\x00\x00'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=191, rssi=-70)
2022-10-28 13:30:11.260 DEBUG (MainThread) [zigpy.zcl] [0xC2A8:1:0x0702] Received ZCL frame: b'\x08U\n\x00\x04*\x1d\x00\x00'
2022-10-28 13:30:11.261 DEBUG (MainThread) [zigpy.zcl] [0xC2A8:1:0x0702] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=0, direction=<Direction.Client_to_Server: 1>, disable_default_response=0, reserved=0, *is_cluster=False, *is_general=True, *is_reply=True), tsn=85, command_id=10, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:11.261 DEBUG (MainThread) [zigpy.zcl] [0xC2A8:1:0x0702] Decoded ZCL frame: Metering:Report_Attributes(attribute_reports=[Attribute(attrid=0x0400, value=TypeValue(type=int24s, value=29))])
2022-10-28 13:30:11.262 DEBUG (MainThread) [zigpy.zcl] [0xC2A8:1:0x0702] Received command 0x0A (TSN 85): Report_Attributes(attribute_reports=[Attribute(attrid=0x0400, value=TypeValue(type=int24s, value=29))])
2022-10-28 13:30:11.262 DEBUG (MainThread) [zigpy.zcl] [0xC2A8:1:0x0702] Attribute report received: instantaneous_demand=29
2022-10-28 13:30:11.269 DEBUG (MainThread) [zigpy.zcl] [0xC2A8:1:0x0702] 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, *is_reply=True), tsn=85, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:11.269 DEBUG (MainThread) [zigpy.zcl] [0xC2A8:1:0x0702] Sending reply: Default_Response(command_id=10, status=<Status.SUCCESS: 0>)
2022-10-28 13:30:11.269 DEBUG (MainThread) [zigpy_deconz.zigbee.application] Sending packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0xC2A8), dst_ep=1, source_route=None, extended_timeout=False, tsn=85, profile_id=260, cluster_id=1794, data=Serialized[b'\x18U\x0b\n\x00'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2022-10-28 13:30:11.269 DEBUG (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from <DeconzAddress address_mode=AddressMode.NWK address=0xc2a8>, ep: 1, profile: 0x0104, cluster_id: 0x0702, data: b'08550a00042a1d0000'
2022-10-28 13:30:11.270 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 184, <DeconzSendDataFlags.NONE: 0>, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0xc2a8 endpoint=1>, 260, 1794, 1, b'\x18U\x0b\n\x00', <DeconzTransmitOptions.USE_NWK_KEY_SECURITY: 2>, 0)
2022-10-28 13:30:11.272 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_request[2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 184]
2022-10-28 13:30:11.272 DEBUG (MainThread) [zigpy_deconz.api] APS data request response: [2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 184]
2022-10-28 13:30:11.280 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:11.280 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:11.281 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2022-10-28 13:30:11.282 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_confirm[12, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 184, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0xc2a8 endpoint=1>, 1, <TXStatus.SUCCESS: 0>, 0, 0, 0, 0]
2022-10-28 13:30:11.282 DEBUG (MainThread) [zigpy_deconz.api] APS data confirm response for request with id 184: 00
2022-10-28 13:30:11.282 DEBUG (MainThread) [zigpy_deconz.api] Request id: 0xb8 'aps_data_confirm' for <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0xc2a8 endpoint=1>, status: 0x00
2022-10-28 13:30:11.461 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:11.461 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:11.461 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, <DataIndicationFlags.Always_Use_NWK_Source_Addr: 1>)
2022-10-28 13:30:11.463 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_indication[31, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x77c0>, 1, 260, 2820, b'\x08N\n\x05\x05!\x13w', 0, 175, 255, 196, 142, 246, 2, -48]
2022-10-28 13:30:11.463 DEBUG (MainThread) [zigpy_deconz.api] APS data indication response: [31, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x77c0>, 1, 260, 2820, b'\x08N\n\x05\x05!\x13w', 0, 175, 255, 196, 142, 246, 2, -48]
2022-10-28 13:30:11.463 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x77C0), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=None, profile_id=260, cluster_id=2820, data=Serialized[b'\x08N\n\x05\x05!\x13w'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=255, rssi=-48)
2022-10-28 13:30:11.463 DEBUG (MainThread) [zigpy.zcl] [0x77C0:1:0x0b04] Received ZCL frame: b'\x08N\n\x05\x05!\x13w'
2022-10-28 13:30:11.464 DEBUG (MainThread) [zigpy.zcl] [0x77C0:1:0x0b04] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=0, direction=<Direction.Client_to_Server: 1>, disable_default_response=0, reserved=0, *is_cluster=False, *is_general=True, *is_reply=True), tsn=78, command_id=10, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:11.464 DEBUG (MainThread) [zigpy.zcl] [0x77C0:1:0x0b04] Decoded ZCL frame: ElectricalMeasurement:Report_Attributes(attribute_reports=[Attribute(attrid=0x0505, value=TypeValue(type=uint16_t, value=30483))])
2022-10-28 13:30:11.464 DEBUG (MainThread) [zigpy.zcl] [0x77C0:1:0x0b04] Received command 0x0A (TSN 78): Report_Attributes(attribute_reports=[Attribute(attrid=0x0505, value=TypeValue(type=uint16_t, value=30483))])
2022-10-28 13:30:11.464 DEBUG (MainThread) [zigpy.zcl] [0x77C0:1:0x0b04] Attribute report received: rms_voltage=30483
2022-10-28 13:30:11.465 DEBUG (MainThread) [zigpy.zcl] [0x77C0:1:0x0b04] 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, *is_reply=True), tsn=78, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:11.466 DEBUG (MainThread) [zigpy.zcl] [0x77C0:1:0x0b04] Sending reply: Default_Response(command_id=10, status=<Status.SUCCESS: 0>)
2022-10-28 13:30:11.466 DEBUG (MainThread) [zigpy_deconz.zigbee.application] Sending packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x77C0), dst_ep=1, source_route=None, extended_timeout=False, tsn=78, profile_id=260, cluster_id=2820, data=Serialized[b'\x18N\x0b\n\x00'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2022-10-28 13:30:11.466 DEBUG (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from <DeconzAddress address_mode=AddressMode.NWK address=0x77c0>, ep: 1, profile: 0x0104, cluster_id: 0x0b04, data: b'084e0a0505211377'
2022-10-28 13:30:11.466 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 185, <DeconzSendDataFlags.NONE: 0>, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x77c0 endpoint=1>, 260, 2820, 1, b'\x18N\x0b\n\x00', <DeconzTransmitOptions.USE_NWK_KEY_SECURITY: 2>, 0)
2022-10-28 13:30:11.468 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_request[2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 185]
2022-10-28 13:30:11.468 DEBUG (MainThread) [zigpy_deconz.api] APS data request response: [2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 185]
2022-10-28 13:30:11.476 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:11.476 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:11.476 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2022-10-28 13:30:11.477 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_confirm[12, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 185, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x77c0 endpoint=1>, 1, <TXStatus.SUCCESS: 0>, 0, 0, 0, 0]
2022-10-28 13:30:11.477 DEBUG (MainThread) [zigpy_deconz.api] APS data confirm response for request with id 185: 00
2022-10-28 13:30:11.477 DEBUG (MainThread) [zigpy_deconz.api] Request id: 0xb9 'aps_data_confirm' for <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x77c0 endpoint=1>, status: 0x00
2022-10-28 13:30:11.500 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:11.500 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:11.500 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, <DataIndicationFlags.Always_Use_NWK_Source_Addr: 1>)
2022-10-28 13:30:11.502 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_indication[36, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, 1, 260, 61184, b'\t\x1e\x02\x00\x8c\t\x02\x00\x04\x00\x00\x01\xfd', 0, 175, 255, 196, 142, 246, 2, -49]
2022-10-28 13:30:11.502 DEBUG (MainThread) [zigpy_deconz.api] APS data indication response: [36, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, 1, 260, 61184, b'\t\x1e\x02\x00\x8c\t\x02\x00\x04\x00\x00\x01\xfd', 0, 175, 255, 196, 142, 246, 2, -49]
2022-10-28 13:30:11.502 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x5F29), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=None, profile_id=260, cluster_id=61184, data=Serialized[b'\t\x1e\x02\x00\x8c\t\x02\x00\x04\x00\x00\x01\xfd'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=255, rssi=-49)
2022-10-28 13:30:11.503 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Received ZCL frame: b'\t\x1e\x02\x00\x8c\t\x02\x00\x04\x00\x00\x01\xfd'
2022-10-28 13:30:11.503 DEBUG (MainThread) [zigpy.zcl] [0x5F29: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, *is_reply=True), tsn=30, command_id=2, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:11.504 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Decoded ZCL frame: MmwRadarManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=140, datapoints=[TuyaDatapointData(dp=9, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xfd\x01\x00\x00', *payload=509))]))
2022-10-28 13:30:11.504 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Received command 0x02 (TSN 30): set_data_response(data=TuyaCommand(status=0, tsn=140, datapoints=[TuyaDatapointData(dp=9, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xfd\x01\x00\x00', *payload=509))]))
2022-10-28 13:30:11.505 DEBUG (MainThread) [zigpy.zcl] [0x5F29: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, *is_reply=True), tsn=30, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:11.505 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.SUCCESS: 0>)
2022-10-28 13:30:11.505 DEBUG (MainThread) [zigpy_deconz.zigbee.application] Sending packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x5F29), dst_ep=1, source_route=None, extended_timeout=False, tsn=30, profile_id=260, cluster_id=61184, data=Serialized[b'\x18\x1e\x0b\x02\x00'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2022-10-28 13:30:11.505 DEBUG (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, ep: 1, profile: 0x0104, cluster_id: 0xef00, data: b'091e02008c09020004000001fd'
2022-10-28 13:30:11.506 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 186, <DeconzSendDataFlags.NONE: 0>, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, 260, 61184, 1, b'\x18\x1e\x0b\x02\x00', <DeconzTransmitOptions.USE_NWK_KEY_SECURITY: 2>, 0)
2022-10-28 13:30:11.508 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_request[2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 186]
2022-10-28 13:30:11.508 DEBUG (MainThread) [zigpy_deconz.api] APS data request response: [2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 186]
2022-10-28 13:30:11.524 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:11.524 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:11.524 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2022-10-28 13:30:11.526 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_confirm[12, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 186, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, 1, <TXStatus.SUCCESS: 0>, 0, 0, 0, 0]
2022-10-28 13:30:11.526 DEBUG (MainThread) [zigpy_deconz.api] APS data confirm response for request with id 186: 00
2022-10-28 13:30:11.526 DEBUG (MainThread) [zigpy_deconz.api] Request id: 0xba 'aps_data_confirm' for <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, status: 0x00
2022-10-28 13:30:12.499 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:12.499 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:12.500 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, <DataIndicationFlags.Always_Use_NWK_Source_Addr: 1>)
2022-10-28 13:30:12.501 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_indication[36, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, 1, 260, 61184, b'\t\x1f\x02\x00\x8d\t\x02\x00\x04\x00\x00\x01\xfc', 0, 175, 255, 196, 142, 246, 2, -48]
2022-10-28 13:30:12.501 DEBUG (MainThread) [zigpy_deconz.api] APS data indication response: [36, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, 1, 260, 61184, b'\t\x1f\x02\x00\x8d\t\x02\x00\x04\x00\x00\x01\xfc', 0, 175, 255, 196, 142, 246, 2, -48]
2022-10-28 13:30:12.501 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x5F29), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=None, profile_id=260, cluster_id=61184, data=Serialized[b'\t\x1f\x02\x00\x8d\t\x02\x00\x04\x00\x00\x01\xfc'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=255, rssi=-48)
2022-10-28 13:30:12.501 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Received ZCL frame: b'\t\x1f\x02\x00\x8d\t\x02\x00\x04\x00\x00\x01\xfc'
2022-10-28 13:30:12.502 DEBUG (MainThread) [zigpy.zcl] [0x5F29: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, *is_reply=True), tsn=31, command_id=2, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:12.502 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Decoded ZCL frame: MmwRadarManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=141, datapoints=[TuyaDatapointData(dp=9, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xfc\x01\x00\x00', *payload=508))]))
2022-10-28 13:30:12.502 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Received command 0x02 (TSN 31): set_data_response(data=TuyaCommand(status=0, tsn=141, datapoints=[TuyaDatapointData(dp=9, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xfc\x01\x00\x00', *payload=508))]))
2022-10-28 13:30:12.504 DEBUG (MainThread) [zigpy.zcl] [0x5F29: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, *is_reply=True), tsn=31, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:12.504 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.SUCCESS: 0>)
2022-10-28 13:30:12.504 DEBUG (MainThread) [zigpy_deconz.zigbee.application] Sending packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x5F29), dst_ep=1, source_route=None, extended_timeout=False, tsn=31, profile_id=260, cluster_id=61184, data=Serialized[b'\x18\x1f\x0b\x02\x00'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2022-10-28 13:30:12.504 DEBUG (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, ep: 1, profile: 0x0104, cluster_id: 0xef00, data: b'091f02008d09020004000001fc'
2022-10-28 13:30:12.505 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 187, <DeconzSendDataFlags.NONE: 0>, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, 260, 61184, 1, b'\x18\x1f\x0b\x02\x00', <DeconzTransmitOptions.USE_NWK_KEY_SECURITY: 2>, 0)
2022-10-28 13:30:12.506 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_request[2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 187]
2022-10-28 13:30:12.506 DEBUG (MainThread) [zigpy_deconz.api] APS data request response: [2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 187]
2022-10-28 13:30:12.515 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:12.515 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:12.515 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2022-10-28 13:30:12.516 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_confirm[12, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 187, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, 1, <TXStatus.SUCCESS: 0>, 0, 0, 0, 0]
2022-10-28 13:30:12.516 DEBUG (MainThread) [zigpy_deconz.api] APS data confirm response for request with id 187: 00
2022-10-28 13:30:12.516 DEBUG (MainThread) [zigpy_deconz.api] Request id: 0xbb 'aps_data_confirm' for <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, status: 0x00
2022-10-28 13:30:13.497 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:13.497 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:13.497 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, <DataIndicationFlags.Always_Use_NWK_Source_Addr: 1>)
2022-10-28 13:30:13.499 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_indication[36, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, 1, 260, 61184, b'\t \x02\x00\x8e\t\x02\x00\x04\x00\x00\x02\n', 0, 175, 255, 196, 142, 246, 2, -49]
2022-10-28 13:30:13.499 DEBUG (MainThread) [zigpy_deconz.api] APS data indication response: [36, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, 1, 260, 61184, b'\t \x02\x00\x8e\t\x02\x00\x04\x00\x00\x02\n', 0, 175, 255, 196, 142, 246, 2, -49]
2022-10-28 13:30:13.499 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x5F29), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=None, profile_id=260, cluster_id=61184, data=Serialized[b'\t \x02\x00\x8e\t\x02\x00\x04\x00\x00\x02\n'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=255, rssi=-49)
2022-10-28 13:30:13.500 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Received ZCL frame: b'\t \x02\x00\x8e\t\x02\x00\x04\x00\x00\x02\n'
2022-10-28 13:30:13.500 DEBUG (MainThread) [zigpy.zcl] [0x5F29: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, *is_reply=True), tsn=32, command_id=2, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:13.500 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Decoded ZCL frame: MmwRadarManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=142, datapoints=[TuyaDatapointData(dp=9, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\n\x02\x00\x00', *payload=522))]))
2022-10-28 13:30:13.501 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Received command 0x02 (TSN 32): set_data_response(data=TuyaCommand(status=0, tsn=142, datapoints=[TuyaDatapointData(dp=9, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\n\x02\x00\x00', *payload=522))]))
2022-10-28 13:30:13.501 DEBUG (MainThread) [zigpy.zcl] [0x5F29: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, *is_reply=True), tsn=32, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:13.502 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.SUCCESS: 0>)
2022-10-28 13:30:13.502 DEBUG (MainThread) [zigpy_deconz.zigbee.application] Sending packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x5F29), dst_ep=1, source_route=None, extended_timeout=False, tsn=32, profile_id=260, cluster_id=61184, data=Serialized[b'\x18 \x0b\x02\x00'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2022-10-28 13:30:13.502 DEBUG (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, ep: 1, profile: 0x0104, cluster_id: 0xef00, data: b'092002008e090200040000020a'
2022-10-28 13:30:13.502 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 188, <DeconzSendDataFlags.NONE: 0>, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, 260, 61184, 1, b'\x18 \x0b\x02\x00', <DeconzTransmitOptions.USE_NWK_KEY_SECURITY: 2>, 0)
2022-10-28 13:30:13.506 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_request[2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 188]
2022-10-28 13:30:13.506 DEBUG (MainThread) [zigpy_deconz.api] APS data request response: [2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 188]
2022-10-28 13:30:13.515 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:13.515 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:13.515 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2022-10-28 13:30:13.516 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_confirm[12, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 188, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, 1, <TXStatus.SUCCESS: 0>, 0, 0, 0, 0]
2022-10-28 13:30:13.516 DEBUG (MainThread) [zigpy_deconz.api] APS data confirm response for request with id 188: 00
2022-10-28 13:30:13.516 DEBUG (MainThread) [zigpy_deconz.api] Request id: 0xbc 'aps_data_confirm' for <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, status: 0x00
2022-10-28 13:30:13.942 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0xB328](TS0601): Device seen - marking the device available and resetting counter
2022-10-28 13:30:13.942 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0xB328](TS0601): Update device availability - device available: True - new availability: True - changed: False
2022-10-28 13:30:14.493 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:14.494 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:14.495 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, <DataIndicationFlags.Always_Use_NWK_Source_Addr: 1>)
2022-10-28 13:30:14.497 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_indication[36, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, 1, 260, 61184, b'\t!\x02\x00\x8f\t\x02\x00\x04\x00\x00\x01\xfc', 0, 175, 255, 196, 142, 246, 2, -48]
2022-10-28 13:30:14.497 DEBUG (MainThread) [zigpy_deconz.api] APS data indication response: [36, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, 1, 260, 61184, b'\t!\x02\x00\x8f\t\x02\x00\x04\x00\x00\x01\xfc', 0, 175, 255, 196, 142, 246, 2, -48]
2022-10-28 13:30:14.497 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x5F29), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=None, profile_id=260, cluster_id=61184, data=Serialized[b'\t!\x02\x00\x8f\t\x02\x00\x04\x00\x00\x01\xfc'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=255, rssi=-48)
2022-10-28 13:30:14.498 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Received ZCL frame: b'\t!\x02\x00\x8f\t\x02\x00\x04\x00\x00\x01\xfc'
2022-10-28 13:30:14.498 DEBUG (MainThread) [zigpy.zcl] [0x5F29: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, *is_reply=True), tsn=33, command_id=2, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:14.498 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Decoded ZCL frame: MmwRadarManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=143, datapoints=[TuyaDatapointData(dp=9, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xfc\x01\x00\x00', *payload=508))]))
2022-10-28 13:30:14.499 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Received command 0x02 (TSN 33): set_data_response(data=TuyaCommand(status=0, tsn=143, datapoints=[TuyaDatapointData(dp=9, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xfc\x01\x00\x00', *payload=508))]))
2022-10-28 13:30:14.501 DEBUG (MainThread) [zigpy.zcl] [0x5F29: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, *is_reply=True), tsn=33, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:14.501 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.SUCCESS: 0>)
2022-10-28 13:30:14.501 DEBUG (MainThread) [zigpy_deconz.zigbee.application] Sending packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x5F29), dst_ep=1, source_route=None, extended_timeout=False, tsn=33, profile_id=260, cluster_id=61184, data=Serialized[b'\x18!\x0b\x02\x00'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2022-10-28 13:30:14.502 DEBUG (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, ep: 1, profile: 0x0104, cluster_id: 0xef00, data: b'092102008f09020004000001fc'
2022-10-28 13:30:14.502 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 189, <DeconzSendDataFlags.NONE: 0>, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, 260, 61184, 1, b'\x18!\x0b\x02\x00', <DeconzTransmitOptions.USE_NWK_KEY_SECURITY: 2>, 0)
2022-10-28 13:30:14.504 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_request[2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 189]
2022-10-28 13:30:14.504 DEBUG (MainThread) [zigpy_deconz.api] APS data request response: [2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 189]
2022-10-28 13:30:14.512 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:14.512 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:14.512 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2022-10-28 13:30:14.514 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_confirm[12, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 189, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, 1, <TXStatus.SUCCESS: 0>, 0, 0, 0, 0]
2022-10-28 13:30:14.514 DEBUG (MainThread) [zigpy_deconz.api] APS data confirm response for request with id 189: 00
2022-10-28 13:30:14.515 DEBUG (MainThread) [zigpy_deconz.api] Request id: 0xbd 'aps_data_confirm' for <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, status: 0x00
2022-10-28 13:30:14.603 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:14.603 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:14.603 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, <DataIndicationFlags.Always_Use_NWK_Source_Addr: 1>)
2022-10-28 13:30:14.605 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_indication[31, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x9dd8>, 1, 260, 2820, b'\x08\x14\n\x05\x05!\x04w', 0, 175, 255, 196, 142, 246, 2, -48]
2022-10-28 13:30:14.605 DEBUG (MainThread) [zigpy_deconz.api] APS data indication response: [31, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x9dd8>, 1, 260, 2820, b'\x08\x14\n\x05\x05!\x04w', 0, 175, 255, 196, 142, 246, 2, -48]
2022-10-28 13:30:14.605 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x9DD8), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=None, profile_id=260, cluster_id=2820, data=Serialized[b'\x08\x14\n\x05\x05!\x04w'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=255, rssi=-48)
2022-10-28 13:30:14.605 DEBUG (MainThread) [zigpy.zcl] [0x9DD8:1:0x0b04] Received ZCL frame: b'\x08\x14\n\x05\x05!\x04w'
2022-10-28 13:30:14.606 DEBUG (MainThread) [zigpy.zcl] [0x9DD8:1:0x0b04] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=0, direction=<Direction.Client_to_Server: 1>, disable_default_response=0, reserved=0, *is_cluster=False, *is_general=True, *is_reply=True), tsn=20, command_id=10, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:14.606 DEBUG (MainThread) [zigpy.zcl] [0x9DD8:1:0x0b04] Decoded ZCL frame: ElectricalMeasurement:Report_Attributes(attribute_reports=[Attribute(attrid=0x0505, value=TypeValue(type=uint16_t, value=30468))])
2022-10-28 13:30:14.606 DEBUG (MainThread) [zigpy.zcl] [0x9DD8:1:0x0b04] Received command 0x0A (TSN 20): Report_Attributes(attribute_reports=[Attribute(attrid=0x0505, value=TypeValue(type=uint16_t, value=30468))])
2022-10-28 13:30:14.607 DEBUG (MainThread) [zigpy.zcl] [0x9DD8:1:0x0b04] Attribute report received: rms_voltage=30468
2022-10-28 13:30:14.607 DEBUG (MainThread) [zigpy.zcl] [0x9DD8:1:0x0b04] 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, *is_reply=True), tsn=20, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:14.608 DEBUG (MainThread) [zigpy.zcl] [0x9DD8:1:0x0b04] Sending reply: Default_Response(command_id=10, status=<Status.SUCCESS: 0>)
2022-10-28 13:30:14.608 DEBUG (MainThread) [zigpy_deconz.zigbee.application] Sending packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x9DD8), dst_ep=1, source_route=None, extended_timeout=False, tsn=20, profile_id=260, cluster_id=2820, data=Serialized[b'\x18\x14\x0b\n\x00'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2022-10-28 13:30:14.608 DEBUG (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from <DeconzAddress address_mode=AddressMode.NWK address=0x9dd8>, ep: 1, profile: 0x0104, cluster_id: 0x0b04, data: b'08140a0505210477'
2022-10-28 13:30:14.608 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 190, <DeconzSendDataFlags.NONE: 0>, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x9dd8 endpoint=1>, 260, 2820, 1, b'\x18\x14\x0b\n\x00', <DeconzTransmitOptions.USE_NWK_KEY_SECURITY: 2>, 0)
2022-10-28 13:30:14.611 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_request[2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 190]
2022-10-28 13:30:14.611 DEBUG (MainThread) [zigpy_deconz.api] APS data request response: [2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 190]
2022-10-28 13:30:14.618 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:14.618 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:14.618 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2022-10-28 13:30:14.619 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_confirm[12, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 190, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x9dd8 endpoint=1>, 1, <TXStatus.SUCCESS: 0>, 0, 0, 0, 0]
2022-10-28 13:30:14.619 DEBUG (MainThread) [zigpy_deconz.api] APS data confirm response for request with id 190: 00
2022-10-28 13:30:14.619 DEBUG (MainThread) [zigpy_deconz.api] Request id: 0xbe 'aps_data_confirm' for <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x9dd8 endpoint=1>, status: 0x00
2022-10-28 13:30:15.300 WARNING (stream_worker) [libav.flv] DTS 0 < 32213 out of order
2022-10-28 13:30:15.494 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:15.495 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:15.495 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, <DataIndicationFlags.Always_Use_NWK_Source_Addr: 1>)
2022-10-28 13:30:15.497 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_indication[36, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, 1, 260, 61184, b'\t"\x02\x00\x90\t\x02\x00\x04\x00\x00\x02\x10', 0, 175, 255, 196, 142, 246, 2, -48]
2022-10-28 13:30:15.497 DEBUG (MainThread) [zigpy_deconz.api] APS data indication response: [36, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, 1, 260, 61184, b'\t"\x02\x00\x90\t\x02\x00\x04\x00\x00\x02\x10', 0, 175, 255, 196, 142, 246, 2, -48]
2022-10-28 13:30:15.498 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x5F29), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=None, profile_id=260, cluster_id=61184, data=Serialized[b'\t"\x02\x00\x90\t\x02\x00\x04\x00\x00\x02\x10'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=255, rssi=-48)
2022-10-28 13:30:15.498 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Received ZCL frame: b'\t"\x02\x00\x90\t\x02\x00\x04\x00\x00\x02\x10'
2022-10-28 13:30:15.498 DEBUG (MainThread) [zigpy.zcl] [0x5F29: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, *is_reply=True), tsn=34, command_id=2, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:15.499 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Decoded ZCL frame: MmwRadarManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=144, datapoints=[TuyaDatapointData(dp=9, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\x10\x02\x00\x00', *payload=528))]))
2022-10-28 13:30:15.499 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Received command 0x02 (TSN 34): set_data_response(data=TuyaCommand(status=0, tsn=144, datapoints=[TuyaDatapointData(dp=9, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\x10\x02\x00\x00', *payload=528))]))
2022-10-28 13:30:15.500 DEBUG (MainThread) [zigpy.zcl] [0x5F29: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, *is_reply=True), tsn=34, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:15.500 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.SUCCESS: 0>)
2022-10-28 13:30:15.500 DEBUG (MainThread) [zigpy_deconz.zigbee.application] Sending packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x5F29), dst_ep=1, source_route=None, extended_timeout=False, tsn=34, profile_id=260, cluster_id=61184, data=Serialized[b'\x18"\x0b\x02\x00'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2022-10-28 13:30:15.500 DEBUG (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, ep: 1, profile: 0x0104, cluster_id: 0xef00, data: b'09220200900902000400000210'
2022-10-28 13:30:15.501 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 191, <DeconzSendDataFlags.NONE: 0>, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, 260, 61184, 1, b'\x18"\x0b\x02\x00', <DeconzTransmitOptions.USE_NWK_KEY_SECURITY: 2>, 0)
2022-10-28 13:30:15.504 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_request[2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 191]
2022-10-28 13:30:15.504 DEBUG (MainThread) [zigpy_deconz.api] APS data request response: [2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 191]
2022-10-28 13:30:15.512 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:15.512 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:15.513 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2022-10-28 13:30:15.514 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_confirm[12, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 191, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, 1, <TXStatus.SUCCESS: 0>, 0, 0, 0, 0]
2022-10-28 13:30:15.515 DEBUG (MainThread) [zigpy_deconz.api] APS data confirm response for request with id 191: 00
2022-10-28 13:30:15.516 DEBUG (MainThread) [zigpy_deconz.api] Request id: 0xbf 'aps_data_confirm' for <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, status: 0x00
2022-10-28 13:30:15.886 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0x545E](TRADFRI remote control): Device seen - marking the device available and resetting counter
2022-10-28 13:30:15.887 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0x545E](TRADFRI remote control): Update device availability - device available: True - new availability: True - changed: False
2022-10-28 13:30:15.898 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0xC2A8](SZ-ESW01-AU): Device seen - marking the device available and resetting counter
2022-10-28 13:30:15.898 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0xC2A8](SZ-ESW01-AU): Update device availability - device available: True - new availability: True - changed: False
2022-10-28 13:30:15.928 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0x09F1](lumi.sensor_switch): Device seen - marking the device available and resetting counter
2022-10-28 13:30:15.929 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0x09F1](lumi.sensor_switch): Update device availability - device available: True - new availability: True - changed: False
2022-10-28 13:30:15.946 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0x3D9B](Remote Control N2): Device seen - marking the device available and resetting counter
2022-10-28 13:30:15.946 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0x3D9B](Remote Control N2): Update device availability - device available: True - new availability: True - changed: False
2022-10-28 13:30:16.478 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:16.478 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:16.480 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, <DataIndicationFlags.Always_Use_NWK_Source_Addr: 1>)
2022-10-28 13:30:16.484 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_indication[31, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x77c0>, 1, 260, 2820, b'\x08O\n\x05\x05!\x17w', 0, 175, 255, 196, 142, 246, 2, -49]
2022-10-28 13:30:16.484 DEBUG (MainThread) [zigpy_deconz.api] APS data indication response: [31, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x77c0>, 1, 260, 2820, b'\x08O\n\x05\x05!\x17w', 0, 175, 255, 196, 142, 246, 2, -49]
2022-10-28 13:30:16.484 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x77C0), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=None, profile_id=260, cluster_id=2820, data=Serialized[b'\x08O\n\x05\x05!\x17w'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=255, rssi=-49)
2022-10-28 13:30:16.485 DEBUG (MainThread) [zigpy.zcl] [0x77C0:1:0x0b04] Received ZCL frame: b'\x08O\n\x05\x05!\x17w'
2022-10-28 13:30:16.491 DEBUG (MainThread) [zigpy.zcl] [0x77C0:1:0x0b04] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=0, direction=<Direction.Client_to_Server: 1>, disable_default_response=0, reserved=0, *is_cluster=False, *is_general=True, *is_reply=True), tsn=79, command_id=10, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:16.492 DEBUG (MainThread) [zigpy.zcl] [0x77C0:1:0x0b04] Decoded ZCL frame: ElectricalMeasurement:Report_Attributes(attribute_reports=[Attribute(attrid=0x0505, value=TypeValue(type=uint16_t, value=30487))])
2022-10-28 13:30:16.494 DEBUG (MainThread) [zigpy.zcl] [0x77C0:1:0x0b04] Received command 0x0A (TSN 79): Report_Attributes(attribute_reports=[Attribute(attrid=0x0505, value=TypeValue(type=uint16_t, value=30487))])
2022-10-28 13:30:16.494 DEBUG (MainThread) [zigpy.zcl] [0x77C0:1:0x0b04] Attribute report received: rms_voltage=30487
2022-10-28 13:30:16.500 DEBUG (MainThread) [zigpy.zcl] [0x77C0:1:0x0b04] 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, *is_reply=True), tsn=79, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:16.500 DEBUG (MainThread) [zigpy.zcl] [0x77C0:1:0x0b04] Sending reply: Default_Response(command_id=10, status=<Status.SUCCESS: 0>)
2022-10-28 13:30:16.500 DEBUG (MainThread) [zigpy_deconz.zigbee.application] Sending packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x77C0), dst_ep=1, source_route=None, extended_timeout=False, tsn=79, profile_id=260, cluster_id=2820, data=Serialized[b'\x18O\x0b\n\x00'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2022-10-28 13:30:16.501 DEBUG (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from <DeconzAddress address_mode=AddressMode.NWK address=0x77c0>, ep: 1, profile: 0x0104, cluster_id: 0x0b04, data: b'084f0a0505211777'
2022-10-28 13:30:16.501 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 192, <DeconzSendDataFlags.NONE: 0>, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x77c0 endpoint=1>, 260, 2820, 1, b'\x18O\x0b\n\x00', <DeconzTransmitOptions.USE_NWK_KEY_SECURITY: 2>, 0)
2022-10-28 13:30:16.505 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:16.505 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 170>, 0]
2022-10-28 13:30:16.505 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_request[2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 42>, 192]
2022-10-28 13:30:16.505 DEBUG (MainThread) [zigpy_deconz.api] APS data request response: [2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|2: 42>, 192]
2022-10-28 13:30:16.509 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, <DataIndicationFlags.Always_Use_NWK_Source_Addr: 1>)
2022-10-28 13:30:16.512 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|APSDE_DATA_CONFIRM|2: 174>, 0]
2022-10-28 13:30:16.512 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_INDICATION|APSDE_DATA_CONFIRM|2: 174>, 0]
2022-10-28 13:30:16.512 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_indication[36, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 38>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, 1, 260, 61184, b'\t#\x02\x00\x91\t\x02\x00\x04\x00\x00\x02\x16', 0, 175, 255, 196, 142, 246, 2, -49]
2022-10-28 13:30:16.513 DEBUG (MainThread) [zigpy_deconz.api] APS data indication response: [36, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 38>, <DeconzAddress address_mode=AddressMode.NWK address=0x0000>, 1, <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, 1, 260, 61184, b'\t#\x02\x00\x91\t\x02\x00\x04\x00\x00\x02\x16', 0, 175, 255, 196, 142, 246, 2, -49]
2022-10-28 13:30:16.513 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x5F29), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=None, profile_id=260, cluster_id=61184, data=Serialized[b'\t#\x02\x00\x91\t\x02\x00\x04\x00\x00\x02\x16'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=255, rssi=-49)
2022-10-28 13:30:16.513 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Received ZCL frame: b'\t#\x02\x00\x91\t\x02\x00\x04\x00\x00\x02\x16'
2022-10-28 13:30:16.514 DEBUG (MainThread) [zigpy.zcl] [0x5F29: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, *is_reply=True), tsn=35, command_id=2, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:16.514 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Decoded ZCL frame: MmwRadarManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=145, datapoints=[TuyaDatapointData(dp=9, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\x16\x02\x00\x00', *payload=534))]))
2022-10-28 13:30:16.516 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Received command 0x02 (TSN 35): set_data_response(data=TuyaCommand(status=0, tsn=145, datapoints=[TuyaDatapointData(dp=9, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\x16\x02\x00\x00', *payload=534))]))
2022-10-28 13:30:16.520 DEBUG (MainThread) [zigpy.zcl] [0x5F29: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, *is_reply=True), tsn=35, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-10-28 13:30:16.522 DEBUG (MainThread) [zigpy.zcl] [0x5F29:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.SUCCESS: 0>)
2022-10-28 13:30:16.523 DEBUG (MainThread) [zigpy_deconz.zigbee.application] Sending packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x5F29), dst_ep=1, source_route=None, extended_timeout=False, tsn=35, profile_id=260, cluster_id=61184, data=Serialized[b'\x18#\x0b\x02\x00'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2022-10-28 13:30:16.525 DEBUG (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from <DeconzAddress address_mode=AddressMode.NWK address=0x5f29>, ep: 1, profile: 0x0104, cluster_id: 0xef00, data: b'09230200910902000400000216'
2022-10-28 13:30:16.525 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2022-10-28 13:30:16.526 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_confirm[12, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 192, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x77c0 endpoint=1>, 1, <TXStatus.SUCCESS: 0>, 0, 0, 0, 0]
2022-10-28 13:30:16.526 DEBUG (MainThread) [zigpy_deconz.api] APS data confirm response for request with id 192: 00
2022-10-28 13:30:16.527 DEBUG (MainThread) [zigpy_deconz.api] Request id: 0xc0 'aps_data_confirm' for <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x77c0 endpoint=1>, status: 0x00
2022-10-28 13:30:16.527 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 193, <DeconzSendDataFlags.NONE: 0>, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, 260, 61184, 1, b'\x18#\x0b\x02\x00', <DeconzTransmitOptions.USE_NWK_KEY_SECURITY: 2>, 0)
2022-10-28 13:30:16.529 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_request[2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 193]
2022-10-28 13:30:16.530 DEBUG (MainThread) [zigpy_deconz.api] APS data request response: [2, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 193]
2022-10-28 13:30:16.604 DEBUG (MainThread) [zigpy_deconz.api] Received command device_state_changed[<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:16.604 DEBUG (MainThread) [zigpy_deconz.api] Device state changed response: [<DeviceState.128|APSDE_DATA_REQUEST_SLOTS_AVAILABLE|APSDE_DATA_CONFIRM|2: 166>, 0]
2022-10-28 13:30:16.611 DEBUG (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2022-10-28 13:30:16.620 DEBUG (MainThread) [zigpy_deconz.api] Received command aps_data_confirm[12, <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE|2: 34>, 193, <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, 1, <TXStatus.SUCCESS: 0>, 0, 0, 0, 0]
2022-10-28 13:30:16.620 DEBUG (MainThread) [zigpy_deconz.api] APS data confirm response for request with id 193: 00
2022-10-28 13:30:16.620 DEBUG (MainThread) [zigpy_deconz.api] Request id: 0xc1 'aps_data_confirm' for <DeconzAddressEndpoint address_mode=AddressMode.NWK address=0x5f29 endpoint=1>, status: 0x00
PlusPlus-ua commented 1 year ago

Thank you. How would I add this to my HA setup? When I first got these sensors I added a custom quirk called ts0601_motion.py in order to get a working sensor with just the basic two entities. Would I add your code as a new file?

Just remove ts0601_motion.py, since it overwrites file from zhaquirks package, and create new file ts0601_radar.py with content of my code.

javicalle commented 1 year ago

I also has problem with Illuminance, I not sure in conversation formula, but it may be a defect of mine sensor.

The usual conversion for tuya it seems to be this: https://github.com/zigpy/zha-device-handlers/blob/249ec6d01bfdb0938486bbf27b9b2e6615ba5288/zhaquirks/tuya/ts0601_motion.py#L191-L195

smittong commented 1 year ago

Hello @PlusPlus-ua great bit of code. I have it working well. Only issue I've noticed is no Illuminance sensor value is available? (This isn't an issue for me as I'm using this currently as a security sensor and will be getting rid of my ugly PIR sensors). Is it possible to remove the word "Number" from each of the fields just to make it look more tidy?

My sensor output:

image

Thank you.

aquemy commented 1 year ago

@smittong I have also tested successfully the quirk and I have the Illuminance value (see below). However, to have my model working I had to add the "models_info" to the signature, otherwise the quirk was not loaded. Not sure is this is the problem but in case it is, my TuyaMmwRadarOccupancy class:

Don't forget to add your model (from your screen it looks like _TZE200_ikvncluo:

class TuyaMmwRadarOccupancy(CustomDevice):
    """Millimeter wave occupancy sensor."""

    signature = {
        #  endpoint=1, profile=260, device_type=81, device_version=1,
        #  input_clusters=[0, 4, 5, 61184], output_clusters=[25, 10]
        "models_info": [
            ("_TZE200_ar0slwnd", "TS0601"),
            ("_TZE200_sfiy5tfs", "TS0601"),
            ("_TZE200_mrf6vtua", "TS0601"),
            ("_TZE200_ztc6ggyl", "TS0601"),
        ],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaNewManufCluster.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaMmwRadarCluster,
                    TuyaIlluminanceMeasurement,
                    TuyaOccupancySensing,
                    TuyaMmwRadarTargetDistance,
                    TuyaMmwRadarSensitivity,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarMinRange,
                ],
                OUTPUT_CLUSTERS: [],
            },
            3: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarMaxRange,
                ],
                OUTPUT_CLUSTERS: [],
            },
            4: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarDetectionDelay,
                ],
                OUTPUT_CLUSTERS: [],
            },
            5: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarFadingTime,
                ],
                OUTPUT_CLUSTERS: [],
            },
        }
    }

image

PlusPlus-ua commented 1 year ago

Only issue I've noticed is no Illuminance sensor value is available?

Have no idea why, I've the same device and Illuminance is available.

Is it possible to remove the word "Number" from each of the fields just to make it look more tidy?

As far as I know - no, it is added somewhere in deep of ZHA integration.

Don't forget to add your model (from your screen it looks like _TZE200_ikvncluo:

Usually it's not needed, if model name and signature of endpoints matches, quirk should be loaded.

aquemy commented 1 year ago

Usually it's not needed, if model name and signature of endpoints matches, quirk should be loaded.

Somehow it was the only way I managed to get the quirk loaded on my side.

javicalle commented 1 year ago

Don't forget to add your model (from your screen it looks like _TZE200_ikvncluo:

Usually it's not needed, if model name and signature of endpoints matches, quirk should be loaded.

Well, you can try to match the model and signature like this:

class TuyaMmwRadarOccupancy(CustomDevice):
    """Millimeter wave occupancy sensor."""

    signature = {
        MODEL: "TS0601",
        .../...

Or match the model, manufacturer and signature like this:

class TuyaMmwRadarOccupancy(CustomDevice):
    """Millimeter wave occupancy sensor."""

    signature = {
        "models_info": [
            ("_TZE200_ar0slwnd", "TS0601"),
            ("_TZE200_sfiy5tfs", "TS0601"),
            ("_TZE200_mrf6vtua", "TS0601"),
            ("_TZE200_ztc6ggyl", "TS0601"),
        ],
        .../...

But IMHO not defining the manufacturer seems quite risky to me since many TS0601 devices can be adjusted to that signature (I have found more of 10 of them):

        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaNewManufCluster.cluster_id,  # <-- Tuya manufacturer cluster
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
        },

So I would suggest (at least for the TS0601 devices) to adjust the quirk for a model and manufacturer.

sparkydave1981 commented 1 year ago

Is it possible to remove the word "Number" from each of the fields just to make it look more tidy?

You can do this in the device config by manually overriding the names for each entity.

image image

smittong commented 1 year ago

Hello @sparkydave1981 thanks for that tip on the renaming, brilliant.

wormiedk commented 1 year ago

Any update on this?

Yes, I've updated version. It looks like TuyaAttributesCluster from zhaquirks.tuya.mcu doesn't support float values, so I've changed all settings to int. So, delays measured now in milisecons and ranges in centimeters. I'ts a bit ugly but works. I also has problem with Illuminance, I not sure in conversation formula, but it may be a defect of mine sensor.

Here is my current code: @PlusPlus-ua Your quirk works excellently however for me the illuminance value is updated VERY frequently at least every 10 seconds but sometimes much more often. Is there a way to limit this?

blair287 commented 1 year ago

@smittong I have also tested successfully the quirk and I have the Illuminance value (see below). However, to have my model working I had to add the "models_info" to the signature, otherwise the quirk was not loaded. Not sure is this is the problem but in case it is, my TuyaMmwRadarOccupancy class:

Don't forget to add your model (from your screen it looks like _TZE200_ikvncluo:

class TuyaMmwRadarOccupancy(CustomDevice):
    """Millimeter wave occupancy sensor."""

    signature = {
        #  endpoint=1, profile=260, device_type=81, device_version=1,
        #  input_clusters=[0, 4, 5, 61184], output_clusters=[25, 10]
        "models_info": [
            ("_TZE200_ar0slwnd", "TS0601"),
            ("_TZE200_sfiy5tfs", "TS0601"),
            ("_TZE200_mrf6vtua", "TS0601"),
            ("_TZE200_ztc6ggyl", "TS0601"),
        ],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaNewManufCluster.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaMmwRadarCluster,
                    TuyaIlluminanceMeasurement,
                    TuyaOccupancySensing,
                    TuyaMmwRadarTargetDistance,
                    TuyaMmwRadarSensitivity,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarMinRange,
                ],
                OUTPUT_CLUSTERS: [],
            },
            3: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarMaxRange,
                ],
                OUTPUT_CLUSTERS: [],
            },
            4: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarDetectionDelay,
                ],
                OUTPUT_CLUSTERS: [],
            },
            5: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarFadingTime,
                ],
                OUTPUT_CLUSTERS: [],
            },
        }
    }

image

This just generates an error saying custom device not defined and prevents zha from loading.

smittong commented 1 year ago

Hello @blair287. I did add the models info about a month ago but didn't seem to make any difference, but I noted a couple of days ago the illuminance sensor appeared without me doing anything.

blair287 commented 1 year ago

Hello @blair287. I did add the models info about a month ago but didn't seem to make any difference, but I noted a couple of days ago the illuminance sensor appeared without me doing anything.

Ah yes it did appear after a while.

Hopefully this can be supported inside ZHA soon by default

Would be great if the times were in seconds and not ms

KevinVanthuyne commented 1 year ago

Any update on this?

Yes, I've updated version. It looks like TuyaAttributesCluster from zhaquirks.tuya.mcu doesn't support float values, so I've changed all settings to int. So, delays measured now in milisecons and ranges in centimeters. I'ts a bit ugly but works. I also has problem with Illuminance, I not sure in conversation formula, but it may be a defect of mine sensor.

Here is my current code:

"""Tuya mmw radar occupancy sensor."""

import math
from typing import Dict, 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 (
    AnalogInput,
    AnalogOutput,
    Basic,
    GreenPowerProxy,
    Groups,
    Identify,
    Ota,
    Scenes,
    Time,
)
from zigpy.zcl.clusters.measurement import (
    IlluminanceMeasurement,
    OccupancySensing
)
from zigpy.zcl.clusters.security import IasZone

from zhaquirks import Bus, LocalDataCluster, MotionOnEvent
from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODEL,
    MOTION_EVENT,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)
from zhaquirks.tuya import (
    NoManufacturerCluster,
    TuyaLocalCluster,
    TuyaNewManufCluster,
)
from zhaquirks.tuya.mcu import (
    TuyaDPType,
    DPToAttributeMapping,
    TuyaAttributesCluster,
    TuyaMCUCluster,
)

class TuyaMmwRadarSelfTest(t.enum8):
    """Mmw radar self test values."""
    TESTING = 0
    TEST_SUCCESS = 1
    TEST_FAILURE = 2
    OTHER = 3
    COMM_FAULT = 4
    RADAR_FAULT = 5

class TuyaOccupancySensing(OccupancySensing, TuyaLocalCluster):
    """Tuya local OccupancySensing cluster."""

class TuyaIlluminanceMeasurement(IlluminanceMeasurement, TuyaLocalCluster):
    """Tuya local IlluminanceMeasurement cluster."""

class TuyaMmwRadarSensitivity(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for sensitivity."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Sensitivity"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 1)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 9)
        self._update_attribute(self.attributes_by_name["resolution"].id, 1)

class TuyaMmwRadarMinRange(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for min range."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Min range"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 950)
        self._update_attribute(self.attributes_by_name["resolution"].id, 10)
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 118
        )  # 31: meters

class TuyaMmwRadarMaxRange(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for max range."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Max range"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 950)
        self._update_attribute(self.attributes_by_name["resolution"].id, 10)
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 118
        )  # 31: meters

class TuyaMmwRadarDetectionDelay(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for detection delay."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Detection delay"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 100)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 20000)
        self._update_attribute(self.attributes_by_name["resolution"].id, 100)
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 159
        )  # 73: seconds

class TuyaMmwRadarFadingTime(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for fading time."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Fading time"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 1000)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 200000)
        self._update_attribute(self.attributes_by_name["resolution"].id, 1000)
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 159
        )  # 73: seconds

class TuyaMmwRadarTargetDistance(TuyaAttributesCluster, AnalogInput):
    """AnalogInput cluster for target distance."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Target distance"
        )
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 31
        )  # 31: meters

class TuyaMmwRadarCluster(NoManufacturerCluster, TuyaMCUCluster):
    """Mmw radar cluster."""
    attributes = TuyaMCUCluster.attributes.copy()
    attributes.update(
        {
            # ramdom attribute IDs
            0xEF01: ("occupancy", t.uint32_t, True),
            0xEF02: ("sensitivity", t.uint32_t, True),
            0xEF03: ("min_range", t.uint32_t, True),
            0xEF04: ("max_range", t.uint32_t, True),
            0xEF06: ("self_test", TuyaMmwRadarSelfTest, True),
            0xEF09: ("target_distance", t.uint32_t, True),
            0xEF65: ("detection_delay", t.uint32_t, True),
            0xEF66: ("fading_time", t.uint32_t, True),
            0xEF67: ("cli", t.CharacterString, True),
            0xEF68: ("illuminance", t.uint32_t, True),
        }
    )

    dp_to_attribute: Dict[int, DPToAttributeMapping] = {
        1: DPToAttributeMapping(
            TuyaOccupancySensing.ep_attribute,
            "occupancy",
            dp_type=TuyaDPType.BOOL,
        ),
        2: DPToAttributeMapping(
            TuyaMmwRadarSensitivity.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
        ),
        3: DPToAttributeMapping(
            TuyaMmwRadarMinRange.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
            endpoint_id=2,
            #converter=lambda x: x / 100,
            #dp_converter=lambda x: x * 100,
        ),
        4: DPToAttributeMapping(
            TuyaMmwRadarMaxRange.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
            endpoint_id=3,
            #converter=lambda x: x / 100,
            #dp_converter=lambda x: x * 100,
        ),
        6: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "self_test",
            dp_type=TuyaDPType.ENUM,
        ),
        9: DPToAttributeMapping(
            TuyaMmwRadarTargetDistance.ep_attribute,
            "present_value",
            #converter=lambda x: x / 100,
            dp_type=TuyaDPType.VALUE,
        ),
        101: DPToAttributeMapping(
            TuyaMmwRadarDetectionDelay.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: x * 100,
            dp_converter=lambda x: x // 100,
            endpoint_id=4,
        ),
        102: DPToAttributeMapping(
            TuyaMmwRadarFadingTime.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: x * 100,
            dp_converter=lambda x: x // 100,
            endpoint_id=5,
        ),
        103: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "cli",
            dp_type=TuyaDPType.STRING,
        ),
        104: DPToAttributeMapping(
            TuyaIlluminanceMeasurement.ep_attribute,
            "measured_value",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: math.log10(x) * 10000 + 1,
        ),
    }

    data_point_handlers = {
        1: "_dp_2_attr_update",
        2: "_dp_2_attr_update",
        3: "_dp_2_attr_update",
        4: "_dp_2_attr_update",
        6: "_dp_2_attr_update",
        9: "_dp_2_attr_update",
        101: "_dp_2_attr_update",
        102: "_dp_2_attr_update",
        103: "_dp_2_attr_update",
        104: "_dp_2_attr_update",
    }

class TuyaMmwRadarOccupancy(CustomDevice):
    """Millimeter wave occupancy sensor."""

    signature = {
        MODEL: "TS0601",
        ENDPOINTS: {
            # <SimpleDescriptor endpoint=1 profile=260 device_type=81
            # device_version=1
            # input_clusters=[0, 4, 5, 61184]
            # output_clusters=[10, 25]>
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaMmwRadarCluster.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaMmwRadarCluster,
                    TuyaIlluminanceMeasurement,
                    TuyaOccupancySensing,
                    TuyaMmwRadarTargetDistance,
                    TuyaMmwRadarSensitivity,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarMinRange,
                ],
                OUTPUT_CLUSTERS: [],
            },
            3: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarMaxRange,
                ],
                OUTPUT_CLUSTERS: [],
            },
            4: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarDetectionDelay,
                ],
                OUTPUT_CLUSTERS: [],
            },
            5: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarFadingTime,
                ],
                OUTPUT_CLUSTERS: [],
            },
        }
    }

This quirk works for me in combination with adding the manufacturer info as mentioned by @aquemy.

Is there a reason why this quirk has not been merged to the official quirks yet?

aquemy commented 1 year ago

@KevinVanthuyne I am actually now facing an issue with this quirk: https://github.com/zigpy/zha-device-handlers/issues/1863#issuecomment-1347885668

Can you confirm that the configuration via the sliders works and is not reset automatically? Can you see the service called in the logbook? Not only for the sensitivity?

I am having a hard time understanding if the issue is my own environment or the quirk itself.

KevinVanthuyne commented 1 year ago

The sliders seem to keep their position and also actually influence the settings like maximum distance. However only sensitivity seems to generate logbook events, all other settings do not.

aquemy commented 1 year ago

Thanks for the confirmation @KevinVanthuyne.

After updating to the the latest version of HA, removing all quirks and devices, restarting my hardware and repairing every sensor, everything started to work again. This is weird though.

blair287 commented 1 year ago

@PlusPlus-ua My sensor is working but all the configuration sliders show unavailable now so cannot be adjusted which is weird. I tried removing and adding again using your quirk as I was before but now the configuration sliders have just disappeared completely.

Ignore me it seems that my HA stopped using your quirk in the last update and defaulted to the tuya mmwave quick I edited your quirk with tje device info as someone suggested above and now its all back sorry if I bothered you.

jimmyeao commented 1 year ago

I haven't been able to get this code working, seems I cant have a custom quirk for a device that is already "integrated" into ZHA. using a TS0601 identified as _TZE204_ztc6ggyl All I get is illuminance and occupancy, no other settings. Its picking up Quirk: zhaquirks.tuya.ts0601_motion.MmwRadarMotion instead of ts0601_radar.py

blair287 commented 1 year ago

I haven't been able to get this code working, seems I cant have a custom quirk for a device that is already "integrated" into ZHA. using a TS0601 identified as _TZE204_ztc6ggyl All I get is illuminance and occupancy, no other settings. Its picking up Quirk: zhaquirks.tuya.ts0601_motion.MmwRadarMotion instead of ts0601_radar.py

Because you need to add that device signature to it. I have same model use this, also remember to delete the pycache in the custom quirks folder then restart HA.

"""Tuya mmw radar occupancy sensor."""

import math
from typing import Dict, 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 (
    AnalogInput,
    AnalogOutput,
    Basic,
    GreenPowerProxy,
    Groups,
    Identify,
    Ota,
    Scenes,
    Time,
)
from zigpy.zcl.clusters.measurement import (
    IlluminanceMeasurement,
    OccupancySensing
)
from zigpy.zcl.clusters.security import IasZone

from zhaquirks import Bus, LocalDataCluster, MotionOnEvent
from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODEL,
    MOTION_EVENT,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)
from zhaquirks.tuya import (
    NoManufacturerCluster,
    TuyaLocalCluster,
    TuyaNewManufCluster,
)
from zhaquirks.tuya.mcu import (
    TuyaDPType,
    DPToAttributeMapping,
    TuyaAttributesCluster,
    TuyaMCUCluster,
)

class TuyaMmwRadarSelfTest(t.enum8):
    """Mmw radar self test values."""
    TESTING = 0
    TEST_SUCCESS = 1
    TEST_FAILURE = 2
    OTHER = 3
    COMM_FAULT = 4
    RADAR_FAULT = 5

class TuyaOccupancySensing(OccupancySensing, TuyaLocalCluster):
    """Tuya local OccupancySensing cluster."""

class TuyaIlluminanceMeasurement(IlluminanceMeasurement, TuyaLocalCluster):
    """Tuya local IlluminanceMeasurement cluster."""

class TuyaMmwRadarSensitivity(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for sensitivity."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Sensitivity"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 1)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 9)
        self._update_attribute(self.attributes_by_name["resolution"].id, 1)

class TuyaMmwRadarMinRange(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for min range."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Min range"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 950)
        self._update_attribute(self.attributes_by_name["resolution"].id, 10)
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 118
        )  # 31: meters

class TuyaMmwRadarMaxRange(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for max range."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Max range"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 950)
        self._update_attribute(self.attributes_by_name["resolution"].id, 10)
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 118
        )  # 31: meters

class TuyaMmwRadarDetectionDelay(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for detection delay."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Detection delay"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 100)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 20000)
        self._update_attribute(self.attributes_by_name["resolution"].id, 100)
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 159
        )  # 73: seconds

class TuyaMmwRadarFadingTime(TuyaAttributesCluster, AnalogOutput):
    """AnalogOutput cluster for fading time."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Fading time"
        )
        self._update_attribute(self.attributes_by_name["min_present_value"].id, 1000)
        self._update_attribute(self.attributes_by_name["max_present_value"].id, 200000)
        self._update_attribute(self.attributes_by_name["resolution"].id, 1000)
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 159
        )  # 73: seconds

class TuyaMmwRadarTargetDistance(TuyaAttributesCluster, AnalogInput):
    """AnalogInput cluster for target distance."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self._update_attribute(
            self.attributes_by_name["description"].id, "Target distance"
        )
        self._update_attribute(
            self.attributes_by_name["engineering_units"].id, 31
        )  # 31: meters

class TuyaMmwRadarCluster(NoManufacturerCluster, TuyaMCUCluster):
    """Mmw radar cluster."""
    attributes = TuyaMCUCluster.attributes.copy()
    attributes.update(
        {
            # ramdom attribute IDs
            0xEF01: ("occupancy", t.uint32_t, True),
            0xEF02: ("sensitivity", t.uint32_t, True),
            0xEF03: ("min_range", t.uint32_t, True),
            0xEF04: ("max_range", t.uint32_t, True),
            0xEF06: ("self_test", TuyaMmwRadarSelfTest, True),
            0xEF09: ("target_distance", t.uint32_t, True),
            0xEF65: ("detection_delay", t.uint32_t, True),
            0xEF66: ("fading_time", t.uint32_t, True),
            0xEF67: ("cli", t.CharacterString, True),
            0xEF68: ("illuminance", t.uint32_t, True),
        }
    )

    dp_to_attribute: Dict[int, DPToAttributeMapping] = {
        1: DPToAttributeMapping(
            TuyaOccupancySensing.ep_attribute,
            "occupancy",
            dp_type=TuyaDPType.BOOL,
        ),
        2: DPToAttributeMapping(
            TuyaMmwRadarSensitivity.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
        ),
        3: DPToAttributeMapping(
            TuyaMmwRadarMinRange.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
            endpoint_id=2,
            #converter=lambda x: x / 100,
            #dp_converter=lambda x: x * 100,
        ),
        4: DPToAttributeMapping(
            TuyaMmwRadarMaxRange.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
            endpoint_id=3,
            #converter=lambda x: x / 100,
            #dp_converter=lambda x: x * 100,
        ),
        6: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "self_test",
            dp_type=TuyaDPType.ENUM,
        ),
        9: DPToAttributeMapping(
            TuyaMmwRadarTargetDistance.ep_attribute,
            "present_value",
            #converter=lambda x: x / 100,
            dp_type=TuyaDPType.VALUE,
        ),
        101: DPToAttributeMapping(
            TuyaMmwRadarDetectionDelay.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: x * 100,
            dp_converter=lambda x: x // 100,
            endpoint_id=4,
        ),
        102: DPToAttributeMapping(
            TuyaMmwRadarFadingTime.ep_attribute,
            "present_value",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: x * 100,
            dp_converter=lambda x: x // 100,
            endpoint_id=5,
        ),
        103: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "cli",
            dp_type=TuyaDPType.STRING,
        ),
        104: DPToAttributeMapping(
            TuyaIlluminanceMeasurement.ep_attribute,
            "measured_value",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: math.log10(x) * 10000 + 1,
        ),
    }

    data_point_handlers = {
        1: "_dp_2_attr_update",
        2: "_dp_2_attr_update",
        3: "_dp_2_attr_update",
        4: "_dp_2_attr_update",
        6: "_dp_2_attr_update",
        9: "_dp_2_attr_update",
        101: "_dp_2_attr_update",
        102: "_dp_2_attr_update",
        103: "_dp_2_attr_update",
        104: "_dp_2_attr_update",
    }

class TuyaMmwRadarOccupancy(CustomDevice):
    """Millimeter wave occupancy sensor."""

    signature = {
        #  endpoint=1, profile=260, device_type=81, device_version=1,
        #  input_clusters=[0, 4, 5, 61184], output_clusters=[25, 10]
        "models_info": [
            ("_TZE200_ar0slwnd", "TS0601"),
            ("_TZE200_sfiy5tfs", "TS0601"),
            ("_TZE200_mrf6vtua", "TS0601"),
            ("_TZE200_ztc6ggyl", "TS0601"),
            ("_TZE204_ztc6ggyl", "TS0601"),
        ],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaNewManufCluster.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaMmwRadarCluster,
                    TuyaIlluminanceMeasurement,
                    TuyaOccupancySensing,
                    TuyaMmwRadarTargetDistance,
                    TuyaMmwRadarSensitivity,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarMinRange,
                ],
                OUTPUT_CLUSTERS: [],
            },
            3: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarMaxRange,
                ],
                OUTPUT_CLUSTERS: [],
            },
            4: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarDetectionDelay,
                ],
                OUTPUT_CLUSTERS: [],
            },
            5: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
                INPUT_CLUSTERS: [
                    TuyaMmwRadarFadingTime,
                ],
                OUTPUT_CLUSTERS: [],
            },
        }
    }
jimmyeao commented 1 year ago

That did the trick, thank you!

acseven commented 1 year ago

Because you need to add that device signature to it. I have same model use this, also remember to delete the pycache in the custom quirks folder then restart HA.

I've added the quirk code mentioned here to a specific file:

Captura de ecrã 2023-02-02, às 23 12 20

As far as I can tell the file is loaded fine (I made sure to delete that folder's pycache folder as well when present before restarting HA), and I get this device info and entities:

Captura de ecrã 2023-02-02, às 23 10 27

Although it is mostly working, there are some missing entities; when comparing to this Zigbee2MQTT listing, these aren't available, being the first one kind of important to create some automations:

Captura de ecrã 2023-02-02, às 23 23 27

Beside this, and as visible in the screenshot above, the illuminance sensor doesn't return a correct measurement. Regardless of the light intensity in the room the measured value is 2 lx.

Can these be fixed?

Additional screenshots:

Captura de ecrã 2023-02-02, às 23 24 35
CobraDunn commented 1 year ago

Quirk works great. with _TZE200_holel4dk for the Moes unit I have. Thanks to all for the work on this.