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
712 stars 660 forks source link

[Device Support Request] linptech Human Presence Sensor #2599

Open seanhagen opened 11 months ago

seanhagen commented 11 months ago

Problem description

Request to add support for the linptech Human Presence Sensor ( aka Moes Human Presence Sensor -- might be a rebrand of the linptech )

It looks like folks in this thread are getting close to having it working in zigbee2mqtt.

Solution description

Integration into ZHA or zha_quirk to get the device working in HA.

Screenshots/Video

No response

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=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)", "endpoints": { "1": { "profile_id": "0x0104", "device_type": "0x0402", "input_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0500", "0x4000", "0xe002", "0xef00" ], "output_clusters": [ "0x000a", "0x0019" ] } }, "manufacturer": "_TZ3218_awarhusb", "model": "TS0225", "class": "zigpy.device.Device" } ```

Diagnostic information

Diagnostic information ```json { "home_assistant": { "installation_type": "Home Assistant OS", "version": "2023.9.2", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.11.5", "docker": true, "arch": "aarch64", "timezone": "America/Vancouver", "os_name": "Linux", "os_version": "6.1.21-v8", "supervisor": "2023.09.2", "host_os": "Home Assistant OS 10.5", "docker_version": "23.0.6", "chassis": "embedded", "run_as_root": true }, "custom_components": { "plex_recently_added": { "version": "0.3.8", "requirements": [] }, "browser_mod": { "version": "2.3.0", "requirements": [] }, "radarr_upcoming_media": { "version": "0.3.6", "requirements": [] }, "holidays": { "version": "1.9.6", "requirements": [ "python-dateutil>=2.8.2", "holidays>=0.14.2" ] }, "truenas": { "version": "0.0.0", "requirements": [] }, "ble_monitor": { "version": "12.4.0", "requirements": [ "pycryptodomex>=3.14.1", "janus>=1.0.0", "aioblescan>=0.2.14", "btsocket>=0.2.0", "pyric>=0.1.6.3" ] }, "waste_collection_schedule": { "version": "1.42.0", "requirements": [ "icalendar", "recurring_ical_events", "icalevents", "bs4" ] }, "mail_and_packages": { "version": "0.3.18", "requirements": [ "beautifulsoup4", "Pillow>=9.0" ] }, "pfsense": { "version": "0.1.0", "requirements": [ "mac-vendor-lookup>=0.1.11" ] }, "adaptive_lighting": { "version": "1.19.0", "requirements": [ "ulid-transform" ] }, "schedule_state": { "version": "0.18.1", "requirements": [ "portion==2.3.0" ] }, "sonarr_upcoming_media": { "version": "0.2.7", "requirements": [] }, "alarmo": { "version": "v1.9.10", "requirements": [] }, "babybuddy": { "version": "v0.0.0", "requirements": [] }, "hacs": { "version": "1.32.1", "requirements": [ "aiogithubapi>=22.10.1" ] }, "grocy": { "version": "v4.11.1", "requirements": [ "pygrocy==2.0.0" ] }, "multiscrape": { "version": "6.5.0", "requirements": [ "lxml==4.9.1", "beautifulsoup4==4.11.1" ] }, "scheduler": { "version": "v0.0.0", "requirements": [] }, "garbage_collection": { "version": "3.21", "requirements": [ "python-dateutil>=2.8.2" ] }, "ics_calendar": { "version": "3.1.8", "requirements": [ "ics>=0.7.2", "recurring_ical_events>=2.0.2", "icalendar>=5.0.4" ] }, "keymaster": { "version": "v0.0.85", "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", "universal_silabs_flasher" ], "requirements": [ "bellows==0.36.3", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.103", "zigpy-deconz==0.21.1", "zigpy==0.57.1", "zigpy-xbee==0.18.2", "zigpy-zigate==0.11.0", "zigpy-znp==0.11.4", "universal-silabs-flasher==0.0.13" ], "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": "_uzg-01._tcp.local.", "name": "uzg-01*" }, { "type": "_slzb-06._tcp.local.", "name": "slzb-06*" } ], "is_built_in": true }, "data": { "ieee": "**REDACTED**", "nwk": 48475, "manufacturer": "_TZ3218_awarhusb", "model": "TS0225", "name": "_TZ3218_awarhusb TS0225", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "manufacturer_code": 4098, "power_source": "Mains", "lqi": 116, "rssi": -71, "last_seen": "2023-09-20T15:30:32", "available": true, "device_type": "Router", "signature": { "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)", "endpoints": { "1": { "profile_id": "0x0104", "device_type": "0x0402", "input_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0500", "0x4000", "0xe002", "0xef00" ], "output_clusters": [ "0x000a", "0x0019" ] } }, "manufacturer": "_TZ3218_awarhusb", "model": "TS0225" }, "active_coordinator": false, "entities": [ { "entity_id": "binary_sensor.linptech_presence_sensor_iaszone", "name": "_TZ3218_awarhusb TS0225" }, { "entity_id": "button.linptech_presence_sensor_identify", "name": "_TZ3218_awarhusb TS0225" } ], "neighbors": [], "routes": [], "endpoint_names": [ { "name": "IAS_ZONE" } ], "user_given_name": "linptech Presence Sensor", "device_reg_id": "c6d51d3b072fca36eaef7e77eeb12ded", "area_id": null, "cluster_details": { "1": { "device_type": { "name": "IAS_ZONE", "id": 1026 }, "profile_id": 260, "in_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0004": { "attribute_name": "manufacturer", "value": "_TZ3218_awarhusb" }, "0x0005": { "attribute_name": "model", "value": "TS0225" } }, "unsupported_attributes": {} }, "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0xe002": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} }, "0x4000": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} }, "0xef00": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} }, "0x0500": { "endpoint_attribute": "ias_zone", "attributes": { "0x0010": { "attribute_name": "cie_addr", "value": [ 52, 66, 7, 255, 255, 46, 33, 0 ] }, "0x0000": { "attribute_name": "zone_state", "value": 0 }, "0x0002": { "attribute_name": "zone_status", "value": 1 }, "0x0001": { "attribute_name": "zone_type", "value": 32771 } }, "unsupported_attributes": {} } }, "out_clusters": { "0x000a": { "endpoint_attribute": "time", "attributes": {}, "unsupported_attributes": {} }, "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} } } } } } } ```

Logs

No response

Custom quirk

No response

Additional information

No response

betimmm commented 11 months ago

Same need here, can anyone help?

judahrand commented 10 months ago

This seems to be working in z2mqtt, I believe. I've had a play with trying to write a custom quirk but I'm not really sure what I'm doing! If anyone is willing/able to help I'd appreciate it!

felafel commented 9 months ago

This seems to be working in z2mqtt, I believe. I've had a play with trying to write a custom quirk but I'm not really sure what I'm doing! If anyone is willing/able to help I'd appreciate it!

I have only today learned about ZHA quirks. If you would like someone to test it let me know. Thanks

maelremrem commented 9 months ago

Got mine today, and I only have the occupancy working. Can someone help me to write an ZHA quirk ?

felafel commented 9 months ago

I tried to use a different quirk that is similar and change it to accept this model. That did not work for me. I am going to look into Zigbee2MQTT but not sure if it works with SkyConnect.

cbarth3 commented 9 months ago

Picked one of these up. If I can help in some way to get it working with zha let me know

felafel commented 9 months ago

Picked one of these up. If I can help in some way to get it working with zha let me know

I would say that writing a quirk for it would be great.

danielgomezrico commented 9 months ago

@felafel can you open a PR with that code? Opening that may show what code did you add to get some advice

felafel commented 9 months ago

I am not sure if this is helpful but here is what I have. I do not know why it is not being picked up and I have not found a way to see if the quirk is being attempted. I set up the settings I have seen in the YAML file but whether it is being used is a mystery. It would be helpful if ZHA could confirm that it is looking for quirks in my folder, and also, whether it cannot use files that are there for whatever reason. If there is a file there then ZHA should assume I want to use it, I think.

`"""Device handler for Tuya ZG-205Z-A Mini 24Ghz human presence sensor."""

import math from typing import Dict, Optional, Tuple, Union from zigpy.profiles import zgp, zha from zigpy.profiles.zha import DeviceType from zigpy.quirks import CustomCluster, CustomDevice import zigpy.types as t from zigpy.zcl import foundation

from zigpy.zcl.clusters.general import Basic, Identify, Ota, GreenPowerProxy, AnalogOutput from zigpy.zcl.clusters.security import IasZone from zigpy.zcl.clusters.measurement import ( IlluminanceMeasurement, OccupancySensing, )

from zhaquirks import MotionWithReset from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODELS_INFO, OUTPUT_CLUSTERS, PROFILE_ID, ) from zhaquirks.tuya import TuyaLocalCluster, TuyaManufCluster, TuyaNewManufCluster, TuyaZBE000Cluster from zhaquirks.tuya.mcu import ( DPToAttributeMapping, TuyaAttributesCluster, TuyaMCUCluster, )

class MotionCluster(MotionWithReset): """Motion cluster."""

reset_s: int = 60

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

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

def __init__(self, *args, **kwargs):
    """Init."""
    super().__init__(*args, **kwargs)
    self._update_attribute(self.attributes_by_name["description"].id, "Fading time")
    self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
    self._update_attribute(self.attributes_by_name["max_present_value"].id, 600)
    self._update_attribute(self.attributes_by_name["resolution"].id, 1)
    self._update_attribute(
        self.attributes_by_name["engineering_units"].id, 73
    )

class TuyaMmwRadarLargeMotionDetectionSensitivity(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for Large motion detection sensitivity."""

def __init__(self, *args, **kwargs):
    """Init."""
    super().__init__(*args, **kwargs)
    self._update_attribute(self.attributes_by_name["description"].id, "Large motion sensitivity")
    self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
    self._update_attribute(self.attributes_by_name["max_present_value"].id, 10)
    self._update_attribute(self.attributes_by_name["resolution"].id, 1)

class TuyaMmwRadarLargeMotionDetectionDistance(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for Large motion detection distance."""

def __init__(self, *args, **kwargs):
    """Init."""
    super().__init__(*args, **kwargs)
    self._update_attribute(self.attributes_by_name["description"].id, "Large motion detection distance")
    self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
    self._update_attribute(self.attributes_by_name["max_present_value"].id, 1000)
    self._update_attribute(self.attributes_by_name["resolution"].id, 10)
    self._update_attribute(
        self.attributes_by_name["engineering_units"].id, 118
    )

class TuyaMmwRadarSmallMotionDetectionSensitivity(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for Small motion detection sensitivity."""

def __init__(self, *args, **kwargs):
    """Init."""
    super().__init__(*args, **kwargs)
    self._update_attribute(self.attributes_by_name["description"].id, "Small motion sensitivity")
    self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
    self._update_attribute(self.attributes_by_name["max_present_value"].id, 10)
    self._update_attribute(self.attributes_by_name["resolution"].id, 1)

class TuyaMmwRadarSmallMotionDetectionDistance(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for Small motion detection distance."""

def __init__(self, *args, **kwargs):
    """Init."""
    super().__init__(*args, **kwargs)
    self._update_attribute(self.attributes_by_name["description"].id, "Small motion detection distance")
    self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
    self._update_attribute(self.attributes_by_name["max_present_value"].id, 600)
    self._update_attribute(self.attributes_by_name["resolution"].id, 10)
    self._update_attribute(
        self.attributes_by_name["engineering_units"].id, 118
    )

class TuyaMmwRadarStaticMotionDetectionSensitivity(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for Static motion detection sensitivity."""

def __init__(self, *args, **kwargs):
    """Init."""
    super().__init__(*args, **kwargs)
    self._update_attribute(self.attributes_by_name["description"].id, "Static motion sensitivity")
    self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
    self._update_attribute(self.attributes_by_name["max_present_value"].id, 10)
    self._update_attribute(self.attributes_by_name["resolution"].id, 1)

class TuyaMmwRadarStaticMotionDetectionDistance(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for Static motion detection distance."""

def __init__(self, *args, **kwargs):
    """Init."""
    super().__init__(*args, **kwargs)
    self._update_attribute(self.attributes_by_name["description"].id, "Static motion detection distance")
    self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
    self._update_attribute(self.attributes_by_name["max_present_value"].id, 600)
    self._update_attribute(self.attributes_by_name["resolution"].id, 10)
    self._update_attribute(self.attributes_by_name["engineering_units"].id, 118)

class MmwRadarManufCluster(TuyaMCUCluster): """Tuya ZG-205Z-A Mini 24Ghz human presence sensor cluster."""

attributes = TuyaMCUCluster.attributes.copy()
attributes.update(
    {
        # ramdom attribute IDs
        #0xEF02: ("motion_detection_sensitivity", t.uint32_t, True),
        0xEF03: ("mov_minimum_distance", t.uint32_t, True),
        #0xEF04: ("motion_detection_distance", t.uint32_t, True),
        0xEF05: ("human_motion_state", t.enum8, True),
        #0xEF65: ("fading_time", t.uint32_t, True),
        0xEF66: ("motion_false_detection", t.uint32_t, True),
        #0xEF67: ("small_motion_detection_distance", t.uint32_t, True),
        #0xEF69: ("small_motion_detection_sensitivity", t.uint32_t, True),
        0xEF6A: ("illuminance_value", t.uint32_t, True),
        0xEF6B: ("indicator", t.enum8, True),
        #0xEF6C: ("static_detection_distance", t.uint32_t, True),
        #0xEF06: ("static_detection_sensitivity", t.uint32_t, True),
        0xEF07: ("micro_minimum_distance", t.uint32_t, True),
        0xEF08: ("motionless_minimum_distance", t.uint32_t, True),
        0xEF09: ("reset_setting", t.uint32_t, True),
        0xEF0A: ("breathe_false_detection", t.uint32_t, True),
        0xEF0B: ("time", t.uint32_t, True),
        0xEF0C: ("alarm_time", t.uint32_t, True),
        0xEF0D: ("alarm_volume", t.enum8, True),
        0xEF0E: ("working_mode", t.enum8, True),
        0xEF0F: ("auto1", t.uint32_t, True),
        0xEF10: ("auto2", t.uint32_t, True),
        0xEF11: ("auto3", t.uint32_t, True),
    }
)

dp_to_attribute: Dict[int, DPToAttributeMapping] = {
    1: DPToAttributeMapping(
        TuyaOccupancySensing.ep_attribute,
        "occupancy",
    ),
    2: DPToAttributeMapping(
        TuyaMmwRadarLargeMotionDetectionSensitivity.ep_attribute,
        "present_value",
    ),
    3: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "mov_minimum_distance",
    ),
    4: DPToAttributeMapping(
        TuyaMmwRadarLargeMotionDetectionDistance.ep_attribute,
        "present_value",
    ),
    101: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "human_motion_state",
    ),
    102: DPToAttributeMapping(
        TuyaMmwRadarFadingTime.ep_attribute,
        "present_value",
    ),
    103: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "motion_false_detection",
    ),
    104: DPToAttributeMapping(
        TuyaMmwRadarSmallMotionDetectionDistance.ep_attribute,
        "present_value",
    ),
    105: DPToAttributeMapping(
        TuyaMmwRadarSmallMotionDetectionSensitivity.ep_attribute,
        "present_value",
    ),
    106: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "illuminance_value",
    ),
    107: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "indicator",
    ),
    108: DPToAttributeMapping(
        TuyaMmwRadarStaticMotionDetectionDistance.ep_attribute,
        "present_value",
    ),
    109: DPToAttributeMapping(
        TuyaMmwRadarStaticMotionDetectionSensitivity.ep_attribute,
        "present_value",
    ),
    110: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "micro_minimum_distance",
    ),
    111: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "motionless_minimum_distance",
    ),
    112: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "reset_setting",
    ),
    113: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "breathe_false_detection",
    ),
    114: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "time",
    ),
    115: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "alarm_time",
    ),
    116: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "alarm_volume",
    ),
    117: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "working_mode",
    ),
    118: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "auto1",
    ),
    119: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "auto2",
    ),
    120: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "auto3",
    ),
}

data_point_handlers = {
    1: "_dp_2_attr_update",
    2: "_dp_2_attr_update",
    3: "_dp_2_attr_update",
    4: "_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",
    109: "_dp_2_attr_update",
    110: "_dp_2_attr_update",
    111: "_dp_2_attr_update",
    112: "_dp_2_attr_update",
    113: "_dp_2_attr_update",
    114: "_dp_2_attr_update",
    115: "_dp_2_attr_update",
    116: "_dp_2_attr_update",
    117: "_dp_2_attr_update",
    118: "_dp_2_attr_update",
    119: "_dp_2_attr_update",
    120: "_dp_2_attr_update",
}

class TS0225Radar(CustomDevice): """Quirk for Tuya ZG-205Z-A Mini 24Ghz human presence sensor."""

note: Changed _TZE200_2aaelwxk to _TZ3218_awarhusb. Both appear to be model TS0225

signature = {
    #  endpoint=1, profile=260, device_type=1026, device_version=1,
    #  input_clusters=["0x0000", "0x0003", "0x0400", "0x0500","0xe000","0xe002", "0xee00", "0xef00"], output_clusters=[])
    MODELS_INFO: [("_TZ3218_awarhusb", "TS0225")],
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                IlluminanceMeasurement.cluster_id,
                IasZone.cluster_id,
                TuyaZBE000Cluster.cluster_id,
                0xE002, # Unknown
                0xEE00, # Unknown
                TuyaNewManufCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [],
        },
        242: {
            # "profile_id": "0xA1E0", "device_type": "0x0061",
            # "in_clusters": [], "out_clusters": ["0x0021"]
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}
replacement = {
    ENDPOINTS: {
        1: {
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                IlluminanceMeasurement.cluster_id,
                MotionCluster,
                TuyaZBE000Cluster,
                MmwRadarManufCluster,
                TuyaOccupancySensing,

            ],
            OUTPUT_CLUSTERS: [],
        },
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
            INPUT_CLUSTERS: [
                TuyaMmwRadarFadingTime,
            ],
            OUTPUT_CLUSTERS: [],
        },
        3: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
            INPUT_CLUSTERS: [
                TuyaMmwRadarLargeMotionDetectionSensitivity,
            ],
            OUTPUT_CLUSTERS: [],
        },
        4: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
            INPUT_CLUSTERS: [
                TuyaMmwRadarLargeMotionDetectionDistance,
            ],
            OUTPUT_CLUSTERS: [],
        },
        5: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
            INPUT_CLUSTERS: [
                TuyaMmwRadarSmallMotionDetectionSensitivity,
            ],
            OUTPUT_CLUSTERS: [],
        },
        6: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
            INPUT_CLUSTERS: [
                TuyaMmwRadarSmallMotionDetectionDistance,
            ],
            OUTPUT_CLUSTERS: [],
        },
        7: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
            INPUT_CLUSTERS: [
                TuyaMmwRadarStaticMotionDetectionSensitivity,
            ],
            OUTPUT_CLUSTERS: [],
        },
        8: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
            INPUT_CLUSTERS: [
                TuyaMmwRadarStaticMotionDetectionDistance,
            ],
            OUTPUT_CLUSTERS: [],
        },
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}`
felafel commented 9 months ago

Does @danielgomezrico or anyone else have constructive help with the code above?

danielgomezrico commented 9 months ago

I was a bit out of clues about how to build this one, but I want to try

kaiserkiwi commented 9 months ago

Bought some of these because they were recommended. Sadly the person that recommended it didn't know about ZHA support (he said it works out of the box, but he meant Z2MQTT.

Any news on this?

mroony commented 8 months ago

I did the same and too have no clue on how to make it better.

kaiserkiwi commented 8 months ago

According to blakkadder the device seems to work already. I don't have the opportunity to test it right now, so any updates on this?

See https://zigbee.blakadder.com/Linptech_ES1.html

felafel commented 8 months ago

According to blakkadder the device seems to work already. I don't have the opportunity to test it right now, so any updates on this?

See https://zigbee.blakadder.com/Linptech_ES1.html

There is an attempted ZHA Quirk above to get the other features to work. Presence itself appears to be in ZHA but the other features do not. Do you have any suggestions on getting the quirk to work?

kaiserkiwi commented 8 months ago

I sadly have no experience in Python or ZHA quirks. So I'm just here to ask. 😅

When I use it the way it works now and someone writes a quirk does it automatically work or do I have to re-pair it?

felafel commented 7 months ago

I might just go with Zigbee2MQTT. This is crazy that no-one can fix this. ZHA should just deprecate if it cannot keep up with an alternative that seems more feature rich. My concern was that SkyConnect would not work but I think it does now so hopefully it does and I can just get my devices to be fully utilised.

dmulcahey commented 7 months ago

@felafel i understand you may be frustrated but everyone working on these things are volunteers. This isn’t the appropriate place to vent.

kaiserkiwi commented 7 months ago

I think it's fair to point out that the official implementation is much worse in many points than a community alternative. The wrong place to vent? Definitely. But he is right in my opinion.

I'm really frustrated too. Tried to switch ti Zigbee2MQTT, failed and now are trapped in this.

I really wish that ZHA would get much more attention. Not only for Device support.

dmulcahey commented 7 months ago

I think it's fair to point out that the official implementation is much worse in many points than a community alternative. The wrong place to vent? Definitely. But he is right in my opinion.

I'm really frustrated too. Tried to switch ti Zigbee2MQTT, failed and now are trapped in this.

I really wish that ZHA would get much more attention. Not only for Device support.

What am I missing? All of this is FREE and done by folks in their spare time… ZHA came from the community and is largely maintained by community members… no one forces anyone to use it. everything here in this repo is from the community. The problem is with device manufacturers… they basically do what they want.

Tbh, being frustrated is perfectly normal and acceptable but dumping it on folks who put a lot of effort into this in their free time is just not right. Try to look at the situation from the opposite perspective and imagine how you would feel.

kineticscreen commented 7 months ago

I think my frustration is certainly less about the work of the volunteers, which as you say is entirely supported by the community, and more that I listened to Home Assistant when they announced ZHA as the native support for Zigbee. I was at the time on Zigbee2MQTT and changed over thinking that I was moving to the more stable / supported platform. Since then it's consistently lagged in features and support. For example, at the time I already had OTA updates presented nicely in the UI for Z2M, years late ZHA still handles OTA update incredibly unintuitively. I kept expecting that such basic things were only around the corner, but like the experience of this presence sensor, there's no predictable outcome for ZHA based on what Z2M is managing to do.

Expressing frustration at the countless hours spent by volunteers on ZHA is definitely missing the point, and they don't owe anyone anything, but to someone starting a Home Assistant build afresh, they're still encouraged that ZHA is best option for them to set up their Zigbee network, and I just don't think that's proven to be accurate.

kaiserkiwi commented 7 months ago

To come back to the initial topic: Has someone already implemented a custom quirk that we could test to get this running?

I really would like to use the luminance sensor in this thing instead of trying to guess the current light based on time and weather. 😅

milobt commented 7 months ago

I have 5 of these and they work pretty well, however, there is a lag from some of them some time, not sure if this is because of some interference or due to the sensors flooding the zigbee log.

Some good news of the LED indicator front, I found to that when pairing these sensors with a TUYA hub, instead of my Z2M network, it pops up saying there’s an update, specifically to allow you to turn off the indicator LED. So, if you update the device and then set the LED to off in the TUYA app, remove the device from the TUYA hub and repair with you Z2M network, it keeps the off setting and so stays off when motion is detected - GREAT!

This does posisble mean that there is now a cluster exposed to be able to configure the LED state over zigbee so anyone that can, please look into whether the LED cluster is exposed and add it to the device configuration.

comperta commented 4 months ago

Hello everyone,

The _TZ3218_awarhusb module uses different clusters than those used by _TZE200_2aaelwxk so we cannot simply add the device, despite the fact that they are both TS0225 models.

I tried to implement a quirk that takes into account the signature of the _TZ3218_awarhusb module, without success so far. I simply managed to recover the "Fading Time" and only in the device management.

I'll give you the code I use, if someone has better knowledge than me (first time I'm getting into this), I'm interested :-)

I am blocked in particular on two points:

source from which I took inspiration: https://raw.githubusercontent.com/kkossev/Hubitat/development/Drivers/Tuya%20Multi%20Sensor%204%20In%201/Tuya%20Multi%20Sensor%204%20In%201.groovy

search TS0225_LINPTECH_RADAR inside the file.

"// LINPTECH / MOES are using a custom cluster 0xE002 for the settings (except for the fadingTime), ZCL cluster 0x0400 for illuminance (malformed reports!) and the IAS cluster 0x0500 for motion detection"

and of course zigbee2mqtt: https://github.com/Koenkk/zigbee2mqtt/issues/18637 there are screenshots and valuable information on the data to read :-)

I Hope someone could help with this start : ts0225_presence.zip

rafmet commented 4 months ago

Hi,

I don't have any experience writing zigpy quirks and at the beginning it seemed to be way above my head but as a complete beginner I was able to write a partially working quirk for TZ3218/TS0225. First I tried to write V1 quirk but it was very difficult to expose sensor values as entities in Home Assistant. Then I tried V2 and they look a little simpler but documentation is poor and there are almost no examples since V2 quirks are quite a new idea. The Zigbee2mqtt converter was helpful as a source of device details.

What is working:

What is not working:

When setting sensitivity or detection distance I get UNSUPPORTED_ATTRIBUTE

tz3218_ts0225.zip

I would be grateful for any help/feedback

mool commented 4 months ago

Hi, I'm also totally new with quirks but yesterday I was able to get this kind of working.... at least I was able to set the motion_detection_distance to reduce the distance where the sensor was detecting presence.

https://gist.github.com/mool/d4fb96eaed3d04b9bdbf1d7c1517141c

kaiserkiwi commented 3 months ago

As this would be my first quirk, how the heck do they work? I found many things online to use them but the last bit is always missing.

I created /config/custom_zha_quirks. I added the file from @mool. I added the zha config to my configuation.yaml

zha:
  enable_quirks: true
  custom_quirks_path: /config/custom_zha_quirks

I restarted and got the "Loaded custom quirks. Please contribute them to https://github.com/zigpy/zha-device-handlers" log message.

But how do I apply the quirk? There's no option and it doesn't get applied automatically but with TS0225 and _TZ3218_awarhusb the identifier should match.

What am I missing? 😅

rafmet commented 3 months ago

I restarted and got the "Loaded custom quirks. Please contribute them to https://github.com/zigpy/zha-device-handlers" log message.

Good news - Home Assistant noticed the quirks :-)

But how do I apply the quirk? There's no option and it doesn't get applied automatically but with TS0225 and _TZ3218_awarhusb the identifier should match.

There is no need to apply quirk in any way. When you go to device settings you should see line "Quirk: ....." in Zigbee info. If there is no quirk info then probably identifiers of quirk and your device differs.

felafel commented 3 months ago

TL;DR I am using Zigbee2MQTT (Z2M) and it is working well including luminance.

For those that claimed my last post was "off-topic" or venting I think they should read the whole thread. Reading the one post is not enough. At that time I posted the most including these types of progressive posts [does anyone have a solution] [I tried this and maybe someone can help] [does anyone have suggestions on getting this to work]. The answers were "no idea" or crickets.

In addition, there was more missing context. I am a real software developer and I can easily get HA to work without Nabu Casa. I subscribe to Nabu Casa (in my second year) and I bought the SkyConnect. I am not dumping on HA or any devs that are trying to make things better.

I think z2m works well. I do not see the point in recreating the wheel. I think the ZHA devs may be more effective making z2M better. However, if they really want to duplicate something that works; one thing I think is very much missing is quirk functionality. See above posts about this as well. Is the quirks folder being used? Who knows. Is the device trying a quirk but it does not work? Who knows.

Have fun and I will unsubscribe since this thread is no longer applicable to me.

kaiserkiwi commented 3 months ago

There is no need to apply quirk in any way. When you go to device settings you should see line "Quirk: ....." in Zigbee info. If there is no quirk info then probably identifiers of quirk and your device differs.

That's so weird. It's right there. The script:

Bildschirmfoto 2024-05-13 um 20 31 21

The device:

Bildschirmfoto 2024-05-13 um 20 31 35

Restarted multiple times now and even made an Home Assistant update just to be sure. But nope. Doesn't get detected. :/

rafmet commented 3 months ago

Restarted multiple times now and even made an Home Assistant update just to be sure. But nope. Doesn't get detected. :/

I don't know German but as I guess "Eigenart" means "Quirk" so the quirk is applied - ts0225_linptech is the name of the file and TS0225Radar is the name of the class.

kaiserkiwi commented 3 months ago

Oh well… I never thought someone would translate this as we use this word in this context here too, as no direct translation would be possible. 🙃

Then it's applied but doesn't give me anything extra. Thanks for your help. I guess future quirks won't be such a headache for me.

rafmet commented 3 months ago

Oh well… I never thought someone would translate this as we use this word in this context here too, as no direct translation would be possible. 🙃

Then it's applied but doesn't give me anything extra. Thanks for your help. I guess future quirks won't be such a headache for me.

It probably gives you possibility to set detection distance through 'Manage Zigbee Device' / selecting cluster / selecting attribute / write atrribute. Not very user friendly. As I understand it was one of the problems with "old" quirks. That's why I started to try with v2. You can try the quirk I've uploaded earlier in this thread.

comperta commented 3 months ago

thank you @rafmet , I tried your file, and it works for me. However I have stability problems when I use it.

rafmet commented 3 months ago

thank you @rafmet , I tried your file, and it works for me. However I have stability problems when I use it.

I guess the instability you mentioned is related to the error when setting sensitivity or distance. Unfortunately still don't know how to fix it or at least somehow ignore error :-( v2 quirks are still new so I can't find many examples to learn from and documentation is poor :-(

thermseekr commented 2 weeks ago

Hi there, any developments on this? I'm selecting sensors to buy for testing for a new project. One that combines mmWave and luminosity would be great.