zigpy / zha-device-handlers

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

[Device Support Request] - TZE204_qasjif9e - mmWave Sensor #2510

Open robert1993 opened 1 year ago

robert1993 commented 1 year ago

Problem description

Wall mount 5v version of this product: https://nl.aliexpress.com/item/1005005477612297.html?spm=a2g0o.order_list.order_list_main.16.2a5879d214SME3&gatewayAdapt=glo2nld

Solution description

Support for the device. Not sure what to provide in order to be able to create quirk. It seems that there's already support for z2m for what it's worth.

Screenshots/Video

Screenshots/Video [Paste/upload your media here]

Device signature

Device signature ```json { "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)", "endpoints": { "1": { "profile_id": "0x0104", "device_type": "0x0051", "input_clusters": [ "0x0000", "0x0004", "0x0005", "0xef00" ], "output_clusters": [ "0x000a", "0x0019" ] }, "242": { "profile_id": "0xa1e0", "device_type": "0x0061", "input_clusters": [], "output_clusters": [ "0x0021" ] } }, "manufacturer": "_TZE204_qasjif9e", "model": "TS0601", "class": "zigpy.device.Device" } ```

Diagnostic information

Diagnostic information ```json { "home_assistant": { "installation_type": "Home Assistant OS", "version": "2023.8.0", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.11.4", "docker": true, "arch": "x86_64", "timezone": "Europe/Amsterdam", "os_name": "Linux", "os_version": "6.1.39", "supervisor": "2023.07.1", "host_os": "Home Assistant OS 10.4", "docker_version": "23.0.6", "chassis": "vm", "run_as_root": true }, "custom_components": { "enphase_envoy": { "version": "0.0.13", "requirements": [ "envoy-utils" ] }, "alarmo": { "version": "v1.9.10", "requirements": [] }, "scheduler": { "version": "v0.0.0", "requirements": [] }, "mass": { "version": "2023.2.2", "requirements": [] }, "hacs": { "version": "1.32.1", "requirements": [ "aiogithubapi>=22.10.1" ] }, "neerslag": { "version": "2022.07.07.1", "requirements": [] }, "adaptive_lighting": { "version": "1.18.3", "requirements": [ "ulid-transform" ] }, "afvalwijzer": { "version": "2023.06.01", "requirements": [] }, "frigate": { "version": "4.0.0", "requirements": [ "pytz==2022.7" ] }, "watchman": { "version": "0.5.1", "requirements": [ "prettytable==3.0.0" ] }, "better_thermostat": { "version": "1.2.2", "requirements": [] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "after_dependencies": [ "onboarding", "usb" ], "codeowners": [ "@dmulcahey", "@adminiuga", "@puddly" ], "config_flow": true, "dependencies": [ "file_upload" ], "documentation": "https://www.home-assistant.io/integrations/zha", "iot_class": "local_polling", "loggers": [ "aiosqlite", "bellows", "crccheck", "pure_pcapy3", "zhaquirks", "zigpy", "zigpy_deconz", "zigpy_xbee", "zigpy_zigate", "zigpy_znp" ], "requirements": [ "bellows==0.35.8", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.102", "zigpy-deconz==0.21.0", "zigpy==0.56.2", "zigpy-xbee==0.18.1", "zigpy-zigate==0.11.0", "zigpy-znp==0.11.3" ], "usb": [ { "vid": "10C4", "pid": "EA60", "description": "*2652*", "known_devices": [ "slae.sh cc2652rb stick" ] }, { "vid": "1A86", "pid": "55D4", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus v2" ] }, { "vid": "10C4", "pid": "EA60", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus" ] }, { "vid": "10C4", "pid": "EA60", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*zigstar*", "known_devices": [ "ZigStar Coordinators" ] }, { "vid": "1CF1", "pid": "0030", "description": "*conbee*", "known_devices": [ "Conbee II" ] }, { "vid": "10C4", "pid": "8A2A", "description": "*zigbee*", "known_devices": [ "Nortek HUSBZB-1" ] }, { "vid": "0403", "pid": "6015", "description": "*zigate*", "known_devices": [ "ZiGate+" ] }, { "vid": "10C4", "pid": "EA60", "description": "*zigate*", "known_devices": [ "ZiGate" ] }, { "vid": "10C4", "pid": "8B34", "description": "*bv 2010/10*", "known_devices": [ "Bitron Video AV2010/10" ] } ], "zeroconf": [ { "type": "_esphomelib._tcp.local.", "name": "tube*" }, { "type": "_zigate-zigbee-gateway._tcp.local.", "name": "*zigate*" }, { "type": "_zigstar_gw._tcp.local.", "name": "*zigstar*" }, { "type": "_slzb-06._tcp.local.", "name": "slzb-06*" } ], "is_built_in": true }, "data": { "ieee": "**REDACTED**", "nwk": 56924, "manufacturer": "_TZE204_qasjif9e", "model": "TS0601", "name": "_TZE204_qasjif9e TS0601", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "manufacturer_code": 4417, "power_source": "Mains", "lqi": 145, "rssi": null, "last_seen": "2023-08-04T09:07:35", "available": true, "device_type": "Router", "signature": { "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)", "endpoints": { "1": { "profile_id": "0x0104", "device_type": "0x0051", "input_clusters": [ "0x0000", "0x0004", "0x0005", "0xef00" ], "output_clusters": [ "0x000a", "0x0019" ] }, "242": { "profile_id": "0xa1e0", "device_type": "0x0061", "input_clusters": [], "output_clusters": [ "0x0021" ] } }, "manufacturer": "_TZE204_qasjif9e", "model": "TS0601" }, "active_coordinator": false, "entities": [], "neighbors": [], "routes": [], "endpoint_names": [ { "name": "SMART_PLUG" }, { "name": "PROXY_BASIC" } ], "user_given_name": "mmWave", "device_reg_id": "319a684c083a0822065c72edc7933800", "area_id": "kantoor_robert", "cluster_details": { "1": { "device_type": { "name": "SMART_PLUG", "id": 81 }, "profile_id": 260, "in_clusters": { "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0xef00": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} }, "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0001": { "attribute_name": "app_version", "value": 74 }, "0x0004": { "attribute_name": "manufacturer", "value": "_TZE204_qasjif9e" }, "0x0005": { "attribute_name": "model", "value": "TS0601" }, "0x0007": { "attribute_name": "power_source", "value": 1 } }, "unsupported_attributes": {} } }, "out_clusters": { "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} }, "0x000a": { "endpoint_attribute": "time", "attributes": {}, "unsupported_attributes": {} } } }, "242": { "device_type": { "name": "PROXY_BASIC", "id": 97 }, "profile_id": 41440, "in_clusters": {}, "out_clusters": { "0x0021": { "endpoint_attribute": "green_power", "attributes": {}, "unsupported_attributes": {} } } } } } } ```

Logs

Logs ```python [Paste the logs here] ```

Custom quirk

Custom quirk ```python [Paste your custom quirk here] ```

Additional information

No response

drashish87 commented 1 year ago

I have also spent more than 5 hours looking for a quirk to support this one!

jbustdel commented 1 year ago

Try this, works ok but not regulations and no light sensor. A switch is present, i dont Know why.....

"""Human Presence Sensor 24GHz."""

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, GreenPowerProxy, Groups, Ota, Scenes, Time
from zigpy.zcl.clusters.measurement import (
OccupancySensing,
IlluminanceMeasurement,
)
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,
)

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

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

class MmwRadarManufCluster(TuyaMCUCluster):
"""Human Presence Sensor 24GHz."""

attributes = TuyaMCUCluster.attributes.copy()
attributes.update(
    {
        # ramdom attribute IDs
        0xEF65: ("duration_of_attendance", t.uint32_t, True),
        0xEF66: ("duration_of_absence", t.uint32_t, True),
    }
)

dp_to_attribute: Dict[int, DPToAttributeMapping] = {
    1: DPToAttributeMapping(
        TuyaOccupancySensing.ep_attribute,
        "occupancy"
    ),
    101: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "duration_of_attendance"
    ),
    102: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "duration_of_absence"
    ),
    113: DPToAttributeMapping(
        TuyaNewManufCluster.ep_attribute,
        "dp_113",
    ),
}

data_point_handlers = {
    1: "_dp_2_attr_update",
    101: "_dp_2_attr_update",
    102: "_dp_2_attr_update",
    113: "_dp_2_attr_update",
}
class MmwRadarMotion_var03(CustomDevice):
"""Millimeter wave occupancy sensor."""

signature = {
    #  endpoint=1, profile=260, device_type=81, device_version=1,
    #  input_clusters=[4, 5, 61184, 0], output_clusters=[25, 10])
    MODELS_INFO: [
        ("_TZE200_0u3bj3rc", "TS0601"),
        ("_TZE200_mx6u6l4y", "TS0601"),
        ("_TZE200_v6ossqfy", "TS0601"),
        ("_TZE204_qasjif9e", "TS0601")
    ],
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaMCUCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        242: {
            # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
            # input_clusters=[]
            # output_clusters=[33]
            PROFILE_ID: 41440,
            DEVICE_TYPE: 97,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}

replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                MmwRadarManufCluster,
                TuyaOccupancySensing,
                TuyaAnalogInput,
                TuyaIlluminanceMeasurement,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        242: {
            PROFILE_ID: 41440,
            DEVICE_TYPE: 97,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    }
}
scotie commented 1 year ago

There is another issue for a similar device request from a different manufacturer. I tried This quirk and added a line of our device. The occupancy isn’t working, but the light sensor is. Maybe that helps. Didn’t have too much time to play with it

scotie commented 1 year ago

OK, I had some time to play with this yesterday and made some progress. Disclaimer: this is my first-ever attempt using quirks.

@jbustdel, the code you posted doesn't work for me. the indentation seems wrong, and some declarations are missing.

I took the one I mentioned above, with a working light sensor and modified it a bit. image

The light sensor is working. Occupancy is working, but taking some time to clear.

From the settings - only the Number Sensitivity seem to work, but I haven't yet tested how it affects the behavior.

ts0601_.zip

jbustdel commented 1 year ago

Great!!!!... works for me. But the option controls seems not to do nothing

scotie commented 1 year ago

Could you try this one?

Though I'm a bit skeptical :) ts0601_.zip

jbustdel commented 1 year ago

Its similar. I think options not work yet. Thanks.

peverveer commented 1 year ago

OK, I had some time to play with this yesterday and made some progress. Disclaimer: this is my first-ever attempt using quirks.

@jbustdel, the code you posted doesn't work for me. the indentation seems wrong, and some declarations are missing.

I took the one I mentioned above, with a working light sensor and modified it a bit. image

The light sensor is working. Occupancy is working, but taking some time to clear.

From the settings - only the Number Sensitivity seem to work, but I haven't yet tested how it affects the behavior.

ts0601_.zip

I can confirm that the illuminance and occupency sensors are both working fine for me. For the controls however, I am unsure whether these have any effect currently.

vipial1 commented 1 year ago

Same problem here. With your quirk I can only have occupancy, not illuminance. And even occupancy looks never cleared (waiting for more than 5 minutes in another room).

EDIT: it is finally cleared...it takes 1-3 minutes.

pgroene commented 1 year ago

The motion and light detection works, however the setting do not change anything. There is also distance measuring in the device. I'll check if i can add that.

It takes 7 seconds to clear when i leave the room. It would be nice to set the fading time.

jbustdel commented 1 year ago

I use presence sensor with motion sensor. Its perfect combination. The presence sensor is too sensitive and fire also in other room or when a human pass in front of the door where its instaled. I use to fire the motion sensor and turn off light with presence sensor. Works perfect this way.

pgroene commented 1 year ago

For me this one seems to work oke, I was able to change the setting (range and sensitivity and fading time)

https://github.com/zigpy/zha-device-handlers/issues/2378#issuecomment-1666843526

https://github.com/zigpy/zha-device-handlers/files/12269600/ts0601_qasjif9e.zip

pgroene commented 1 year ago

I use presence sensor with motion sensor. Its perfect combination. The presence sensor is too sensitive and fire also in other room or when a human pass in front of the door where its instaled. I use to fire the motion sensor and turn off light with presence sensor. Works perfect this way.

With the proposed pr you can set the distance and sensitity. I thing you no longer need the motion sensor.

Trikos commented 9 months ago

Hi, all of your devices are the 5.8GHz or 24GHz version? I have a 24GHz and trying to make it works. It is also a ceiling sensor or wall? I have the wall versione Thank you

For me this one seems to work oke, I was able to change the setting (range and sensitivity and fading time)

#2378 (comment)

https://github.com/zigpy/zha-device-handlers/files/12269600/ts0601_qasjif9e.zip

Same problem here. With your quirk I can only have occupancy, not illuminance. And even occupancy looks never cleared (waiting for more than 5 minutes in another room).

EDIT: it is finally cleared...it takes 1-3 minutes.

Trikos commented 9 months ago

OK, I had some time to play with this yesterday and made some progress. Disclaimer: this is my first-ever attempt using quirks.

@jbustdel, the code you posted doesn't work for me. the indentation seems wrong, and some declarations are missing.

I took the one I mentioned above, with a working light sensor and modified it a bit. image

The light sensor is working. Occupancy is working, but taking some time to clear.

From the settings - only the Number Sensitivity seem to work, but I haven't yet tested how it affects the behavior.

ts0601_.zip

I tried using this one and other quoted in this post but the sensors always state as CLEAR

mcanteri commented 8 months ago

Hello, I have two types of that sensor, one ceiling (240v) and one wall mount (5v) and both have the same model number _TZE204_qasjif9e. The ceiling one has both illuminance and presence that works, the wall mount just discovered, only the presence. I am okay for now since the presence is the main purpose of that sensor, but if in the future this quirk will work, I hope it'll be complete. Here is my quirk that works:

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

import math from typing import Dict, Optional, Tuple, Union

from zigpy.profiles import zgp, zha from zigpy.quirks import CustomDevice import zigpy.types as t from zigpy.zcl import foundation from zigpy.zcl.clusters.general import ( AnalogInput, Basic, GreenPowerProxy, Groups, Identify, Ota, Scenes, Time, ) from zigpy.zcl.clusters.measurement import ( IlluminanceMeasurement, OccupancySensing, RelativeHumidity, TemperatureMeasurement, ) from zigpy.zcl.clusters.security import IasZone

from zhaquirks import Bus, LocalDataCluster, MotionOnEvent from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODELS_INFO, MOTION_EVENT, OUTPUT_CLUSTERS, PROFILE_ID, ) from zhaquirks.tuya import ( DPToAttributeMapping, TuyaLocalCluster, TuyaManufCluster, TuyaNewManufCluster, ) from zhaquirks.tuya.mcu import TuyaMCUCluster

ZONE_TYPE = 0x0001

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

class TuyaAnalogInput(AnalogInput, TuyaLocalCluster): """Tuya local AnalogInput cluster."""

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

class TuyaTemperatureMeasurement(TemperatureMeasurement, TuyaLocalCluster): """Tuya local TemperatureMeasurement cluster."""

class TuyaRelativeHumidity(RelativeHumidity, TuyaLocalCluster): """Tuya local RelativeHumidity cluster."""

class NeoBatteryLevel(t.enum8): """NEO battery level enum."""

BATTERY_FULL = 0x00
BATTERY_HIGH = 0x01
BATTERY_MEDIUM = 0x02
BATTERY_LOW = 0x03
USB_POWER = 0x04

class NeoMotionManufCluster(TuyaNewManufCluster): """Neo manufacturer cluster."""

attributes = TuyaNewManufCluster.attributes.copy()
attributes.update(
    {
        0xEF0D: ("dp_113", t.enum8, True),  # ramdom attribute ID
    }
)

dp_to_attribute: Dict[int, DPToAttributeMapping] = {
    101: DPToAttributeMapping(
        TuyaOccupancySensing.ep_attribute,
        "occupancy",
    ),
    104: DPToAttributeMapping(
        TuyaTemperatureMeasurement.ep_attribute,
        "measured_value",
        lambda x: x * 10,
    ),
    105: DPToAttributeMapping(
        TuyaRelativeHumidity.ep_attribute,
        "measured_value",
        lambda x: x * 100,
    ),
    113: DPToAttributeMapping(
        TuyaNewManufCluster.ep_attribute,
        "dp_113",
    ),
}

data_point_handlers = {
    101: "_dp_2_attr_update",
    104: "_dp_2_attr_update",
    105: "_dp_2_attr_update",
    113: "_dp_2_attr_update",
}

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

# # Possible DPs and values
# presence_state: presence
# target distance: 1.61m
# illuminance: 250lux
# sensitivity: 9
# minimum_detection_distance: 0.00m
# maximum_detection_distance: 4.05m
# dp_detection_delay: 0.1
# dp_fading_time: 5.0
# ¿illuminance?: 255lux
# presence_brightness: no control
# no_one_brightness: no control
# current_brightness: off

attributes = TuyaMCUCluster.attributes.copy()
attributes.update(
    {
        # ramdom attribute IDs
        0xEF02: ("dp_2", t.uint32_t, True),
        0xEF03: ("dp_3", t.uint32_t, True),
        0xEF04: ("dp_4", t.uint32_t, True),
        0xEF06: ("dp_6", t.enum8, True),
        0xEF65: ("dp_101", t.uint32_t, True),
        0xEF66: ("dp_102", t.uint32_t, True),
        0xEF67: ("dp_103", t.CharacterString, True),
        0xEF69: ("dp_105", t.enum8, True),
        0xEF6A: ("dp_106", t.enum8, True),
        0xEF6B: ("dp_107", t.enum8, True),
        0xEF6C: ("dp_108", t.uint32_t, True),
    }
)

dp_to_attribute: Dict[int, DPToAttributeMapping] = {
    1: DPToAttributeMapping(
        TuyaOccupancySensing.ep_attribute,
        "occupancy",
    ),
    2: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_2",
    ),
    3: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_3",
    ),
    4: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_4",
    ),
    6: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_6",
    ),
    9: DPToAttributeMapping(
        TuyaAnalogInput.ep_attribute,
        "present_value",
        lambda x: x / 100,
    ),
    101: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_101",
    ),
    102: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_102",
    ),
    103: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_103",
    ),
    104: DPToAttributeMapping(
        TuyaIlluminanceMeasurement.ep_attribute,
        "measured_value",
        lambda x: 10000 * math.log10(x) + 1 if x != 0 else 0,
    ),
    105: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_105",
    ),
    106: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_106",
    ),
    107: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_107",
    ),
    108: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_108",
    ),
}

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

class MotionCluster(LocalDataCluster, MotionOnEvent): """Tuya Motion Sensor."""

_CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Motion_Sensor}
reset_s = 15

class TuyaManufacturerClusterMotion(TuyaManufCluster): """Manufacturer Specific Cluster of the Motion device."""

def handle_cluster_request(
    self,
    hdr: foundation.ZCLHeader,
    args: Tuple[TuyaManufCluster.Command],
    *,
    dst_addressing: Optional[
        Union[t.Addressing.Group, t.Addressing.IEEE, t.Addressing.NWK]
    ] = None,
) -> None:
    """Handle cluster request."""
    tuya_cmd = args[0]
    self.debug("handle_cluster_request--> hdr: %s, args: %s", hdr, args)
    if hdr.command_id == 0x0001 and tuya_cmd.command_id == 1027:
        self.endpoint.device.motion_bus.listener_event(MOTION_EVENT)

class TuyaMotion(CustomDevice): """BW-IS3 occupancy sensor."""

def __init__(self, *args, **kwargs):
    """Init device."""
    self.motion_bus = Bus()
    super().__init__(*args, **kwargs)

signature = {
    #  endpoint=1 profile=260 device_type=0 device_version=0 input_clusters=[0, 3]
    #  output_clusters=[3, 25]>
    MODELS_INFO: [("_TYST11_i5j6ifxj", "5j6ifxj"), ("_TYST11_7hfcudw5", "hfcudw5")],
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
            INPUT_CLUSTERS: [Basic.cluster_id, Identify.cluster_id],
            OUTPUT_CLUSTERS: [Identify.cluster_id, Ota.cluster_id],
        }
    },
}

replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                MotionCluster,
                TuyaManufacturerClusterMotion,
            ],
            OUTPUT_CLUSTERS: [Identify.cluster_id, Ota.cluster_id],
        }
    }
}

class NeoMotion(CustomDevice): """NAS-PD07 occupancy sensor."""

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

replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                NeoMotionManufCluster,
                TuyaOccupancySensing,
                TuyaTemperatureMeasurement,
                TuyaRelativeHumidity,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        }
    }
}

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

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

replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                MmwRadarManufCluster,
                TuyaOccupancySensing,
                TuyaAnalogInput,
                TuyaIlluminanceMeasurement,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
    }
}

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

signature = {
    #  endpoint=1, profile=260, device_type=81, device_version=1,
    #  input_clusters=[4, 5, 61184, 0], output_clusters=[25, 10])
    MODELS_INFO: [
        ("_TZE200_ar0slwnd", "TS0601"),
        ("_TZE200_sfiy5tfs", "TS0601"),
        ("_TZE200_mrf6vtua", "TS0601"),
        ("_TZE204_qasjif9e", "TS0601"),
    ],
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaNewManufCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        242: {
            # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
            # input_clusters=[]
            # output_clusters=[33]
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}

replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                MmwRadarManufCluster,
                TuyaOccupancySensing,
                TuyaAnalogInput,
                TuyaIlluminanceMeasurement,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    }
}

`

MichalLytek commented 6 months ago

I just received a new version of this sensor from Aliexpress. It still reports as TS0601 by _TZE204_qasjif9e but has improved position of light sensor and no LED on top:

image

image

I use the ts0601_qasjif9e.py quirk from this topic and the older version works ok, I have full configuration options, presense and lux sensors.

ts0601_qasjif9e.zip

However, the new version does not report light sensor.

image

I've checked in the "manage zigbee device" and I get the readings that coresponds to physically covering and uncovering the sensor.

image

What has to be changed in the quirk in order to make it work with the new model? The hex of cluster or endpoint id has changed? How to debug that? 🤔

MichalLytek commented 6 months ago

Nevermind, looks like it was detected after a while 😉

image

github-actions[bot] commented 3 weeks ago

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

igorsantos07 commented 3 weeks ago

stale-proof comment