ZHA Quirk of Zigbee Smoke detector TS0205

Hello Community,

Some time ago, I purchased Zigbee smoke detectors from AliExpress for non-critical areas. Unfortunately, they are not recognized as smoke detectors in ZHA (Zigbee Home Automation), but rather as motion detectors, as shown in the attached screenshot.

I have already attempted to solve this issue using so-called “quirks.” To do this, I added the following to my configuration.yaml:

zha:
  custom_quirks_path: /config/custom_zha_quirks/

I created the corresponding folder beforehand. Inside it, I created a file named TS0205_Update.js with the following content:

"""Smoke Sensor."""
import zigpy.profiles.zha
from zigpy.quirks import CustomCluster, CustomDevice
import zigpy.types as t
from zigpy.zcl.clusters.general import Basic, PowerConfiguration, Groups, Identify, OnOff, Ota, Scenes, Time
from zigpy.zcl.clusters.security import IasZone
from zigpy.zcl.clusters.lightlink import LightLink

from zhaquirks import Bus
from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
    ZONE_STATUS,
    ZONE_TYPE,
)
from zhaquirks.tuya import TuyaManufCluster, TuyaManufClusterAttributes


TUYA_SMOKE_DETECTED_ATTR = 0x0401  # [0]/[1] [Detected]/[Clear]!


class TuyaSmokeDetectorCluster(TuyaManufClusterAttributes):
    """Manufacturer Specific Cluster of the TS0601 smoke detector."""

    attributes = {
        TUYA_SMOKE_DETECTED_ATTR: ("smoke_detected", t.uint8_t, True),
    }

    def _update_attribute(self, attrid, value):
        super()._update_attribute(attrid, value)
        if attrid == TUYA_SMOKE_DETECTED_ATTR:
            if value == 0:
                self.endpoint.device.ias_bus.listener_event(
                    "update_zone_status", IasZone.ZoneStatus.Alarm_1
                )
            else:
                self.endpoint.device.ias_bus.listener_event("update_zone_status", 0)
        else:
            _LOGGER.warning(
                "[0x%04x:%s:0x%04x] unhandled attribute: 0x%04x",
                self.endpoint.device.nwk,
                self.endpoint.endpoint_id,
                self.cluster_id,
                attrid,
            )


class TuyaIasZone(CustomCluster, IasZone):
    """IAS Zone."""

    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Fire_Sensor}

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self.endpoint.device.ias_bus.add_listener(self)

    def update_zone_status(self, value):
        """Update IAS status."""
        super()._update_attribute(ZONE_STATUS, value)


class TuyaSmokeDetector0205(CustomDevice):
    """TS0601 Smoke detector quirk."""

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

    signature = {
        MODELS_INFO: [
            ("_TZ3210_up3pngle", "TS0205"),
        ],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zigpy.profiles.zha.PROFILE_ID,
                DEVICE_TYPE: zigpy.profiles.zha.DeviceType.IAS_ZONE,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfiguration.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    IasZone.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Time.cluster_id,
                    OnOff.cluster_id,
                    Ota.cluster_id,
                    LightLink.cluster_id, 
                ],
            },
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zigpy.profiles.zha.PROFILE_ID,
                DEVICE_TYPE: zigpy.profiles.zha.DeviceType.IAS_ZONE,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfiguration.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaIasZone,
                ],
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Time.cluster_id,
                    OnOff.cluster_id,
                    Ota.cluster_id,
                    LightLink.cluster_id, 
                ],
            },
        },
    }

Despite several attempts to delete and reset the “motion detector,” everything remains the same. Of course, I have also performed a restart.

Do you have any tips or suggestions on how I can solve this problem?

Thank you in advance!

Best regards,
Joscha

Hey,

I’m totally fine with getting approximate information. There’s gotta be someone out there who’s dealt with these quirks before, right?

Hello @Stiltjack ,

Thank you for your efforts. I’ve read the link multiple times before and tried everything, but I’m not making any progress. It seems like the fire alarm, just like the make, has been around for quite some time. Therefore, I suspect I might be making a mistake. That’s why I’m reaching out here, hoping to be pointed out to any errors or similar issues.

Thank you, Josch

Hello!
This week I received mine.
I just had to look for it on the Zigbee network and it recognized it. Yes, as a motion detector, but by changing the logo, everything automatically changed as a smoke detector.
I didn’t have to do anything else.
Of course, the alarm on the lid does not work. The battery level; They were new. But they’re still at 100%, so I don’t know if it’s really giving me the real value either.