Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

_TZE200_3towulqd TS0601 Tuya Motion Sensor with illuminance sensor #1599

Open
itsolon opened this issue Jun 3, 2022 · 97 comments · May be fixed by #2450
Open

_TZE200_3towulqd TS0601 Tuya Motion Sensor with illuminance sensor #1599

itsolon opened this issue Jun 3, 2022 · 97 comments · May be fixed by #2450
Labels
custom quirk available A custom quirk is available to solve the issue, but it's not merged in the repo yet Tuya Request/PR regarding a Tuya device

Comments

@itsolon
Copy link

itsolon commented Jun 3, 2022

Hello, the device is possible to connect to ZHA integration
but then it is not really recognized

the device is bought from here:
https://de.aliexpress.com/item/1005004294995498.html?spm=a2g0o.productlist.0.0.7cff2ed9XwpAXp&algo_pvid=c25e2c8c-63d9-4cea-bb0c-5f190d010c75&aem_p4p_detail=202206032153431297942660195650067651185&algo_exp_id=c25e2c8c-63d9-4cea-bb0c-5f190d010c75-55&pdp_ext_f=%7B%22sku_id%22%3A%2212000028662981700%22%7D&pdp_npi=2%40dis%21EUR%21%2111.38%21%21%21%21%21%400b0a01f816543184230937794e1339%2112000028662981700%21sea

Device signature
{
  "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.EndDevice: 2>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress: 128>, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)",
  "endpoints": {
    "1": {
      "profile_id": 260,
      "device_type": "0x0402",
      "in_clusters": [
        "0x0000",
        "0x0001",
        "0x0500"
      ],
      "out_clusters": [
        "0x000a",
        "0x0019"
      ]
    }
  },
  "manufacturer": "_TZE200_3towulqd",
  "model": "TS0601",
  "class": "zigpy.device.Device"
}

Don't remove the extra line breaks outside the ``` marks.
Diagnostic information
{
  "home_assistant": {
    "installation_type": "Home Assistant OS",
    "version": "2022.6.1",
    "dev": false,
    "hassio": true,
    "virtualenv": false,
    "python_version": "3.9.12",
    "docker": true,
    "arch": "x86_64",
    "timezone": "Europe/Berlin",
    "os_name": "Linux",
    "os_version": "5.15.41",
    "supervisor": "2022.05.3",
    "host_os": "Home Assistant OS 8.1",
    "docker_version": "20.10.14",
    "chassis": "vm",
    "run_as_root": true
  },
  "custom_components": {
    "ecowitt": {
      "version": "0.7",
      "requirements": [
        "pyecowitt==0.14"
      ]
    },
    "frigate": {
      "version": "2.3",
      "requirements": []
    },
    "hacs": {
      "version": "1.25.5",
      "requirements": [
        "aiogithubapi>=22.2.4"
      ]
    },
    "sonoff": {
      "version": "3.0.5",
      "requirements": [
        "pycryptodome>=3.6.6"
      ]
    },
    "alarmo": {
      "version": "v1.9.3",
      "requirements": []
    },
    "remote_homeassistant": {
      "version": "3.6",
      "requirements": []
    },
    "ble_monitor": {
      "version": "8.8.0",
      "requirements": [
        "pycryptodomex>=3.14.1",
        "janus>=1.0.0",
        "aioblescan>=0.2.12",
        "btsocket>=0.2.0",
        "pyric>=0.1.6.3"
      ]
    }
  },
  "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": 46235,
    "manufacturer": "_TZE200_3towulqd",
    "model": "TS0601",
    "name": "_TZE200_3towulqd TS0601",
    "quirk_applied": false,
    "quirk_class": "zigpy.device.Device",
    "manufacturer_code": 4417,
    "power_source": "Battery or Unknown",
    "lqi": 18,
    "rssi": null,
    "last_seen": "2022-06-03T19:40:04",
    "available": true,
    "device_type": "EndDevice",
    "signature": {
      "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.EndDevice: 2>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress: 128>, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)",
      "endpoints": {
        "1": {
          "profile_id": 260,
          "device_type": "0x0402",
          "in_clusters": [
            "0x0000",
            "0x0001",
            "0x0500"
          ],
          "out_clusters": [
            "0x000a",
            "0x0019"
          ]
        }
      }
    },
    "entities": [
      {
        "entity_id": "binary_sensor.tze200_3towulqd_ts0601_5bc87feb_ias_zone",
        "name": "_TZE200_3towulqd TS0601"
      },
      {
        "entity_id": "sensor.tze200_3towulqd_ts0601_5bc87feb_power",
        "name": "_TZE200_3towulqd TS0601"
      }
    ],
    "neighbors": [],
    "endpoint_names": [
      {
        "name": "IAS_ZONE"
      }
    ],
    "user_given_name": null,
    "device_reg_id": "c2fdfe7937f3ebd26c55aef21bd6cda7",
    "area_id": "diele"
  }
}
``

</details>

<details>
<summary>Additional logs</summary>

</details>
![Tuya-2-in-1-Zigbee-Mini-PIR-Motion-Bewegung-Menschlichen-K-rper-Detektor-Helligkeit-Leuchtdichte-Sensor jpg_Q90 jpg_](https://user-images.githubusercontent.com/10437947/171983923-ae98c69e-3f83-4cad-a7f7-5c028696490b.png)

@javicalle
Copy link
Collaborator

javicalle commented Jun 5, 2022

Most implementation extracted from the info in:

Proposed quirk:

ts0601_pirmotion.py
"""BlitzWolf IS-3/Tuya motion rechargeable occupancy sensor."""

import math
from typing import Dict

from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
import zigpy.types as t
from zigpy.zcl.clusters.general import Basic, Ota, Time
from zigpy.zcl.clusters.measurement import IlluminanceMeasurement, OccupancySensing
from zigpy.zcl.clusters.security import IasZone

from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)
from zhaquirks.tuya import TuyaLocalCluster
from zhaquirks.tuya.mcu import (
    DPToAttributeMapping,
    TuyaDPType,
    TuyaMCUCluster,
    TuyaPowerConfigurationCluster,
)

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


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


class SensitivityLevel(t.enum8):
    """Sensitivity level enum."""

    LOW = 0x00
    MEDIUM = 0x01
    HIGH = 0x02


class OnTimeValues(t.enum8):
    """Sensitivity level enum."""

    _10_SEC = 0x00
    _30_SEC = 0x01
    _60_SEC = 0x02
    _120_SEC = 0x03


class PirMotionManufCluster(TuyaMCUCluster):
    """Neo manufacturer cluster."""

    attributes = TuyaMCUCluster.attributes.copy()
    attributes.update({0xEF09: ("sensitivity_level", SensitivityLevel)})
    attributes.update({0xEF0A: ("keep_time", OnTimeValues)})

    dp_to_attribute: Dict[int, DPToAttributeMapping] = {
        1: DPToAttributeMapping(
            TuyaOccupancySensing.ep_attribute,
            "occupancy",
            dp_type=TuyaDPType.BOOL,
        ),
        4: DPToAttributeMapping(
            TuyaPowerConfigurationCluster.ep_attribute,
            "battery_percentage_remaining",
            dp_type=TuyaDPType.VALUE,
        ),
        9: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "sensitivity_level",
            dp_type=TuyaDPType.ENUM,
            converter=lambda x: SensitivityLevel(x),
        ),
        10: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "keep_time",
            dp_type=TuyaDPType.ENUM,
            converter=lambda x: OnTimeValues(x),
        ),
        12: 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",
        4: "_dp_2_attr_update",
        9: "_dp_2_attr_update",
        10: "_dp_2_attr_update",
        12: "_dp_2_attr_update",
    }


class PirMotion(CustomDevice):
    """Tuya PIR motion sensor."""

    signature = {
        MODELS_INFO: [("_TZE200_3towulqd", "TS0601")],
        ENDPOINTS: {
            # endpoints=1 profile=260 device_type=0x0402
            # in_clusters=[0x0000, 0x0001, 0x0500],
            # out_clusters=[0x000a, 0x0019]
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    TuyaPowerConfigurationCluster.cluster_id,
                    IasZone.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                ],
            }
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    TuyaPowerConfigurationCluster,
                    PirMotionManufCluster,
                    TuyaOccupancySensing,
                    TuyaIlluminanceMeasurement,
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                ],
            }
        }
    }

The device is a low power device and reading/setting values can be difficult:

@itsolon
Copy link
Author

itsolon commented Jun 5, 2022

Thank you for your answer, but i do not really know what to do with this code..
i assume i should copy it into a file and upload it to HA?
but i already have TS601 switch you wrote a quirk for me already ..
the question is.. how do i know if i can remove that "hand made quirks" because its now in HA zha integration itself?
Best regards Markus

@javicalle
Copy link
Collaborator

One approach is just configure a zha local quirk folder. This is a guide of the steps to follow:

Copy the propposed file in the local folder and restart. If everything is fine, the device signature will change and maybe some new entities will show up in HA.

@itsolon
Copy link
Author

itsolon commented Jun 6, 2022

ok. it seems that every device i buy at the moment is ts0601 and additionally has issues.
Screenshot 2022-06-06 091828

i made file but corrected from ts0601_swicth.py to ts0601_switch.py

and copied your suggest into that file. after restart

{
"node_descriptor": "NodeDescriptor(logical_type=<LogicalType.EndDevice: 2>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress: 128>, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)",
"endpoints": {
"1": {
"profile_id": 260,
"device_type": "0x0402",
"in_clusters": [
"0x0000",
"0x0001",
"0xef00"
],
"out_clusters": [
"0x000a",
"0x0019"
]
}
},
"manufacturer": "_TZE200_3towulqd",
"model": "TS0601",
"class": "ts0601_switch.PirMotion"
}

good news.. the battery with 100% is reporting.
but no entities movement or brightness :-(

{
"home_assistant": {
"installation_type": "Home Assistant OS",
"version": "2022.6.2",
"dev": false,
"hassio": true,
"virtualenv": false,
"python_version": "3.9.12",
"docker": true,
"arch": "x86_64",
"timezone": "Europe/Berlin",
"os_name": "Linux",
"os_version": "5.15.41",
"supervisor": "2022.05.3",
"host_os": "Home Assistant OS 8.1",
"docker_version": "20.10.14",
"chassis": "vm",
"run_as_root": true
},
"custom_components": {
"ecowitt": {
"version": "0.7",
"requirements": [
"pyecowitt==0.14"
]
},
"frigate": {
"version": "2.3",
"requirements": []
},
"hacs": {
"version": "1.25.5",
"requirements": [
"aiogithubapi>=22.2.4"
]
},
"sonoff": {
"version": "3.0.5",
"requirements": [
"pycryptodome>=3.6.6"
]
},
"alarmo": {
"version": "v1.9.4",
"requirements": []
},
"remote_homeassistant": {
"version": "3.6",
"requirements": []
},
"ble_monitor": {
"version": "8.8.0",
"requirements": [
"pycryptodomex>=3.14.1",
"janus>=1.0.0",
"aioblescan>=0.2.12",
"btsocket>=0.2.0",
"pyric>=0.1.6.3"
]
}
},
"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": "sonoffplus*",
"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": 10480,
"manufacturer": "_TZE200_3towulqd",
"model": "TS0601",
"name": "_TZE200_3towulqd TS0601",
"quirk_applied": true,
"quirk_class": "ts0601_switch.PirMotion",
"manufacturer_code": 4417,
"power_source": "Battery or Unknown",
"lqi": 40,
"rssi": null,
"last_seen": "2022-06-06T11:03:06",
"available": true,
"device_type": "EndDevice",
"signature": {
"node_descriptor": "NodeDescriptor(logical_type=<LogicalType.EndDevice: 2>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress: 128>, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)",
"endpoints": {
"1": {
"profile_id": 260,
"device_type": "0x0402",
"in_clusters": [
"0x0000",
"0x0001",
"0xef00"
],
"out_clusters": [
"0x000a",
"0x0019"
]
}
}
},
"entities": [
{
"entity_id": "sensor.galerie_bewegung_power",
"name": "_TZE200_3towulqd TS0601"
}
],
"neighbors": [],
"endpoint_names": [
{
"name": "IAS_ZONE"
}
],
"user_given_name": "Galerie Bewegung",
"device_reg_id": "7410af9d59c022ac8863daf829516868",
"area_id": "galerie"
}
}

@javicalle
Copy link
Collaborator

Is the 'normal' behaviour for most of the Tuya devices (not only yours). If you don't like troubles I would suggest you that avoid them.

The device is loading the quirk, but maybe the DP mapping is not good. Please, enable the debug logs and attach the relevant info (formatted inside ``` please). For enabling the logs:
https://www.home-assistant.io/integrations/zha/#debug-logging

corrected from ts0601_swicth.py to ts0601_switch.py

Ouch 😅

@itsolon
Copy link
Author

itsolon commented Jun 7, 2022

Hi i could successfully activate logs. but dont know how to filter the relevant info for you..
the log is so big
only zigpy interesting?

@javicalle
Copy link
Collaborator

javicalle commented Jun 7, 2022

Usually looking at the logs while interacting with the device and copying the generated logs.
There's not an easy way to do.

I'm not sure in this case, but with some devices you can look for the device identifier, the most right left number (456789 1234) from [1234:1:456789] in the logs.

@itsolon
Copy link
Author

itsolon commented Jun 13, 2022

hi, javicalle, i have installed new intance with few modules.. for test and enabled logging.
for your interest here you can see everything

Device log extracted
2022-06-13 18:48:53 WARNING (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No 'handle_set_data_response' tuya handler found for set_data_response(data=TuyaCommand(status=0, tsn=87, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xaa\x02\x00\x00', *payload=682)))
2022-06-13 18:48:53 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, is_reply=1, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=37, command_id=<GeneralCommand.Default_Response: 11>, *is_reply=True)
2022-06-13 18:48:53 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.UNSUP_CLUSTER_COMMAND: 129>)
2022-06-13 18:48:53 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x4269), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=61184, TSN=37, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x25\x0B\x02\x81')
2022-06-13 18:48:53 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-06-13 18:48:53 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=37)
2022-06-13 18:48:54 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=61184, SrcAddr=0x4269, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=153, SecurityUse=<Bool.false: 0>, TimeStamp=2117896, TSN=0, Data=b'\x09\x26\x02\x00\x58\x01\x04\x00\x01\x01', MacSrcAddr=0x4269, MsgResultRadius=29)
2022-06-13 18:48:54 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received ZCL frame: b'\x09\x26\x02\x00\x58\x01\x04\x00\x01\x01'
2022-06-13 18:48:54 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, is_reply=1, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=38, command_id=2, *is_reply=True)
2022-06-13 18:48:54 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame: PirMotionManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=88, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x01', *payload=<enum8.undefined_0x01: 1>)))
2022-06-13 18:48:54 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received command 0x02 (TSN 38): set_data_response(data=TuyaCommand(status=0, tsn=88, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x01', *payload=<enum8.undefined_0x01: 1>)))
2022-06-13 18:48:54 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No datapoint handler for TuyaCommand(status=0, tsn=88, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x01', *payload=<enum8.undefined_0x01: 1>))
2022-06-13 18:48:54 WARNING (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No 'handle_set_data_response' tuya handler found for set_data_response(data=TuyaCommand(status=0, tsn=88, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x01', *payload=<enum8.undefined_0x01: 1>)))
2022-06-13 18:48:54 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, is_reply=1, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=38, command_id=<GeneralCommand.Default_Response: 11>, *is_reply=True)
2022-06-13 18:48:54 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.UNSUP_CLUSTER_COMMAND: 129>)
2022-06-13 18:48:54 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x4269), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=61184, TSN=38, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x26\x0B\x02\x81')
2022-06-13 18:48:54 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-06-13 18:48:54 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=38)
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy_znp.api] Sending request: SYS.Ping.Req()
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy_znp.api] Received command: SYS.Ping.Rsp(Capabilities=<MTCapabilities.APP_CNF|GP|UTIL|ZDO|AF|SYS: 1625>)
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=61184, SrcAddr=0x4269, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=153, SecurityUse=<Bool.false: 0>, TimeStamp=2211875, TSN=0, Data=b'\x09\x27\x02\x00\x59\x0C\x02\x00\x04\x00\x00\x02\xAA', MacSrcAddr=0x4269, MsgResultRadius=29)
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received ZCL frame: b'\x09\x27\x02\x00\x59\x0C\x02\x00\x04\x00\x00\x02\xAA'
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, is_reply=1, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=39, command_id=2, *is_reply=True)
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame: PirMotionManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=89, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xaa\x02\x00\x00', *payload=682)))
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received command 0x02 (TSN 39): set_data_response(data=TuyaCommand(status=0, tsn=89, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xaa\x02\x00\x00', *payload=682)))
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No datapoint handler for TuyaCommand(status=0, tsn=89, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xaa\x02\x00\x00', *payload=682))
2022-06-13 18:48:55 WARNING (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No 'handle_set_data_response' tuya handler found for set_data_response(data=TuyaCommand(status=0, tsn=89, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xaa\x02\x00\x00', *payload=682)))
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, is_reply=1, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=39, command_id=<GeneralCommand.Default_Response: 11>, *is_reply=True)
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.UNSUP_CLUSTER_COMMAND: 129>)
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x4269), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=61184, TSN=39, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x27\x0B\x02\x81')
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=39)
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=61184, SrcAddr=0x4269, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=149, SecurityUse=<Bool.false: 0>, TimeStamp=2225736, TSN=0, Data=b'\x09\x28\x02\x00\x5A\x01\x04\x00\x01\x00', MacSrcAddr=0x4269, MsgResultRadius=29)
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received ZCL frame: b'\x09\x28\x02\x00\x5A\x01\x04\x00\x01\x00'
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, is_reply=1, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=40, command_id=2, *is_reply=True)
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame: PirMotionManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=90, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x00', *payload=<enum8.undefined_0x00: 0>)))
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received command 0x02 (TSN 40): set_data_response(data=TuyaCommand(status=0, tsn=90, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x00', *payload=<enum8.undefined_0x00: 0>)))
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No datapoint handler for TuyaCommand(status=0, tsn=90, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x00', *payload=<enum8.undefined_0x00: 0>))
2022-06-13 18:48:55 WARNING (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No 'handle_set_data_response' tuya handler found for set_data_response(data=TuyaCommand(status=0, tsn=90, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x00', *payload=<enum8.undefined_0x00: 0>)))
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, is_reply=1, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=40, command_id=<GeneralCommand.Default_Response: 11>, *is_reply=True)
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.UNSUP_CLUSTER_COMMAND: 129>)
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x4269), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=61184, TSN=40, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x28\x0B\x02\x81')
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-06-13 18:48:55 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=40)
2022-06-13 18:49:08 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=61184, SrcAddr=0x4269, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=153, SecurityUse=<Bool.false: 0>, TimeStamp=3054932, TSN=0, Data=b'\x09\x29\x02\x00\x5B\x0C\x02\x00\x04\x00\x00\x02\x92', MacSrcAddr=0x4269, MsgResultRadius=29)
2022-06-13 18:49:08 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received ZCL frame: b'\x09\x29\x02\x00\x5B\x0C\x02\x00\x04\x00\x00\x02\x92'
2022-06-13 18:49:08 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, is_reply=1, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=41, command_id=2, *is_reply=True)
2022-06-13 18:49:09 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame: PirMotionManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=91, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\x92\x02\x00\x00', *payload=658)))
2022-06-13 18:49:09 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received command 0x02 (TSN 41): set_data_response(data=TuyaCommand(status=0, tsn=91, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\x92\x02\x00\x00', *payload=658)))
2022-06-13 18:49:09 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No datapoint handler for TuyaCommand(status=0, tsn=91, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\x92\x02\x00\x00', *payload=658))
2022-06-13 18:49:09 WARNING (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No 'handle_set_data_response' tuya handler found for set_data_response(data=TuyaCommand(status=0, tsn=91, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\x92\x02\x00\x00', *payload=658)))
2022-06-13 18:49:09 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, is_reply=1, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=41, command_id=<GeneralCommand.Default_Response: 11>, *is_reply=True)
2022-06-13 18:49:09 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.UNSUP_CLUSTER_COMMAND: 129>)
2022-06-13 18:49:09 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x4269), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=61184, TSN=41, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x29\x0B\x02\x81')
2022-06-13 18:49:09 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-06-13 18:49:09 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=41)
2022-06-13 18:49:21 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=61184, SrcAddr=0x4269, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=123, SecurityUse=<Bool.false: 0>, TimeStamp=3812443, TSN=0, Data=b'\x09\x2A\x02\x00\x5C\x0C\x02\x00\x04\x00\x00\x02\x62', MacSrcAddr=0x4269, MsgResultRadius=29)
2022-06-13 18:49:21 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received ZCL frame: b'\x09\x2A\x02\x00\x5C\x0C\x02\x00\x04\x00\x00\x02\x62'
2022-06-13 18:49:21 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, is_reply=1, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=42, command_id=2, *is_reply=True)
2022-06-13 18:49:21 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame: PirMotionManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=92, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'b\x02\x00\x00', *payload=610)))
2022-06-13 18:49:21 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received command 0x02 (TSN 42): set_data_response(data=TuyaCommand(status=0, tsn=92, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'b\x02\x00\x00', *payload=610)))
2022-06-13 18:49:21 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No datapoint handler for TuyaCommand(status=0, tsn=92, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'b\x02\x00\x00', *payload=610))
2022-06-13 18:49:21 WARNING (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No 'handle_set_data_response' tuya handler found for set_data_response(data=TuyaCommand(status=0, tsn=92, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'b\x02\x00\x00', *payload=610)))
2022-06-13 18:49:21 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, is_reply=1, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=42, command_id=<GeneralCommand.Default_Response: 11>, *is_reply=True)
2022-06-13 18:49:21 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.UNSUP_CLUSTER_COMMAND: 129>)
2022-06-13 18:49:21 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x4269), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=61184, TSN=42, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x2A\x0B\x02\x81')
2022-06-13 18:49:21 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-06-13 18:49:21 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=42)
2022-06-13 18:49:25 DEBUG (MainThread) [zigpy_znp.api] Sending request: SYS.Ping.Req()
2022-06-13 18:49:25 DEBUG (MainThread) [zigpy_znp.api] Received command: SYS.Ping.Rsp(Capabilities=<MTCapabilities.APP_CNF|GP|UTIL|ZDO|AF|SYS: 1625>)
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=61184, SrcAddr=0x4269, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=94, SecurityUse=<Bool.false: 0>, TimeStamp=4941751, TSN=0, Data=b'\x09\x2B\x02\x00\x5D\x0C\x02\x00\x04\x00\x00\x00\x0B', MacSrcAddr=0x4269, MsgResultRadius=29)
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received ZCL frame: b'\x09\x2B\x02\x00\x5D\x0C\x02\x00\x04\x00\x00\x00\x0B'
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, is_reply=1, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=43, command_id=2, *is_reply=True)
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame: PirMotionManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=93, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\x0b\x00\x00\x00', *payload=11)))
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received command 0x02 (TSN 43): set_data_response(data=TuyaCommand(status=0, tsn=93, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\x0b\x00\x00\x00', *payload=11)))
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No datapoint handler for TuyaCommand(status=0, tsn=93, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\x0b\x00\x00\x00', *payload=11))
2022-06-13 18:49:39 WARNING (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No 'handle_set_data_response' tuya handler found for set_data_response(data=TuyaCommand(status=0, tsn=93, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\x0b\x00\x00\x00', *payload=11)))
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, is_reply=1, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=43, command_id=<GeneralCommand.Default_Response: 11>, *is_reply=True)
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.UNSUP_CLUSTER_COMMAND: 129>)
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x4269), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=61184, TSN=43, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x2B\x0B\x02\x81')
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=43)
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=61184, SrcAddr=0x4269, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=94, SecurityUse=<Bool.false: 0>, TimeStamp=4955974, TSN=0, Data=b'\x09\x2C\x02\x00\x5E\x01\x04\x00\x01\x01', MacSrcAddr=0x4269, MsgResultRadius=29)
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received ZCL frame: b'\x09\x2C\x02\x00\x5E\x01\x04\x00\x01\x01'
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, is_reply=1, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=44, command_id=2, *is_reply=True)
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame: PirMotionManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=94, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x01', *payload=<enum8.undefined_0x01: 1>)))
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received command 0x02 (TSN 44): set_data_response(data=TuyaCommand(status=0, tsn=94, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x01', *payload=<enum8.undefined_0x01: 1>)))
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No datapoint handler for TuyaCommand(status=0, tsn=94, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x01', *payload=<enum8.undefined_0x01: 1>))
2022-06-13 18:49:39 WARNING (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No 'handle_set_data_response' tuya handler found for set_data_response(data=TuyaCommand(status=0, tsn=94, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x01', *payload=<enum8.undefined_0x01: 1>)))
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, is_reply=1, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=44, command_id=<GeneralCommand.Default_Response: 11>, *is_reply=True)
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.UNSUP_CLUSTER_COMMAND: 129>)
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x4269), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=61184, TSN=44, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x2C\x0B\x02\x81')
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-06-13 18:49:39 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=44)
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=61184, SrcAddr=0x4269, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=87, SecurityUse=<Bool.false: 0>, TimeStamp=5140770, TSN=0, Data=b'\x09\x2D\x02\x00\x5F\x0C\x02\x00\x04\x00\x00\x00\x41', MacSrcAddr=0x4269, MsgResultRadius=29)
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received ZCL frame: b'\x09\x2D\x02\x00\x5F\x0C\x02\x00\x04\x00\x00\x00\x41'
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, is_reply=1, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=45, command_id=2, *is_reply=True)
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame: PirMotionManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=95, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'A\x00\x00\x00', *payload=65)))
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received command 0x02 (TSN 45): set_data_response(data=TuyaCommand(status=0, tsn=95, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'A\x00\x00\x00', *payload=65)))
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No datapoint handler for TuyaCommand(status=0, tsn=95, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'A\x00\x00\x00', *payload=65))
2022-06-13 18:49:42 WARNING (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No 'handle_set_data_response' tuya handler found for set_data_response(data=TuyaCommand(status=0, tsn=95, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'A\x00\x00\x00', *payload=65)))
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, is_reply=1, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=45, command_id=<GeneralCommand.Default_Response: 11>, *is_reply=True)
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.UNSUP_CLUSTER_COMMAND: 129>)
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x4269), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=61184, TSN=45, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x2D\x0B\x02\x81')
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=45)
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=61184, SrcAddr=0x4269, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=98, SecurityUse=<Bool.false: 0>, TimeStamp=5154531, TSN=0, Data=b'\x09\x2E\x02\x00\x60\x01\x04\x00\x01\x00', MacSrcAddr=0x4269, MsgResultRadius=29)
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received ZCL frame: b'\x09\x2E\x02\x00\x60\x01\x04\x00\x01\x00'
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, is_reply=1, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=46, command_id=2, *is_reply=True)
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame: PirMotionManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=96, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x00', *payload=<enum8.undefined_0x00: 0>)))
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received command 0x02 (TSN 46): set_data_response(data=TuyaCommand(status=0, tsn=96, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x00', *payload=<enum8.undefined_0x00: 0>)))
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No datapoint handler for TuyaCommand(status=0, tsn=96, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x00', *payload=<enum8.undefined_0x00: 0>))
2022-06-13 18:49:42 WARNING (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No 'handle_set_data_response' tuya handler found for set_data_response(data=TuyaCommand(status=0, tsn=96, dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x00', *payload=<enum8.undefined_0x00: 0>)))
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, is_reply=1, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=46, command_id=<GeneralCommand.Default_Response: 11>, *is_reply=True)
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.UNSUP_CLUSTER_COMMAND: 129>)
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x4269), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=61184, TSN=46, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x2E\x0B\x02\x81')
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-06-13 18:49:42 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=46)
2022-06-13 18:49:53 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=61184, SrcAddr=0x4269, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=80, SecurityUse=<Bool.false: 0>, TimeStamp=5825100, TSN=0, Data=b'\x09\x2F\x02\x00\x61\x0C\x02\x00\x04\x00\x00\x02\xDA', MacSrcAddr=0x4269, MsgResultRadius=29)
2022-06-13 18:49:53 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received ZCL frame: b'\x09\x2F\x02\x00\x61\x0C\x02\x00\x04\x00\x00\x02\xDA'
2022-06-13 18:49:53 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, is_reply=1, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=47, command_id=2, *is_reply=True)
2022-06-13 18:49:53 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Decoded ZCL frame: PirMotionManufCluster:set_data_response(data=TuyaCommand(status=0, tsn=97, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xda\x02\x00\x00', *payload=730)))
2022-06-13 18:49:53 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Received command 0x02 (TSN 47): set_data_response(data=TuyaCommand(status=0, tsn=97, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xda\x02\x00\x00', *payload=730)))
2022-06-13 18:49:53 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No datapoint handler for TuyaCommand(status=0, tsn=97, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xda\x02\x00\x00', *payload=730))
2022-06-13 18:49:53 WARNING (MainThread) [zigpy.zcl] [0x4269:1:0xef00] No 'handle_set_data_response' tuya handler found for set_data_response(data=TuyaCommand(status=0, tsn=97, dp=12, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\xda\x02\x00\x00', *payload=730)))
2022-06-13 18:49:53 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, is_reply=1, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=47, command_id=<GeneralCommand.Default_Response: 11>, *is_reply=True)
2022-06-13 18:49:53 DEBUG (MainThread) [zigpy.zcl] [0x4269:1:0xef00] Sending reply: Default_Response(command_id=2, status=<Status.UNSUP_CLUSTER_COMMAND: 129>)
2022-06-13 18:49:53 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x4269), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=61184, TSN=47, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x2F\x0B\x02\x81')
2022-06-13 18:49:53 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-06-13 18:49:53 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=47)
2022-06-13 18:49:55 DEBUG (MainThread) [zigpy_znp.api] Sending request: SYS.Ping.Req()
2022-06-13 18:49:55 DEBUG (MainThread) [zigpy_znp.api] Received command: SYS.Ping.Rsp(Capabilities=<MTCapabilities.APP_CNF|GP|UTIL|ZDO|AF|SYS: 1625>)
Device signature
{
  "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.EndDevice: 2>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress: 128>, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)",
  "endpoints": {
    "1": {
      "profile_id": 260,
      "device_type": "0x0402",
      "in_clusters": [
        "0x0000",
        "0x0001",
        "0xef00"
      ],
      "out_clusters": [
        "0x000a",
        "0x0019"
      ]
    }
  },
  "manufacturer": "_TZE200_3towulqd",
  "model": "TS0601",
  "class": "ts0601_switch.PirMotion"
}
Diagnostic information
{
  "home_assistant": {
    "installation_type": "Home Assistant OS",
    "version": "2022.6.5",
    "dev": false,
    "hassio": true,
    "virtualenv": false,
    "python_version": "3.9.12",
    "docker": true,
    "arch": "x86_64",
    "timezone": "Europe/Berlin",
    "os_name": "Linux",
    "os_version": "5.15.41",
    "supervisor": "2022.05.3",
    "host_os": "Home Assistant OS 8.1",
    "docker_version": "20.10.14",
    "chassis": "vm",
    "run_as_root": true
  },
  "custom_components": {
    "ble_monitor": {
      "version": "8.8.1",
      "requirements": [
        "pycryptodomex>=3.14.1",
        "janus>=1.0.0",
        "aioblescan>=0.2.12",
        "btsocket>=0.2.0",
        "pyric>=0.1.6.3"
      ]
    },
    "remote_homeassistant": {
      "version": "3.6",
      "requirements": []
    },
    "hacs": {
      "version": "1.25.5",
      "requirements": [
        "aiogithubapi>=22.2.4"
      ]
    }
  },
  "integration_manifest": {
    "domain": "zha",
    "name": "Zigbee Home Automation",
    "config_flow": true,
    "documentation": "https://www.home-assistant.io/integrations/zha",
    "requirements": [
      "bellows==0.30.0",
      "pyserial==3.5",
      "pyserial-asyncio==0.6",
      "zha-quirks==0.0.75",
      "zigpy-deconz==0.16.0",
      "zigpy==0.45.1",
      "zigpy-xbee==0.14.0",
      "zigpy-zigate==0.7.4",
      "zigpy-znp==0.7.0"
    ],
    "usb": [
      {
        "vid": "10C4",
        "pid": "EA60",
        "description": "*2652*",
        "known_devices": [
          "slae.sh cc2652rb stick"
        ]
      },
      {
        "vid": "10C4",
        "pid": "EA60",
        "description": "*sonoff*plus*",
        "known_devices": [
          "sonoff zigbee dongle plus"
        ]
      },
      {
        "vid": "10C4",
        "pid": "EA60",
        "description": "*tubeszb*",
        "known_devices": [
          "TubesZB Coordinator"
        ]
      },
      {
        "vid": "1A86",
        "pid": "7523",
        "description": "*tubeszb*",
        "known_devices": [
          "TubesZB Coordinator"
        ]
      },
      {
        "vid": "1A86",
        "pid": "7523",
        "description": "*zigstar*",
        "known_devices": [
          "ZigStar Coordinators"
        ]
      },
      {
        "vid": "1CF1",
        "pid": "0030",
        "description": "*conbee*",
        "known_devices": [
          "Conbee II"
        ]
      },
      {
        "vid": "10C4",
        "pid": "8A2A",
        "description": "*zigbee*",
        "known_devices": [
          "Nortek HUSBZB-1"
        ]
      },
      {
        "vid": "0403",
        "pid": "6015",
        "description": "*zigate*",
        "known_devices": [
          "ZiGate+"
        ]
      },
      {
        "vid": "10C4",
        "pid": "EA60",
        "description": "*zigate*",
        "known_devices": [
          "ZiGate"
        ]
      },
      {
        "vid": "10C4",
        "pid": "8B34",
        "description": "*bv 2010/10*",
        "known_devices": [
          "Bitron Video AV2010/10"
        ]
      }
    ],
    "codeowners": [
      "@dmulcahey",
      "@adminiuga"
    ],
    "zeroconf": [
      {
        "type": "_esphomelib._tcp.local.",
        "name": "tube*"
      },
      {
        "type": "_zigate-zigbee-gateway._tcp.local.",
        "name": "*zigate*"
      }
    ],
    "after_dependencies": [
      "usb",
      "zeroconf"
    ],
    "iot_class": "local_polling",
    "loggers": [
      "aiosqlite",
      "bellows",
      "crccheck",
      "pure_pcapy3",
      "zhaquirks",
      "zigpy",
      "zigpy_deconz",
      "zigpy_xbee",
      "zigpy_zigate",
      "zigpy_znp"
    ],
    "is_built_in": true
  },
  "data": {
    "ieee": "**REDACTED**",
    "nwk": 17001,
    "manufacturer": "_TZE200_3towulqd",
    "model": "TS0601",
    "name": "_TZE200_3towulqd TS0601",
    "quirk_applied": true,
    "quirk_class": "ts0601_switch.PirMotion",
    "manufacturer_code": 4417,
    "power_source": "Battery or Unknown",
    "lqi": 94,
    "rssi": null,
    "last_seen": "2022-06-13T18:58:09",
    "available": true,
    "device_type": "EndDevice",
    "signature": {
      "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.EndDevice: 2>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress: 128>, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)",
      "endpoints": {
        "1": {
          "profile_id": 260,
          "device_type": "0x0402",
          "in_clusters": [
            "0x0000",
            "0x0001",
            "0xef00"
          ],
          "out_clusters": [
            "0x000a",
            "0x0019"
          ]
        }
      }
    },
    "entities": [
      {
        "entity_id": "sensor.tze200_3towulqd_ts0601_51c662cb_power",
        "name": "_TZE200_3towulqd TS0601"
      }
    ],
    "neighbors": [],
    "endpoint_names": [
      {
        "name": "IAS_ZONE"
      }
    ],
    "user_given_name": null,
    "device_reg_id": "792a6da6e8efa645d188a045299e8e15",
    "area_id": null
  }
}

@javicalle
Copy link
Collaborator

The device signature is telling us that the quirk has been applied:

  "class": "ts0601_switch.PirMotion"

But logs complains that can't find the DP definition:

2022-06-13 18:48:53 WARNING (MainThread) [zigpy.zcl] [0x4269:1:0xef00] 
  No 'handle_set_data_response' tuya handler found for set_data_response(
    data=TuyaCommand(
      status=0, 
      tsn=87, 
      dp=12,     <--- *
      data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, 
      function=0, 
      raw=b'\xaa\x02\x00\x00', 
      *payload=682)
    )
  )

2022-06-13 18:48:54 WARNING (MainThread) [zigpy.zcl] [0x4269:1:0xef00] 
  No 'handle_set_data_response' tuya handler found for set_data_response(
    data=TuyaCommand(
      status=0, 
      tsn=88, 
      dp=1,    <--- *
      data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, 
      function=0, 
      raw=b'\x01', 
      *payload=<enum8.undefined_0x01: 1>)
    )
  )

@itsolon, I have updated the replacement part of the quirk, can you test the new version?:

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    TuyaPowerConfigurationCluster,
                    PirMotionManufCluster,
                    TuyaOccupancySensing,
                    TuyaIlluminanceMeasurement,
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                ],
            }
        }
    }

@itsolon
Copy link
Author

itsolon commented Jun 14, 2022

yes i will please give me 20 min

@itsolon
Copy link
Author

itsolon commented Jun 14, 2022

image

@itsolon
Copy link
Author

itsolon commented Jun 14, 2022

maybe the missing entity is old and can be removed? it seems the occupancy reports very fast

@javicalle
Copy link
Collaborator

maybe the missing entity is old and can be removed?

Yes, probably it is.

Please, look at the logs for any device related errors.

@itsolon
Copy link
Author

itsolon commented Jun 14, 2022

does this device have iaszone which means occupation.. and second entity motion which means motion

like aquara motion sensor has?
image

@javicalle
Copy link
Collaborator

You should be able to set the sensitivity_level and keep_time attributes from the PirMotionManufCluster cluster.

Accepted values would be:

class SensitivityLevel(t.enum8):
    """Sensitivity level enum."""

    LOW = 0x00
    MEDIUM = 0x01
    HIGH = 0x02


class OnTimeValues(t.enum8):
    """Sensitivity level enum."""

    _10_SEC = 0x00
    _30_SEC = 0x01
    _60_SEC = 0x02
    _120_SEC = 0x03

For setting the value, just write the numeric value (0, 1, 2, ...) and push the "SET ZIGBEE ATTRIBUTE".
To check if value is setted, just push the "GET ZIGBEE ATTRIBUTE".

@itsolon
Copy link
Author

itsolon commented Jun 14, 2022

at the moment it works like this
image

@javicalle
Copy link
Collaborator

The device is reporting just a boolean value at DP_1.
We can implement it like an IasZone Motion_Sensor or like an OccupancySensing, but not both.
According to the manufacturer, it would be a "Human Motion Sensor":

Probably if the device signature already has a IasZone would be better implement as a IasZone Motion_Sensor 🤷🏻‍♂️

@itsolon
Copy link
Author

itsolon commented Jun 14, 2022

i try to use your code and test what i can find out.

@javicalle
Copy link
Collaborator

The IasZone alternative woud be like:

  1. add a new MotionSensorCluster class:
class MotionSensorCluster(IasZone, TuyaLocalCluster):
    """Tuya Motion_Sensor Sensor."""

    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Motion_Sensor}
  1. replace the dp_to_attribute mapping in PirMotionManufCluster class:
        1: DPToAttributeMapping(
            MotionSensorCluster.ep_attribute,
            "zone_status",
            dp_type=TuyaDPType.BOOL,
            converter=lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,
        ),
  1. replace the replacement part in PirMotion class:
    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    TuyaPowerConfigurationCluster,
                    PirMotionManufCluster,
                    MotionSensorCluster,
                    TuyaIlluminanceMeasurement,
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                ],
            }
        }
    }

This would replace the OccupancySensing with an IasZone cluster.

@KrOnAsK
Copy link

KrOnAsK commented Jul 14, 2022

Does this sensor now work without custom files in HA? Because I have the same and it doesnt seem to work

@itsolon
Copy link
Author

itsolon commented Jul 15, 2022

Does this sensor now work without custom files in HA? Because I have the same and it doesnt seem to work

HI KrOnAsk i have to tell you that this device didnt work with zha for me.. that was (mainly) the reason to switch over to zigbee2mqtt where it is supported even with a small picture of it..
there it works like a charm.
even other devices i had to fight for were supported out of the box there.
as far as i can say i do not regret to quit zha for the moment.
possible that i come back some time but this was it for now
Thank you to the great support javicalle and matt west ,, they always gave their best.! trying get things to work
but for this device i decided to switch over to zigbee2mqtt,
reason:?
i counted how many devices are supported there and how many at zha,
i dont remember the correct number but it was 3 times more
like 500 to 1500 devices ..
no question about it.
Best regards Markus

@MattWestb
Copy link
Contributor

ZHA is supporting all devices that is Zigbee (ZCL) compatible out of the box and not making strange things like most tuya and Xiaomi devises id doing and is not working as standard Zigbee devices.

If you is baying one new model Philips HUE bulb that is not added to Z2M its not working but in ZHA is working with all ground functions and can needing some patching for getting some extras Philips have putting in so in the end all system have good and bad sides.

@flosch-dev
Copy link

Hello,
I bought the same motion sensor from aliexpress and had the same problems as the originator of this ticket.

@javicalle - thanks a lot for you advises and your code. I was able to get the motion sensor working after following all you recommended changes from the original python file. Just 1 thing I still noticed:

The motion sensor state was inverted.
I changed the following in dp_to_attribute
converter=lambda x: IasZone.ZoneStatus.Alarm_1 if not x else 0,
Maybe there is a better way to fix this, but I'm quite new on ZHA.

For all the others who want to use:

"""BlitzWolf IS-3/Tuya motion rechargeable occupancy sensor."""

import math
from typing import Dict

from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
import zigpy.types as t
from zigpy.zcl.clusters.general import Basic, Ota, Time
from zigpy.zcl.clusters.measurement import IlluminanceMeasurement, OccupancySensing
from zigpy.zcl.clusters.security import IasZone

from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
    ZONE_TYPE,
)
from zhaquirks.tuya import TuyaLocalCluster
from zhaquirks.tuya.mcu import (
    DPToAttributeMapping,
    TuyaDPType,
    TuyaMCUCluster,
    TuyaPowerConfigurationCluster,
)

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

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

class SensitivityLevel(t.enum8):
    """Sensitivity level enum."""

    LOW = 0x00
    MEDIUM = 0x01
    HIGH = 0x02


class OnTimeValues(t.enum8):
    """Sensitivity level enum."""

    _10_SEC = 0x00
    _30_SEC = 0x01
    _60_SEC = 0x02
    _120_SEC = 0x03

class MotionSensorCluster(IasZone, TuyaLocalCluster):
    """Tuya Motion_Sensor Sensor."""
    
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Motion_Sensor}

class PirMotionManufCluster(TuyaMCUCluster):
    """Neo manufacturer cluster."""

    attributes = TuyaMCUCluster.attributes.copy()
    attributes.update({0xEF09: ("sensitivity_level", SensitivityLevel)})
    attributes.update({0xEF0A: ("keep_time", OnTimeValues)})

    dp_to_attribute: Dict[int, DPToAttributeMapping] = {
        1: DPToAttributeMapping(
            MotionSensorCluster.ep_attribute,
            "zone_status",
            dp_type=TuyaDPType.BOOL,
            converter=lambda x: IasZone.ZoneStatus.Alarm_1 if not x else 0,
        ),
        4: DPToAttributeMapping(
            TuyaPowerConfigurationCluster.ep_attribute,
            "battery_percentage_remaining",
            dp_type=TuyaDPType.VALUE,
        ),
        9: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "sensitivity_level",
            dp_type=TuyaDPType.ENUM,
            converter=lambda x: SensitivityLevel(x),
        ),
        10: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "keep_time",
            dp_type=TuyaDPType.ENUM,
            converter=lambda x: OnTimeValues(x),
        ),
        12: DPToAttributeMapping(
            TuyaIlluminanceMeasurement.ep_attribute,
            "measured_value",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: (10000 * math.log10(x) + 1 )/ 10,
        ),
    }

    data_point_handlers = {
        1: "_dp_2_attr_update",
        4: "_dp_2_attr_update",
        9: "_dp_2_attr_update",
        10: "_dp_2_attr_update",
        12: "_dp_2_attr_update",
    }


class PirMotion(CustomDevice):
    """Tuya PIR motion sensor."""

    signature = {
        MODELS_INFO: [("_TZE200_3towulqd", "TS0601")],
        ENDPOINTS: {
            # endpoints=1 profile=260 device_type=0x0402
            # in_clusters=[0x0000, 0x0001, 0x0500],
            # out_clusters=[0x000a, 0x0019]
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    TuyaPowerConfigurationCluster.cluster_id,
                    IasZone.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                ],
            }
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    TuyaPowerConfigurationCluster,
                    PirMotionManufCluster,
                    MotionSensorCluster,
                    TuyaIlluminanceMeasurement,
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                ],
            }
        }
    }
    

@thatguy-za
Copy link

Can we reopen this issue?

I've just got one of these sensors and it would be great to get it supported in ZHA than need to use a quirk.

@KrOnAsK
Copy link

KrOnAsK commented Aug 24, 2022

I would love that too

@thatguy-za
Copy link

thatguy-za commented Aug 24, 2022

Just because there is a lot going on in this thread, the current solution to this is as follows:

  1. Create a folder for your custom quirks (I created /config/zha_quirks/)

  2. Create a quirk/file in this directory (I followed the guide above and called it "ts0601_pirmotion.py"). This file should contain the quirk from this post - _TZE200_3towulqd TS0601 Tuya Motion Sensor with illuminance sensor #1599 (comment)

  3. Add the following to your config.yaml

zha:
  custom_quirks_path: /config/zha_quirks/
  1. Restart HA
  2. Sensors for Illuminance and Occupancy should be added to your entity (you might need to re-add your device)

@thatguy-za
Copy link

Another user has submitted a pull request here - home-assistant/home-assistant.io#23884

@James-Lee-007
Copy link

Most implementation extracted from the info in:

Proposed quirk:

ts0601_pirmotion.py

"""BlitzWolf IS-3/Tuya motion rechargeable occupancy sensor."""

import math
from typing import Dict

from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
import zigpy.types as t
from zigpy.zcl.clusters.general import Basic, Ota, Time
from zigpy.zcl.clusters.measurement import IlluminanceMeasurement, OccupancySensing
from zigpy.zcl.clusters.security import IasZone

from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)
from zhaquirks.tuya import TuyaLocalCluster
from zhaquirks.tuya.mcu import (
    DPToAttributeMapping,
    TuyaDPType,
    TuyaMCUCluster,
    TuyaPowerConfigurationCluster,
)

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


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


class SensitivityLevel(t.enum8):
    """Sensitivity level enum."""

    LOW = 0x00
    MEDIUM = 0x01
    HIGH = 0x02


class OnTimeValues(t.enum8):
    """Sensitivity level enum."""

    _10_SEC = 0x00
    _30_SEC = 0x01
    _60_SEC = 0x02
    _120_SEC = 0x03


class PirMotionManufCluster(TuyaMCUCluster):
    """Neo manufacturer cluster."""

    attributes = TuyaMCUCluster.attributes.copy()
    attributes.update({0xEF09: ("sensitivity_level", SensitivityLevel)})
    attributes.update({0xEF0A: ("keep_time", OnTimeValues)})

    dp_to_attribute: Dict[int, DPToAttributeMapping] = {
        1: DPToAttributeMapping(
            TuyaOccupancySensing.ep_attribute,
            "occupancy",
            dp_type=TuyaDPType.BOOL,
        ),
        4: DPToAttributeMapping(
            TuyaPowerConfigurationCluster.ep_attribute,
            "battery_percentage_remaining",
            dp_type=TuyaDPType.VALUE,
        ),
        9: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "sensitivity_level",
            dp_type=TuyaDPType.ENUM,
            converter=lambda x: SensitivityLevel(x),
        ),
        10: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "keep_time",
            dp_type=TuyaDPType.ENUM,
            converter=lambda x: OnTimeValues(x),
        ),
        12: 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",
        4: "_dp_2_attr_update",
        9: "_dp_2_attr_update",
        10: "_dp_2_attr_update",
        12: "_dp_2_attr_update",
    }


class PirMotion(CustomDevice):
    """Tuya PIR motion sensor."""

    signature = {
        MODELS_INFO: [("_TZE200_3towulqd", "TS0601")],
        ENDPOINTS: {
            # endpoints=1 profile=260 device_type=0x0402
            # in_clusters=[0x0000, 0x0001, 0x0500],
            # out_clusters=[0x000a, 0x0019]
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    TuyaPowerConfigurationCluster.cluster_id,
                    IasZone.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                ],
            }
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    TuyaPowerConfigurationCluster,
                    PirMotionManufCluster,
                    TuyaOccupancySensing,
                    TuyaIlluminanceMeasurement,
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                ],
            }
        }
    }

The device is a low power device and reading/setting values can be difficult:

Excuse me, maybe someone could help me see what I'm doing wrong...

I have the same small motion sensors from Aliexpress:

image

I connected it with the zha integration, but it appeared as a smoke detector. So I searched and found this quirk. I copied the code into a python file and named it "motion _sensor.py" and put it into a custom quirks folder in my home assistant server, and in the configuration.yaml file I wrote this:

zha: custom_quirks_path: /config/custom_zha_quirks/

But when I restart HA it completely disables my zha, and gives this error:

`Logger: homeassistant.config_entries
Source: custom_zha_quirks/motion_sensor.py:22
First occurred: 13:28:52 (1 occurrences)
Last logged: 13:28:52

Error setting up entry Sonoff Zigbee 3.0 USB Dongle Plus - Sonoff Zigbee 3.0 USB Dongle Plus for zha
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/config_entries.py", line 383, in async_setup
result = await component.async_setup_entry(hass, self)
File "/usr/src/homeassistant/homeassistant/components/zha/init.py", line 110, in async_setup_entry
setup_quirks(config)
File "/usr/local/lib/python3.10/site-packages/zhaquirks/init.py", line 409, in setup
importer.find_module(modname).load_module(modname)
File "", line 548, in _check_name_wrapper
File "", line 1063, in load_module
File "", line 888, in load_module
File "", line 290, in _load_module_shim
File "", line 719, in _load
File "", line 688, in _load_unlocked
File "", line 883, in exec_module
File "", line 241, in _call_with_frames_removed
File "/config/custom_zha_quirks/motion_sensor.py", line 22, in
from zhaquirks.tuya.mcu import (
ImportError: cannot import name 'TuyaDPType' from 'zhaquirks.tuya.mcu' (/usr/local/lib/python3.10/site-packages/zhaquirks/tuya/mcu/init.py)
`

What am I doing wrong? I would appreciate any help, thanks in advance!

@javicalle
Copy link
Collaborator

Check here:
#2250 (comment)

@Naheem
Copy link

Naheem commented Mar 19, 2023

Can some of the people updating this please submit it as a pull request?

I have used the modified quirk from #1599 (comment), thank you very much.

I did have to update my scripts though as the IASzone that I was using previously was not unavailable but occupacy was available (I cant remember if that existed before or not).

Also, I have no idea how often it checks for luminance. is it whenever the occupancy state changes or more often?

@GerardUmbert
Copy link

GerardUmbert commented Mar 21, 2023

You should be able to set the sensitivity_level and keep_time attributes from the PirMotionManufCluster cluster.

Accepted values would be:

class SensitivityLevel(t.enum8):
    """Sensitivity level enum."""

    LOW = 0x00
    MEDIUM = 0x01
    HIGH = 0x02


class OnTimeValues(t.enum8):
    """Sensitivity level enum."""

    _10_SEC = 0x00
    _30_SEC = 0x01
    _60_SEC = 0x02
    _120_SEC = 0x03

For setting the value, just write the numeric value (0, 1, 2, ...) and push the "SET ZIGBEE ATTRIBUTE". To check if value is setted, just push the "GET ZIGBEE ATTRIBUTE".

Can you explain further about the setting the timing attribute, right now IASzone triggers every 10 seconds, i think for my usecase 60secs would be better, but i don't understand the "SET ZIGBEE ATTRIBUTE" you mention.

EDIT: I've managet to set the attribute, but it does most certainly not do anything with the 120secs I have setup, it reacts in like 8-10 seconds

image

@mwkldeveloper
Copy link

mwkldeveloper commented Mar 24, 2023

Most implementation extracted from the info in:

Proposed quirk:

ts0601_pirmotion.py
The device is a low power device and reading/setting values can be difficult:

TuyaDPType seems not in mcu anymore --> #2190 (comment)
Update ts0601_pirmotion.py by removing all TuyaDPType related code and restart HA twice times <--I don't know why need restart twice times to get all entity work. but it works.

updated ts0601_pirmotion.py
"""BlitzWolf IS-3/Tuya motion rechargeable occupancy sensor."""

import math
from typing import Dict

from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
import zigpy.types as t
from zigpy.zcl.clusters.general import Basic, Ota, Time
from zigpy.zcl.clusters.measurement import IlluminanceMeasurement, OccupancySensing
from zigpy.zcl.clusters.security import IasZone
from zigpy.zcl import foundation

from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)
from zhaquirks.tuya import TuyaLocalCluster
from zhaquirks.tuya.mcu import (
    DPToAttributeMapping,
    TuyaMCUCluster,
    TuyaPowerConfigurationCluster,
)

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


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


class SensitivityLevel(t.enum8):
    """Sensitivity level enum."""

    LOW = 0x00
    MEDIUM = 0x01
    HIGH = 0x02


class OnTimeValues(t.enum8):
    """Sensitivity level enum."""

    _10_SEC = 0x00
    _30_SEC = 0x01
    _60_SEC = 0x02
    _120_SEC = 0x03


class PirMotionManufCluster(TuyaMCUCluster):
    """Neo manufacturer cluster."""

    attributes = TuyaMCUCluster.attributes.copy()
    attributes.update({0xEF09: ("sensitivity_level", SensitivityLevel)})
    attributes.update({0xEF0A: ("keep_time", OnTimeValues)})

    async def write_attributes(self, attributes, manufacturer=None):
        """Overwrite to force manufacturer code."""

        return await super().write_attributes(
            attributes, manufacturer=foundation.ZCLHeader.NO_MANUFACTURER_ID
        )

    dp_to_attribute: Dict[int, DPToAttributeMapping] = {
        1: DPToAttributeMapping(
            TuyaOccupancySensing.ep_attribute,
            "occupancy",
            converter=lambda x: IasZone.ZoneStatus.Alarm_1 if not x else 0,
        ),
        4: DPToAttributeMapping(
            TuyaPowerConfigurationCluster.ep_attribute,
            "battery_percentage_remaining",
        ),
        9: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "sensitivity_level",
            converter=lambda x: SensitivityLevel(x),
        ),
        10: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "keep_time",
            converter=lambda x: OnTimeValues(x),
        ),
        12: DPToAttributeMapping(
            TuyaIlluminanceMeasurement.ep_attribute,
            "measured_value",
            converter=lambda x: 10000 * math.log10(x) + 1 if x != 0 else 0,
        ),
    }

    data_point_handlers = {
        1: "_dp_2_attr_update",
        4: "_dp_2_attr_update",
        9: "_dp_2_attr_update",
        10: "_dp_2_attr_update",
        12: "_dp_2_attr_update",
    }


class PirMotion(CustomDevice):
    """Tuya PIR motion sensor."""

    signature = {
        MODELS_INFO: [("_TZE200_3towulqd", "TS0601")],
        ENDPOINTS: {
            # endpoints=1 profile=260 device_type=0x0402
            # in_clusters=[0x0000, 0x0001, 0x0500],
            # out_clusters=[0x000a, 0x0019]
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    TuyaPowerConfigurationCluster.cluster_id,
                    IasZone.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                ],
            }
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    TuyaPowerConfigurationCluster,
                    PirMotionManufCluster,
                    TuyaOccupancySensing,
                    TuyaIlluminanceMeasurement,
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                ],
            }
        }
    }

@antoweb
Copy link

antoweb commented Apr 5, 2023

Most implementation extracted from the info in:

Proposed quirk:
ts0601_pirmotion.py
The device is a low power device and reading/setting values can be difficult:

TuyaDPType seems not in mcu anymore --> #2190 (comment) Update ts0601_pirmotion.py by removing all TuyaDPType related code and restart HA twice times <--I don't know why need restart twice times to get all entity work. but it works.

updated ts0601_pirmotion.py

Hello with this quirks my sensor goes on and off the presence detection every minute itself. Any help?

@polter05
Copy link

Hello,

Same problem. After deletion, reset then reinstallation, triggering every 30 minutes. Any idea knowing that it worked perfectly before last weekend? I always do day-to-day updates.

@polter05
Copy link

Hello,

Same problem. After deletion, reset then reinstallation, triggering every 30 minutes. Any idea knowing that it worked perfectly before last weekend? I always do day-to-day updates.

After a few time, every minutes yet. nothing to do. no body have the same issue ? with zha or with z2b, it's the same problem.

@jmanis2
Copy link

jmanis2 commented Jun 9, 2023

The updated quirk in #1599 (comment) has gotten this to work and resolved the issue with the original quirk and mappings for mcu. Can we get this added to the repository as I missed this burried in the comments.

The only issue that I'm having is that the occupancy sensor appears to be inverted, meaning that when motion is detected it's clearing the occupancy and when there's no motion it sets occupancy. Additionally the device is updating the status every 10 seconds so if I'm near it, it's continually flipping status from occupied to unoccupied. I've attempted to change the PirMotionManfuCluster : keeptime attribute as well as the TuyaOccupancySensing : pir_o_to_u_delay attributes but none appear to have any affect on the delay between occupied to unoccupied. I may just try to integrate this in to the automation that if the status hasn't changed in 5 mins then trigger an unoccupied action but I'd rather see this get improved in the integration.

Naheem added a commit to Naheem/zha-device-handlers that referenced this issue Jul 2, 2023
Copy latest version from zigpy#1599
@Naheem Naheem linked a pull request Jul 2, 2023 that will close this issue
3 tasks
@Naheem
Copy link

Naheem commented Jul 2, 2023

I have created a pull request with the quirk in this issue, to try and get it merged upstream instead of being left in an issue.

However it may need input from people more knowledgeable than me, so any assistance in getting this committed will be helpful.

@ivan-gj
Copy link

ivan-gj commented Jul 20, 2023

Hello, @Naheem ! I just tried the quirk, and though HA now perfectly shows the "Occupancy" sensor, the Illuminance sensor is not being shown, but I can perfectly get its reading in the device manager as shown in this screen shot (sorry for the Spanish):
Screenshot_20230720_174841
The question would clearly be... how can I turn that into a Sensor? Or is this working differently for you?


Solved!

Seems like a full restart of the HA machine suddenly did the thing.

@fr4ngus
Copy link

fr4ngus commented Sep 29, 2023

Hi,
I'm going to ZHA zigbee manage sensor section but I don't find how to change the value of the sensitivity of the motion sensor.
I use the updated script of the sensor but it doesn't work.
Thank you for your help.

@AdaaamB
Copy link

AdaaamB commented Oct 3, 2023

#1599 (comment) working perfectly for me, thank you and thanks to thatguy-za for the steps to get it working!

@vascofazza
Copy link

I installed the quirk and according to the logs it's getting loaded.
Anyway, I cannot see any configuration about keep_time. I restarted the HA instance and I didn't have any quirk before, so no cache was there already.
Am I doing something wrong?
image

@antoweb
Copy link

antoweb commented Jan 20, 2024

Quirks as follow works good for presence and illuminance but no battery.
Any news?

`"""BlitzWolf IS-3/Tuya motion rechargeable occupancy sensor."""

import math
from typing import Dict

from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
import zigpy.types as t
from zigpy.zcl.clusters.general import Basic, Ota, Time
from zigpy.zcl.clusters.measurement import IlluminanceMeasurement, OccupancySensing
from zigpy.zcl.clusters.security import IasZone
from zigpy.zcl import foundation

from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
)
from zhaquirks.tuya import TuyaLocalCluster
from zhaquirks.tuya.mcu import (
DPToAttributeMapping,
TuyaMCUCluster,
TuyaPowerConfigurationCluster,
)

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

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

class SensitivityLevel(t.enum8):
"""Sensitivity level enum."""

LOW = 0x00
MEDIUM = 0x01
HIGH = 0x02

class OnTimeValues(t.enum8):
"""Sensitivity level enum."""

_10_SEC = 0x00
_30_SEC = 0x01
_60_SEC = 0x02
_120_SEC = 0x03

class PirMotionManufCluster(TuyaMCUCluster):
"""Neo manufacturer cluster."""

attributes = TuyaMCUCluster.attributes.copy()
attributes.update({0xEF09: ("sensitivity_level", SensitivityLevel)})
attributes.update({0xEF0A: ("keep_time", OnTimeValues)})

async def write_attributes(self, attributes, manufacturer=None):
    """Overwrite to force manufacturer code."""

    return await super().write_attributes(
        attributes, manufacturer=foundation.ZCLHeader.NO_MANUFACTURER_ID
    )

dp_to_attribute: Dict[int, DPToAttributeMapping] = {
    1: DPToAttributeMapping(
        TuyaOccupancySensing.ep_attribute,
        "occupancy",
        converter=lambda x: IasZone.ZoneStatus.Alarm_1 if not x else 0,
    ),
    4: DPToAttributeMapping(
        TuyaPowerConfigurationCluster.ep_attribute,
        "battery_percentage_remaining",
    ),
    9: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "sensitivity_level",
        converter=lambda x: SensitivityLevel(x),
    ),
    10: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "keep_time",
        converter=lambda x: OnTimeValues(x),
    ),
    12: DPToAttributeMapping(
        TuyaIlluminanceMeasurement.ep_attribute,
        "measured_value",
        converter=lambda x: 10000 * math.log10(x) + 1 if x != 0 else 0,
    ),
}

data_point_handlers = {
    1: "_dp_2_attr_update",
    4: "_dp_2_attr_update",
    9: "_dp_2_attr_update",
    10: "_dp_2_attr_update",
    12: "_dp_2_attr_update",
}

class PirMotion(CustomDevice):
"""Tuya PIR motion sensor."""

signature = {
    MODELS_INFO: [("_TZE200_3towulqd", "TS0601")],
    ENDPOINTS: {
        # endpoints=1 profile=260 device_type=0x0402
        # in_clusters=[0x0000, 0x0001, 0x0500],
        # out_clusters=[0x000a, 0x0019]
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                TuyaPowerConfigurationCluster.cluster_id,
                IasZone.cluster_id,
            ],
            OUTPUT_CLUSTERS: [
                Time.cluster_id,
                Ota.cluster_id,
            ],
        }
    },
}

replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                TuyaPowerConfigurationCluster,
                PirMotionManufCluster,
                TuyaOccupancySensing,
                TuyaIlluminanceMeasurement,
            ],
            OUTPUT_CLUSTERS: [
                Time.cluster_id,
                Ota.cluster_id,
            ],
        }
    }
}`

@antoweb
Copy link

antoweb commented Jan 20, 2024

Sorry battery sensor works good but illuminance value is updated only after presence detection

@Naheem
Copy link

Naheem commented Jan 20, 2024

I dont think the battery sensor actually works - I had a device battery die recently and until the last day it had battery status as 100%

@vinzent
Copy link

vinzent commented Jun 3, 2024

For the records.

Bildschirmfoto vom 2024-06-03 10-06-44
Bildschirmfoto vom 2024-06-03 10-06-23
Bildschirmfoto vom 2024-06-03 09-52-50
Screenshot_20240603-093536
Screenshot_20240603-093527
Screenshot_20240603-093507
Screenshot_20240603-093456
Screenshot_20240603-093448
Screenshot_20240603-093428

Extracted DP Id's:

{
"1":"PIR state",
"4":"Battery level",
"9":"PIR Sensitivity",
"10":"Keep time",
"12":"Illuminance value",
"102":"Light Sense Interval Time(Version 2.0.1 and above)"
}

@vinzent
Copy link

vinzent commented Jun 7, 2024

quirk v2 variant: https://gist.github.com/vinzent/2194a8ef531d8e8ec3bc17ea17eab0e9

Looks like in HA 2024.06.0:

grafik

@cemizm
Copy link

cemizm commented Jun 12, 2024

I have the same sensor and without any custom quirks (2024.6.2)

image

The illuminance stays at exactly zero with some short spikes around 2000 (blue line). As comparision i included the illuminance of motion sensor from another vendor.

image

It is also strange that the illuminance is more like a discrete then continuous values. i dont have a tuya bride to test it with the tuya app, but would be interesting to correlate the value of the app with the raw value we receive before converting with log10. or maybe it is just my sensor that has some defect?

@vinzent
Copy link

vinzent commented Jun 12, 2024

@cemizm At least for me the Illumimance measurement seems to be good (with quirk). Developping my version of the quirk, i've discovered that when mapping the tuya datapoint to the Illuminance cluster, there were 2 values sent every time. The device sends illuminance values even when zha doesnt bind to the illuminance cluster measure_value attribute. with the double reporting the value switched between around 0 and the real lux value.

@cemizm
Copy link

cemizm commented Jun 13, 2024

@vinzent thank you for your great work! With your quirk the illuminance seems to be working now at a first glance, but I will let it run for while to plot the results for a whole day. :)

@vinzent
Copy link

vinzent commented Jun 13, 2024

@cemizm beaware of the quirks v2 issue which prevents reloading the ZHA integration: zigpy/zigpy#1410

@cemizm
Copy link

cemizm commented Jun 13, 2024

@cemizm beaware of the quirks v2 issue which prevents reloading the ZHA integration: zigpy/zigpy#1410

good to know, will save me a lot of time when i run into that issue

@cemizm
Copy link

cemizm commented Jun 23, 2024

@vinzent again, thank you for the custom_quirk. the illuminance value look much better now:

image

how can i help to get this quirk integrated as default device handler?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
custom quirk available A custom quirk is available to solve the issue, but it's not merged in the repo yet Tuya Request/PR regarding a Tuya device
Projects
None yet
Development

Successfully merging a pull request may close this issue.