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
753 stars 693 forks source link

[Device Support Request] ZY-M100 #2378

Closed diogo-madeira closed 4 months ago

diogo-madeira commented 1 year ago

Problem description

It apears in HA, but without any sensor.

Solution description

Any

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_sxm7l9xa", "model": "TS0601", "class": "zigpy.device.Device" } ```

Diagnostic information

Diagnostic information ```json { "home_assistant": { "installation_type": "Home Assistant OS", "version": "2023.5.0", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.10.11", "docker": true, "arch": "x86_64", "timezone": "America/Recife", "os_name": "Linux", "os_version": "6.1.25", "supervisor": "2023.04.1", "host_os": "Home Assistant OS 10.1", "docker_version": "23.0.3", "chassis": "vm", "run_as_root": true }, "custom_components": { "sonoff": { "version": "3.5.1", "requirements": [ "pycryptodome>=3.6.6" ] }, "nodered": { "version": "1.2.0", "requirements": [] }, "smartir": { "version": "1.17.6", "requirements": [ "aiofiles==0.6.0" ] }, "powercalc": { "version": "v1.5.1", "requirements": [ "numpy>=1.21.1" ] }, "hacs": { "version": "1.32.1", "requirements": [ "aiogithubapi>=22.10.1" ] }, "thermal_comfort": { "version": "2.1.1", "requirements": [] }, "nuki_ng": { "version": "0.2.1", "requirements": [] }, "ytube_music_player": { "version": "20230321.01", "requirements": [ "ytmusicapi==0.25.0", "pytube==10.5.1", "integrationhelper==0.2.2" ] }, "google_photos": { "version": "v0.5.0", "requirements": [ "google-api-python-client>=2.71.0", "pillow>=9.1.1,<10.0.0" ] }, "ble_monitor": { "version": "11.11.1", "requirements": [ "pycryptodomex>=3.14.1", "janus>=1.0.0", "aioblescan>=0.2.14", "btsocket>=0.2.0", "pyric>=0.1.6.3" ] }, "browser_mod": { "version": "2.2.1", "requirements": [] }, "xiaomi_cloud_map_extractor": { "version": "v2.2.0", "requirements": [ "pillow", "pybase64", "python-miio", "requests", "pycryptodome" ] } }, "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.2", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.99", "zigpy-deconz==0.21.0", "zigpy==0.55.0", "zigpy-xbee==0.18.0", "zigpy-zigate==0.11.0", "zigpy-znp==0.11.1" ], "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": 49103, "manufacturer": "_TZE204_sxm7l9xa", "model": "TS0601", "name": "_TZE204_sxm7l9xa TS0601", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "manufacturer_code": 4417, "power_source": "Mains", "lqi": 98, "rssi": null, "last_seen": "2023-05-04T09:59:08", "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_sxm7l9xa", "model": "TS0601" }, "active_coordinator": false, "entities": [], "neighbors": [], "routes": [], "endpoint_names": [ { "name": "SMART_PLUG" }, { "name": "unknown 97 device_type of 0xa1e0 profile id" } ], "user_given_name": "Radar", "device_reg_id": "147de22f46ce6385a2bf8b83e1363256", "area_id": null, "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_sxm7l9xa" }, "0x0005": { "attribute_name": "model", "value": "TS0601" } }, "unsupported_attributes": {} } }, "out_clusters": { "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} }, "0x000a": { "endpoint_attribute": "time", "attributes": {}, "unsupported_attributes": {} } } }, "242": { "device_type": { "name": "unknown", "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

b2un0 commented 1 year ago

relates to https://github.com/Koenkk/zigbee2mqtt/issues/17483

b2un0 commented 1 year ago
Details

```json { "home_assistant": { "installation_type": "Home Assistant Container", "version": "2023.5.2", "dev": false, "hassio": false, "virtualenv": false, "python_version": "3.10.11", "docker": true, "arch": "aarch64", "timezone": "Europe/Berlin", "os_name": "Linux", "os_version": "6.1.21-v8+", "run_as_root": true }, "custom_components": { "zha_toolkit": { "version": "v0.8.39", "requirements": [ "packaging>=20.8", "pytz" ] }, "xiaomi_miio_fan": { "version": "2022.8.0.0", "requirements": [ "construct==2.10.56", "python-miio>=0.5.12" ] }, "localtuya": { "version": "5.0.0", "requirements": [] }, "avanza_stock": { "version": "1.2.0", "requirements": [ "pyavanza==0.6.0" ] }, "xiaomi_miot": { "version": "0.7.8", "requirements": [ "construct==2.10.56", "python-miio>=0.5.6", "micloud>=0.3" ] }, "hacs": { "version": "1.32.1", "requirements": [ "aiogithubapi>=22.10.1" ] }, "auto_backup": { "version": "1.3.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.2", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.99", "zigpy-deconz==0.21.0", "zigpy==0.55.0", "zigpy-xbee==0.18.0", "zigpy-zigate==0.11.0", "zigpy-znp==0.11.1" ], "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": 37381, "manufacturer": "_TZE204_sxm7l9xa", "model": "TS0601", "name": "_TZE204_sxm7l9xa TS0601", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "manufacturer_code": 4417, "power_source": "Mains", "lqi": 255, "rssi": -31, "last_seen": "2023-05-10T16:50:41", "available": true, "device_type": "Router", "signature": { "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=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_sxm7l9xa", "model": "TS0601" }, "active_coordinator": false, "entities": [], "neighbors": [], "routes": [], "endpoint_names": [ { "name": "SMART_PLUG" }, { "name": "unknown 97 device_type of 0xa1e0 profile id" } ], "user_given_name": null, "device_reg_id": "adde545ae3ac7c4a6087c835d1180281", "area_id": null, "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": { "0x0004": { "attribute_name": "manufacturer", "value": "_TZE204_sxm7l9xa" }, "0x0005": { "attribute_name": "model", "value": "TS0601" } }, "unsupported_attributes": {} } }, "out_clusters": { "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} }, "0x000a": { "endpoint_attribute": "time", "attributes": {}, "unsupported_attributes": {} } } }, "242": { "device_type": { "name": "unknown", "id": 97 }, "profile_id": 41440, "in_clusters": {}, "out_clusters": { "0x0021": { "endpoint_attribute": "green_power", "attributes": {}, "unsupported_attributes": {} } } } } } } ```

Nwk: 0x9205 Pairing Log: home-assistant_zha_2023-05-10T14-48-30.769Z.log

--

the device looks like the same as _TZE204_ztc6ggyl which is available in

https://github.com/zigpy/zha-device-handlers/blob/a221e682e9baffe95588eb6708d096cfc481cd5d/zhaquirks/tuya/ts0601_motion.py#L352

duplicated the ts0601_motion.py to my quirks folder and added the _TZE204_sxm7l9xa under the _TZE204_ztc6ggyl line. But the quirk does not applied. don't know why..

Woll3 commented 1 year ago

Details

Nwk: 0x9205 Pairing Log: home-assistant_zha_2023-05-10T14-48-30.769Z.log

--

the device looks like the same as _TZE204_ztc6ggyl which is available in

https://github.com/zigpy/zha-device-handlers/blob/a221e682e9baffe95588eb6708d096cfc481cd5d/zhaquirks/tuya/ts0601_motion.py#L352

duplicated the ts0601_motion.py to my quirks folder and added the _TZE204_sxm7l9xa under the _TZE204_ztc6ggyl line. But the quirk does not applied. don't know why..

Thanks for the hint! 👍 For me, this doesn't work. I tried the following two quirks:

}, "data": { "ieee": "**REDACTED**", "nwk": 22172, "manufacturer": "_TZE204_sxm7l9xa", "model": "TS0601", "name": "_TZE204_sxm7l9xa TS0601", "quirk_applied": true, "quirk_class": "ts0601_human_presence_sensor.MmwRadarMotion_var03", "manufacturer_code": 4417, "power_source": "Mains", "lqi": 255, "rssi": -70, "last_seen": "2023-05-11T00:01:10", "available": true, "device_type": "Router", "signature": { "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, 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=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": "0x0107", "input_clusters": [ "0x0000", "0x0004", "0x0005", "0x0006", "0x0406", "0xef00" ], "output_clusters": [ "0x000a", "0x0019" ] }, "242": { "profile_id": "0xa1e0", "device_type": "0x0061", "input_clusters": [], "output_clusters": [ "0x0021" ] } }, "manufacturer": "_TZE204_sxm7l9xa", "model": "TS0601" },

programmieramt commented 1 year ago

Hello, I just had the same issues with zigbee2mqtt:

The _TZE204_ztc6ggyl has different "datapoints" then the _TZE204_sxm7l9xa so it is not done with just adding the manufacture id. For z2mqtt you see the differents here: https://github.com/Koenkk/zigbee2mqtt/issues/17483#issuecomment-1547504532

Never worked with quirks but will try to check if possible

programmieramt commented 1 year ago

Here is the description for the datapoints:

104 - Lux 105 - Presence 106 - Motion sensitivity 107 - Max detection distance 108 - Min detection distance 109 - Target distance 110 - Detection delay 111 - Fading time

Woll3 commented 1 year ago
"""ZY-M100 Human Presence Sensor"""
#https://github.com/zigpy/zha-device-handlers/issues/2378

#based on
#"""BlitzWolf IS-3/Tuya motion rechargeable occupancy sensor."""
#https://github.com/zigpy/zha-device-handlers/blob/a221e682e9baffe95588eb6708d096cfc481cd5d/zhaquirks/tuya/ts0601_motion.py#L352

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

from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
import zigpy.types as t
from zigpy.zcl import foundation
from zigpy.zcl.clusters.general import (
    AnalogInput,
    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):
    """ZY-M100 manufacturer cluster."""

    attributes = TuyaMCUCluster.attributes.copy()
    attributes.update(
        {
            0xEF00: ("dp_0", t.CharacterString, True),
            0xEF68: ("dp_104", t.enum8, True),
            0xEF69: ("dp_105", t.enum8, True),
            0xEF6A: ("dp_106", t.enum8, True),
            0xEF6B: ("dp_107", t.uint16_t, True),
            0xEF6C: ("dp_108", t.uint16_t, True),
            0xEF6D: ("dp_109", t.uint16_t, True),
            0xEF6E: ("dp_110", t.uint8_t, True),
            0xEF6F: ("dp_111", t.uint8_t, True),
        }
    )

    dp_to_attribute: Dict[int, DPToAttributeMapping] = {
        104: DPToAttributeMapping(
            TuyaIlluminanceMeasurement.ep_attribute,
            "measured_value",
            lambda x: 10000 * math.log10(x) + 1 if x != 0 else 0,
        ),
        105: DPToAttributeMapping(
            TuyaOccupancySensing.ep_attribute,
            "occupancy",
        ),
        106: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "dp_106",
        ),
        107: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "dp_107",
        ),
        108: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "dp_108",
        ),
        109: DPToAttributeMapping(
            TuyaAnalogInput.ep_attribute,
            "present_value",
            lambda x: x / 100,
        ),
        110: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "dp_110",
        ),
        111: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "dp_111",
        ),
    }

    data_point_handlers = {
        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",
        109: "_dp_2_attr_update",
        110: "_dp_2_attr_update",
        111: "_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 MmwRadarMotionZYM100(CustomDevice):
    """ZY-M100 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: [
            ("_TZE204_sxm7l9xa", "TS0601")
        ],
        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],
            },
        },
    }

    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],
            },
        }
    }

I tried to modify this file but the code is not working. The sensor doesn't use the quirk! Mhh! Where is there error?

programmieramt commented 1 year ago

Did you just added the manufacturer Id? _TZE204_sxm7l9xa I think we have to do a new matching for the datapoints in the new quirk

Woll3 commented 1 year ago

Did you just added the manufacturer Id? _TZE204_sxm7l9xa I think we have to do a new matching for the datapoints in the new quirk

No, I tried to match the data points according to your table above -> https://github.com/zigpy/zha-device-handlers/issues/2378#issuecomment-1548362639

hiscorebob commented 1 year ago

I tried to modify this file but the code is not working. The sensor doesn't use the quirk! Mhh! Where is there error?

Never used a quirk before, this is also new to me. I tried using your quirk, and noticed the Logs get flooded with "unknown cluster command" messages.

dieneuser commented 1 year ago

Did you just added the manufacturer Id? _TZE204_sxm7l9xa I think we have to do a new matching for the datapoints in the new quirk

I can confirm the behavior. The Quirk does not seem to be used: image zha-796e67a077f16237422834223f8280f9-_TZE204_sxm7l9xa TS0601-b56351faae6a353ffd0cbb4ae7e1bb53.json.txt

The following message appears in the logger:

Logger: zigpy.zcl
Source: runner.py:179
First occurred: 13:36:19 (3938 occurrences)
Last logged: 13:54:27

- [0xFFDC:1:0xef00] Unknown cluster command 2 b'\x00\xf4n\x02\x00\x04\x00\x00\x00\x96'
- [0xFFDC:1:0xef00] Unknown cluster command 2 b'\x00\xf5m\x02\x00\x04\x00\x00\x00\x00'
- [0xFFDC:1:0xef00] Unknown cluster command 2 b'\x00\xf6i\x04\x00\x01\x00'
- [0xFFDC:1:0xef00] Unknown cluster command 2 b'\x00\xf7h\x02\x00\x04\x00\x00\x00['
- [0xFFDC:1:0xef00] Unknown cluster command 2 b'\x00\xf8m\x02\x00\x04\x00\x00\x00\x00'
programmieramt commented 1 year ago

I also tried several quirks and stuff but the device doesn’t use them

rofo69 commented 1 year ago

Really not sure which of the many threads about this device to post on, but I've managed to get the ZHA quirk working for me with the basic occupancy sensor and illuminance using this quirk that I put together from various others floating around:-

Its based on the _TZE204_sxm7l9xa variant.

Its basically Wolf's altered quirk above but I've changed the device signature to work with the _TZE204_sxm7l9xa variant.

If anyone can extend it to expose the configuration options that would be amazing.

ts0601_motion.zip

NCC1941 commented 1 year ago

Really not sure which of the many threads about this device to post on, but I've managed to get the ZHA quirk working for me with the basic occupancy sensor and illuminance using this quirk that I put together from various others floating around:-

Its based on the _TZE204_sxm7l9xa variant.

Its basically Wolf's altered quirk above but I've changed the device signature to work with the _TZE204_sxm7l9xa variant.

If anyone can extend it to expose the configuration options that would be amazing.

ts0601_motion.zip

For whatever it's worth, the quirk you've provided didn't work with my _TZE204_sxm7l9xa. Similar result as above with the other quirk(s), my device just doesn't use the quirk.

In case it's relevant, I do also have a _TZE204_ztc6ggyl which I'm using with the other quirk that provides all of the configuration options. That one uses its quirk, and seems to work fine.

programmieramt commented 1 year ago

Really not sure which of the many threads about this device to post on, but I've managed to get the ZHA quirk working for me with the basic occupancy sensor and illuminance using this quirk that I put together from various others floating around:- Its based on the _TZE204_sxm7l9xa variant. Its basically Wolf's altered quirk above but I've changed the device signature to work with the _TZE204_sxm7l9xa variant. If anyone can extend it to expose the configuration options that would be amazing. ts0601_motion.zip

For whatever it's worth, the quirk you've provided didn't work with my _TZE204_sxm7l9xa. Similar result as above with the other quirk(s), my device just doesn't use the quirk.

In case it's relevant, I do also have a _TZE204_ztc6ggyl which I'm using with the other quirk that provides all of the configuration options. That one uses its quirk, and seems to work fine.

Same for me the quirk is not used

rofo69 commented 1 year ago

Can you post the device signature for the _TZE204_ztc6ggyl and your _TZE204_sxm7l9xa and I'll try to see why it's not picking up.

programmieramt commented 1 year ago

Is this everyhting you need?

{
  "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, 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=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_sxm7l9xa",
  "model": "TS0601",
  "class": "zigpy.device.Device"
}

Edit: I dont know why it is not formatted Edit2: Now with the right signature @rofo69

rofo69 commented 1 year ago

Go to the device in zha click the the dots next to the reconfigure button. Then choose manage zigbee device then click signature and paste those for both your devices.

I have the _TZE204_sxm7l9xa working again. I must have broken something in the file I posted. I will upload in about an hour or so. I am away from my pc atm.

rofo69 commented 1 year ago

Can you also post the sig for _TZE204_ztc6ggyl

programmieramt commented 1 year ago

Can you also post the sig for _TZE204_ztc6ggyl

Here. This device works and also exposes the config values to the fronted

{
  "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *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": "0x0107",
      "input_clusters": [
        "0x0000",
        "0x0004",
        "0x0005",
        "0x000c",
        "0x000d",
        "0x0400",
        "0x0406",
        "0xef00"
      ],
      "output_clusters": [
        "0x000a",
        "0x0019"
      ]
    },
    "2": {
      "profile_id": "0x0104",
      "device_type": "0x0007",
      "input_clusters": [
        "0x000d"
      ],
      "output_clusters": []
    },
    "3": {
      "profile_id": "0x0104",
      "device_type": "0x0007",
      "input_clusters": [
        "0x000d"
      ],
      "output_clusters": []
    },
    "4": {
      "profile_id": "0x0104",
      "device_type": "0x0007",
      "input_clusters": [
        "0x000d"
      ],
      "output_clusters": []
    },
    "5": {
      "profile_id": "0x0104",
      "device_type": "0x0007",
      "input_clusters": [
        "0x000d"
      ],
      "output_clusters": []
    }
  },
  "manufacturer": "_TZE204_ztc6ggyl",
  "model": "TS0601",
  "class": "presence_new.TuyaMmwRadarOccupancy"
}
rofo69 commented 1 year ago

Could you unload your working quirk on _TZE204_ztc6ggyl then reload HA and show me what the sig looks like without the quirk loaded. Then you can put it back again.

rofo69 commented 1 year ago

I'll post my working basic quirk for _TZE204_sxm7l9xa in about 45 minutes when I am back.

programmieramt commented 1 year ago

Could you unload your working quirk on _TZE204_ztc6ggyl then reload HA and show me what the sig looks like without the quirk loaded. Then you can put it back again.

{
{
  "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *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": "0x0107",
      "input_clusters": [
        "0x0000",
        "0x0004",
        "0x0005",
        "0x000c",
        "0x0400",
        "0x0406",
        "0xef00"
      ],
      "output_clusters": [
        "0x000a",
        "0x0019"
      ]
    }
  },
  "manufacturer": "_TZE204_ztc6ggyl",
  "model": "TS0601",
  "class": "zhaquirks.tuya.ts0601_motion.MmwRadarMotion"
}

This is the signature without the quirk. But without the quirk it does not exposed the config to HA

rofo69 commented 1 year ago

Thats fine, i just wanted to compare both against _TZE204_sxm7l9xa, as I'm no quirk expert.

Here is the correct quirk that gives at least some functionality. I've also corrected the original link above.

ts0601_motion.zip

I'll see if i can figure out how to expose the config entries.

programmieramt commented 1 year ago

Thats fine, i just wanted to compare both against _TZE204_sxm7l9xa, as I'm no quirk expert.

Here is the correct quirk that gives at least some functionality. I've also corrected the original link above.

ts0601_motion.zip

I'll see if i can figure out how to expose the config entries.

Great. Looks good. The occupancy sensor is now exposed. Thank you


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

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

from zhaquirks import Bus, LocalDataCluster, MotionOnEvent
from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODEL,
    MOTION_EVENT,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)

from zhaquirks.tuya import (
    NoManufacturerCluster,
    TuyaLocalCluster,
    TuyaNewManufCluster,
)
from zhaquirks.tuya.mcu import (
    # TuyaDPType,
    DPToAttributeMapping,
    TuyaAttributesCluster,
    TuyaMCUCluster,
)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

This is the quirk which exposes the config

rofo69 commented 1 year ago

Ok, I've started working through modifying the quirks I have and am getting close:

image

But the logs are throwing some errors that I need to chase down.

rofo69 commented 1 year ago

Ok, through a fair bit of trial and error, I think I have a working quirk with config options. I can't get detection distance as a sensor working yet, but I might have a go.

I think you might need that sensor working for the min and max range config options to work (I'm guessing).

modded_ts0601_motion.zip

programmieramt commented 1 year ago

Ok, through a fair bit of trial and error, I think I have a working quirk with config options. I can't get detection distance as a sensor working yet, but I might have a go.

I think you might need that sensor working for the min and max range config options to work (I'm guessing).

modded_ts0601_motion.zip

For me looks good. I am not sure if the value are used but I can configure it

rofo69 commented 1 year ago

If you could test the settings, let me know if they seem to be effective.

diogo-madeira commented 1 year ago

Ok, through a fair bit of trial and error, I think I have a working quirk with config options. I can't get detection distance as a sensor working yet, but I might have a go.

I think you might need that sensor working for the min and max range config options to work (I'm guessing).

modded_ts0601_motion.zip

I tried this quirk.... I can see all options, the illuminance sensor works, but the Occupancy sensor is not working....

Edit: After 5 minutes it starts to work.... I'll test if it's working right.

rofo69 commented 1 year ago

Looks like there are some more tweaks to do. The detected distance appears to be coming in meters:- image

But the min and max are in cms, so that needs to be standardised:

image

rofo69 commented 1 year ago

Ok, having tested this device at home, whilst the illuminance and motion appear to work, I am utterly unconvinced the configuration settings don't work at all. I'm going to have to do some more digging or someone else can pick up what I have and fix/improve it.

rofo69 commented 1 year ago

I'm leaving my last effort here with a few more corrections. Sadly I still can't get the configs when set in the UI, to apply to the device.

final_try.zip

Woll3 commented 1 year ago

Ok, through a fair bit of trial and error, I think I have a working quirk with config options. I can't get detection distance as a sensor working yet, but I might have a go. I think you might need that sensor working for the min and max range config options to work (I'm guessing). modded_ts0601_motion.zip

For me looks good. I am not sure if the value are used but I can configure it

I tried the quirk but it doesn't work for me! The log file is attached! The controls and sensors are unavailable.

zha-1195eddb0211698aa461dee2b7b8c968-_TZE204_sxm7l9xa TS0601-da8eb788a12c5cd05d5447065f7d1059.json.txt

rofo69 commented 1 year ago

Are you using the _TZE204_sxm7l9xa variant ? Have you cleared your pycache folder ?

As I say... its 'works', but the config entities dont seem to set on the device, but the motion and illuminance sensors do work.

NCC1941 commented 1 year ago

I've just loaded up the final_try quirk, and can confirm that it works for me, in that the Occupancy and Illuminance sensors both seem to work (Illuminance is giving values several times higher than I get from other sensors nearby, but that could just be a placement issue, or other sensor variance), and the config options exist.

Haven't attempted to change any of the config settings yet, but honestly I'm just glad to have the sensors working at all. Thank you for your work.

Edit: Just tried changing the max range, and yep, doesn't work here either.

programmieramt commented 1 year ago

I'm leaving my last effort here with a few more corrections. Sadly I still can't get the configs when set in the UI, to apply to the device. I think it might be to do with adding the updates to the UI bus, but I'm guessing at this point.

final_try.zip

Thanks for your effort. At least it is working.

hiscorebob commented 1 year ago

I'm leaving my last effort here with a few more corrections. Sadly I still can't get the configs when set in the UI, to apply to the device. I think it might be to do with adding the updates to the UI bus, but I'm guessing at this point.

final_try.zip

Thank you! Presence Sensors are working now!

backcountrymountains commented 1 year ago

Thanks for this! It got my _TZE204_sxm7l9xa working!

I can get it to work for Occupancy but I don't get any sensors for Target Distance or Illumination: image

What is the magic incantation to get ZHA to add those sensors? I can manually read the TuyaIlluminationMeasurement:measured_value image and TuyaMmwRadarTargetDistance:present_value attributes image using the Manage Zigbee Device menu, but the entities aren't created by ZHA in HA for me to look at.

What do I do?!?!?!

Thanks!

HA 2023.6.0 HUSUZB-1 Quirk: tuya.tuya_sxm_motion.MmwRadarMotionZYM100 (I renamed it, but it's final_try.py)

Woll3 commented 1 year ago

Are you using the _TZE204_sxm7l9xa variant ? Have you cleared your pycache folder ?

As I say... its 'works', but the config entities dont seem to set on the device, but the motion and illuminance sensors do work.

Screenshot 2023-06-08 143744

How do I clear the pycache folder? Thanks! 😊

wishie commented 1 year ago

Occupancy and Illuminance both appear. Illuminance work fine, but my occupancy entity seems to never change back from "Detected" once its been triggered.

rofo69 commented 1 year ago

The quirk I hacked together here:-

https://github.com/zigpy/zha-device-handlers/files/11547413/final_try.zip

Has a working illuminance and occupancy sensor, you can see the occupancy triggering on and off in this screenshot:

image

I've never been able to get the config items to correctly work and hope someone with more knowledge than I can fix/amend/re-do my attempt to get it the _TZE204_sxm7l9xa variant fully working with ZHA.

To answer the question above, to clear your pycache folder the easiest thing to do is install either a terminal addon, or a samba share addon and access the file system and delete the files in that pycache folder. The pycache folder is located under your cutom_zha_quirks folder.

Go to system -> Addons and search for either. I use Samba as its easier for me to just see the files via windows on my network.

Milkaschoko commented 1 year ago

Hello, I have the same motion sensor mounted outside and I also see the sensors and controllers. At night it seems to work but during the day it is detected most of the time. Have covered the sensor with a cloth so that the brightness does not always show 2000lux (currently 254 lux) but it almost always shows occupied no matter how sensitive I set.

Screenshot_20230620_163320_Home Assistant

rofo69 commented 1 year ago

I only use the lux setting when its very low, to turn on a light in a room. For this use case, the sensor seems to work correctly.

As for putting the motion sensor outside, the mmwave type sensors are so sensitive, they will trigger on the slightest movement, so if there are any trees, leaves etc moving, its likely to trigger them. They really aren't designed for outdoor use. Perhaps a camera or PIR sensor would be a better candidate for you, depending on what you're trying to do.

As for the sensitivity setting, As I mentioned earlier in the thread, I'm not convinced that any of the settings are working correctly. I basically put together the quirk above by pasting together some others. Its now beyond my expertise to figure out what needs to be done.

Although I suspect, if any of the settings work, it is infact sensitivity, but I can't be certain of that.

Milkaschoko commented 1 year ago

I have now tried a few more, I can set the max-range and the value is taken over. Min-range unfortunately can not be adjusted, it comes an error message. Even if I set the min value in the Quirks to 300, the value is not taken over. image

Njamotep commented 1 year ago

@rofo69 Thank you so much for the work you put into this. One question, and it's not really that important: I see in your screenshots that you have illuminance sensor working on _TZE204_sxm7l9xa, but mine doesn't seem to work. What could be wrong? Have cleared pycache and installed from scratch several times. Using the final_try.py .TIA!

Njamotep commented 1 year ago

Nvm, like the 20th time I removed and re-paired the device it suddenly showed up! Thanks again!!

Riddlr commented 1 year ago

Hi All, Here is what I use, seems to work okay. TS0601s.zip

rofo69 commented 1 year ago

I think the configs might be working with the file @Riddlr has posted. I've not tested them all so far (see update below), but I think min and max range do work. (Although I think if max range is zero, its ignore and you still get detection).

I've noticed that the file seems to have alot of weird space characters in the blank lines, and at the end of the lines. I don't think it affects the quirk at all, but I purged them using this tool:

https://www.gillmeister-software.com/online-tools/text/trim_lines-remove_spaces.aspx

UPDATE:- Configs look good. Some notes:-

Detection delay: I think anything above 2000 makes the sensor highly unresponsive. Min/Max ranges do work, but they aren't accurate. I can set max range to say 10cms, but it still triggers at about 50. Not a huge deal, but be aware if you are using a measuring tape to work out your distances. Max Range: I think zero counts as unlimited. I've tweaked my quirk to allow a minimum max range of 10. Sensitivity: Very difficult to test, and short ranges (under a meter), seems to make no difference. Fading Time: Quirk allows this to be set to a value under 2000, which the device does not like. (it springs back to 2000), but otherwise, works fine. I've teaked my quirk to have a minimum allowed value of 2000. Please also note that having fading time working is a huge deal as the device is no longer spamming my zigbee network every 2 seconds.

My very minor edits, plus white space removal are in the file below.

Note that for some reason, after the quirk is loaded, you often have to restart HA again to get the illuminance sensor to appear.

ts0601_motion.zip

Njamotep commented 1 year ago

Fantastic! Works great for my usecase with the improved quirk! Thanks @rofo69 and @Riddlr !

Goodie01 commented 1 year ago

Without wanting to be impatient... but being a little impatient; how far away is this from release and/or how would one go about adding it manually?