zha-device-handlers icon indicating copy to clipboard operation
zha-device-handlers copied to clipboard

[Device Support Request] TY0201 by _TZ3000_bjawzodf

Open idumzaes opened this issue 1 year ago • 64 comments

Problem description

Round white temperature and humidity sensor with display purchased from Temu. Only temperature and battery shows.

I attempted using the ts0201.py and replacing ("_TZ3000_qaaysllp", "TS0201") with ("_TZ3000_bjawzodf", "TY0201") and it seems to be working.

Solution description

Temperature, Humidity and Battery level support.

Screenshots/Video

Screenshots/Video

Before Quirk Screenshot 2023-12-25 at 7 50 05 PM

After Quirk Screenshot 2023-12-25 at 8 10 44 PM

Device signature

Device signature

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

Diagnostic information

Diagnostic information

{ "home_assistant": { "installation_type": "Home Assistant OS", "version": "2023.12.3", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.11.6", "docker": true, "arch": "x86_64", "timezone": "America/New_York", "os_name": "Linux", "os_version": "6.1.63-haos", "supervisor": "2023.12.0", "host_os": "Home Assistant OS 11.2", "docker_version": "24.0.7", "chassis": "vm", "run_as_root": true }, "custom_components": { "meross_lan": { "version": "3.0.0", "requirements": [] }, "hacs": { "version": "1.33.0", "requirements": [ "aiogithubapi>=22.10.1" ] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "after_dependencies": [ "onboarding", "usb" ], "codeowners": [ "@dmulcahey", "@adminiuga", "@puddly", "@TheJulianJES" ], "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.37.3", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.107", "zigpy-deconz==0.22.2", "zigpy==0.60.1", "zigpy-xbee==0.20.1", "zigpy-zigate==0.12.0", "zigpy-znp==0.12.0", "universal-silabs-flasher==0.0.15", "pyserial-asyncio-fast==0.11" ], "usb": [ { "vid": "10C4", "pid": "EA60", "description": "2652", "known_devices": [ "slae.sh cc2652rb stick" ] }, { "vid": "1A86", "pid": "55D4", "description": "sonoffplus*", "known_devices": [ "sonoff zigbee dongle plus v2" ] }, { "vid": "10C4", "pid": "EA60", "description": "sonoffplus*", "known_devices": [ "sonoff zigbee dongle plus" ] }, { "vid": "10C4", "pid": "EA60", "description": "tubeszb", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "tubeszb", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "zigstar", "known_devices": [ "ZigStar Coordinators" ] }, { "vid": "1CF1", "pid": "0030", "description": "conbee", "known_devices": [ "Conbee II" ] }, { "vid": "0403", "pid": "6015", "description": "conbee", "known_devices": [ "Conbee III" ] }, { "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": 63935, "manufacturer": "_TZ3000_bjawzodf", "model": "TY0201", "name": "_TZ3000_bjawzodf TY0201", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "quirk_id": null, "manufacturer_code": 4417, "power_source": "Battery or Unknown", "lqi": 87, "rssi": null, "last_seen": "2023-12-25T18:54:54", "available": true, "device_type": "EndDevice", "signature": { "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.EndDevice: 2>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress: 128>, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)", "endpoints": { "1": { "profile_id": "0x0104", "device_type": "0x0302", "input_clusters": [ "0x0000", "0x0001", "0x0003", "0x0402", "0x0405" ], "output_clusters": [ "0x0019" ] } }, "manufacturer": "_TZ3000_bjawzodf", "model": "TY0201" }, "active_coordinator": false, "entities": [ { "entity_id": "button.tz3000_bjawzodf_ty0201_identify", "name": "_TZ3000_bjawzodf TY0201" }, { "entity_id": "sensor.tz3000_bjawzodf_ty0201_battery", "name": "_TZ3000_bjawzodf TY0201" }, { "entity_id": "sensor.tz3000_bjawzodf_ty0201_temperature", "name": "_TZ3000_bjawzodf TY0201" } ], "neighbors": [], "routes": [], "endpoint_names": [ { "name": "TEMPERATURE_SENSOR" } ], "user_given_name": null, "device_reg_id": "388644d1eb87a058dbda55635d46ea92", "area_id": null, "cluster_details": { "1": { "device_type": { "name": "TEMPERATURE_SENSOR", "id": 770 }, "profile_id": 260, "in_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0004": { "attribute_name": "manufacturer", "value": "_TZ3000_bjawzodf" }, "0x0005": { "attribute_name": "model", "value": "TY0201" } }, "unsupported_attributes": {} }, "0x0001": { "endpoint_attribute": "power", "attributes": { "0x0021": { "attribute_name": "battery_percentage_remaining", "value": 200 } }, "unsupported_attributes": {} }, "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0402": { "endpoint_attribute": "temperature", "attributes": { "0x0000": { "attribute_name": "measured_value", "value": 2360 } }, "unsupported_attributes": {} }, "0x0405": { "endpoint_attribute": "humidity", "attributes": { "0x0000": { "attribute_name": "measured_value", "value": 3870 } }, "unsupported_attributes": { "0x0000": { "attribute_name": "measured_value" } } } }, "out_clusters": { "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} } } } } } }

Logs

Logs
[Paste the logs here]

Custom quirk

Custom quirk

"""Tuya TS201 temperature, humidity and optional illumination sensors."""

from zigpy.profiles import zha from zigpy.profiles.zha import DeviceType from zigpy.quirks import CustomCluster, CustomDevice import zigpy.types as t from zigpy.zcl.clusters.general import Basic, Identify, Ota, PowerConfiguration, Time from zigpy.zcl.clusters.measurement import ( IlluminanceMeasurement, RelativeHumidity, TemperatureMeasurement, ) from zigpy.zdo.types import NodeDescriptor

from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODELS_INFO, NODE_DESCRIPTOR, OUTPUT_CLUSTERS, PROFILE_ID, )

class ValueAlarm(t.enum8): """Temperature and humidity alarm values."""

ALARM_OFF = 0x02
MAX_ALARM_ON = 0x01
MIN_ALARM_ON = 0x00

class TuyaTemperatureHumidityAlarmCluster(CustomCluster): """Tuya temperature and humidity alarm cluster (0xE002)."""

name = "Tuya Temperature and Humidity Alarm Cluster"
cluster_id = 0xE002

attributes = {
    # Alarm settings
    0xD00A: ("alarm_temperature_max", t.uint16_t, True),
    0xD00B: ("alarm_temperature_min", t.uint16_t, True),
    0xD00C: ("alarm_humidity_max", t.uint16_t, True),
    0xD00E: ("alarm_humidity_min", t.uint16_t, True),
    # Alarm information
    0xD00F: ("alarm_humidity", ValueAlarm, True),
    0xD006: ("temperature_humidity", ValueAlarm, True),
    # Unknown
    0xD010: ("unknown", t.uint8_t, True),
}

class NeoTemperatureHumidtyIlluminanceSensor(CustomDevice): """Neo temperature, humidity and illumination sensor."""

signature = {
    #  <SimpleDescriptor endpoint=1, profile=260, device_type=262
    #  device_version=1
    #  input_clusters=[0, 1, 1024, 57346]
    #  output_clusters=[25, 10]>
    MODELS_INFO: [("_TZ3000_bjawzodf", "TY0201")],
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: DeviceType.LIGHT_SENSOR,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                PowerConfiguration.cluster_id,
                IlluminanceMeasurement.cluster_id,
                TuyaTemperatureHumidityAlarmCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [
                Time.cluster_id,
                Ota.cluster_id,
            ],
        },
    },
}

replacement = {
    ENDPOINTS: {
        1: {
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                PowerConfiguration.cluster_id,
                IlluminanceMeasurement.cluster_id,
                TuyaTemperatureHumidityAlarmCluster,
            ],
            OUTPUT_CLUSTERS: [
                Time.cluster_id,
                Ota.cluster_id,
            ],
        },
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: DeviceType.TEMPERATURE_SENSOR,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                TemperatureMeasurement.cluster_id,
                RelativeHumidity.cluster_id,
            ],
        },
    },
}

class ZemismartTemperatureHumidtySensor(CustomDevice): """Zemismart temperature and humidity sensor."""

signature = {
    #  <SimpleDescriptor endpoint=1 profile=260 device_type=770
    # device_version=1
    # input_clusters=[0, 1, 3, 1029, 1026, 61183]
    # output_clusters=[3, 25]>
    MODELS_INFO: [("_TZ3000_lfa05ajd", "TS0201")],
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                PowerConfiguration.cluster_id,
                Identify.cluster_id,
                RelativeHumidity.cluster_id,
                TemperatureMeasurement.cluster_id,
                0xEEFF,  # Unknown
            ],
            OUTPUT_CLUSTERS: [Identify.cluster_id, Ota.cluster_id],
        }
    },
}

replacement = {
    NODE_DESCRIPTOR: NodeDescriptor(
        0x02,
        0x40,
        0x80,
        0x1037,
        0x7F,
        0x0064,
        0x2C00,
        0x0064,
        0x00,  # Forcing capability 0x80 instead of 0x84 so AC Power = false
    ),
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                PowerConfiguration.cluster_id,
                Identify.cluster_id,
                RelativeHumidity.cluster_id,
                TemperatureMeasurement.cluster_id,
            ],
            OUTPUT_CLUSTERS: [Identify.cluster_id, Ota.cluster_id],
        }
    },
}

class RelativeHumidityX10(CustomCluster, RelativeHumidity): """Handles invalid humidity values."""

def _update_attribute(self, attrid, value):
    # x10 factor in measured_value`(attrid=0)
    if attrid == 0:
        value = value * 10
    super()._update_attribute(attrid, value)

class MoesTemperatureHumidtySensorWithScreen(CustomDevice): """Moes temperature and humidity sensor with screen."""

signature = {
    #  <SimpleDescriptor endpoint=1, profile=260, device_type="0x0302"
    #  input_clusters=["0x0000", "0x0001", "0x0003", "0x0402", "0x0405", "0xe002"]
    #  output_clusters=["0x0003", "0x000a", "0x0019"]>
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: DeviceType.TEMPERATURE_SENSOR,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                PowerConfiguration.cluster_id,
                Identify.cluster_id,
                TemperatureMeasurement.cluster_id,
                RelativeHumidity.cluster_id,
                TuyaTemperatureHumidityAlarmCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [
                Identify.cluster_id,
                Time.cluster_id,
                Ota.cluster_id,
            ],
        },
    },
}

replacement = {
    ENDPOINTS: {
        1: {
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                PowerConfiguration.cluster_id,
                Identify.cluster_id,
                TemperatureMeasurement.cluster_id,
                RelativeHumidityX10,
                TuyaTemperatureHumidityAlarmCluster,
            ],
            OUTPUT_CLUSTERS: [
                Identify.cluster_id,
                Time.cluster_id,
                Ota.cluster_id,
            ],
        },
    },
}

Additional information

https://www.temu.com/tuya-smart-zigbee-temperature-and-humidity-sensor-smart-life-app-control-indoor-humidity-detector-works-with-zigbee-gateway-hub-g-601099531358811.html

idumzaes avatar Dec 26 '23 01:12 idumzaes