Skip to content

[Device Support Request] TY0201 by _TZ3000_bjawzodf #2862

@idumzaes

Description

@idumzaes

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    TuyaRequest/PR regarding a Tuya device

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions