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

Convert Tuya garage to v2

Open prairiesnpr opened this issue 8 months ago • 9 comments

Proposed change

Converts Tuya garage quirks to v2, Adds TS0603 _TZE608_c75zqghm and _TZE608_fmemczv1.

Based on: https://github.com/Koenkk/zigbee-herdsman-converters/blob/6c3d7e2aa1fba6f6342baea21e5b3bbd3688cb0e/src/devices/tuya.ts#L7481

Additional information

Closes: #3263, feel free to close #3607 first and I'll rebase this one. Closes: #1260 Closes: #3889 Closes: #3843 Closes: #3375 Closes: #2533

Checklist

  • [ ] The changes are tested and work correctly
  • [x] pre-commit checks pass / the code has been formatted using Black
  • [ ] Tests have been added to verify that the new code works

prairiesnpr avatar Feb 17 '25 20:02 prairiesnpr

Codecov Report

:white_check_mark: All modified and coverable lines are covered by tests. :white_check_mark: Project coverage is 90.94%. Comparing base (f23fda3) to head (1d0f9f0). :warning: Report is 127 commits behind head on dev.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #3891      +/-   ##
==========================================
- Coverage   90.95%   90.94%   -0.02%     
==========================================
  Files         326      326              
  Lines       10597    10585      -12     
==========================================
- Hits         9638     9626      -12     
  Misses        959      959              

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

:rocket: New features to boost your workflow:
  • :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

codecov[bot] avatar Feb 17 '25 20:02 codecov[bot]

Can't wait to see it happen ! 🙏

Julien-Decoen avatar Mar 20 '25 13:03 Julien-Decoen

Any idea when this is gonna be in release? Can I somehow "install" this with custom quirks in the meanwhile? I tried adding the two changed files to my customquirk folder, but it doesn't work image

Tropaion avatar Mar 30 '25 15:03 Tropaion

This can't be merged as is, it needs to be converted to act a cover and I haven't had time to work with it further. There are several guides on how to use custom quirks on the community forums that should let you use this for now.

prairiesnpr avatar Mar 30 '25 16:03 prairiesnpr

This can't be merged as is, it needs to be converted to act a cover and I haven't had time to work with it further.

What do you mean by act a cover? I'm not getting the second button to work on _TZE204_nklqjk62 and it seems like it really needs a button that can read the status from the magnetic sensor to either send true/false depending on the state.

Bruners avatar May 09 '25 16:05 Bruners

This can't be merged as is, it needs to be converted to act a cover and I haven't had time to work with it further.

What do you mean by act a cover? I'm not getting the second button to work on _TZE204_nklqjk62 and it seems like it really needs a button that can read the status from the magnetic sensor to either send true/false depending on the state.

It would need to be rewritten so that it presents itself to Home Assistant as a cover, not a command button like it does now. We don't currently have support for covers in v2 quirks, so it's not easy.

prairiesnpr avatar May 10 '25 01:05 prairiesnpr

Why should it be a cover?! I disagree, I use mine as a lock with Z2M and a template lock entity. I have no interest in a cover and wouldn't use it. It is a garage door opener to my knowledge not anything to do with windows or covers. It is a sensitive opening that merits the defaults a lock get you like asking for a pin code using voice assistants. I would like to ditch z2m that is acting up recently but missing this is blocking me. I can't understand why it has been so long working with quirks and still it hasn't been released. I get it's open source and I ain't complaining only thanking those having spent time on it! But still I believe you shouldn't make it more complicated than it is: it exposes a button that should be used as a push button for most garage doors and a contact sensor. Make those available the rest is a template device that can be shared between users. Well that's my opinion at least I see no value in holding this back trying to achieve better in an opiniated way that isn't going to fit everyone anyway...

toxic0berliner avatar May 18 '25 16:05 toxic0berliner

Maybe we should leave these as buttons and just rename them "Toggle Relay X"

TheJulianJES avatar May 19 '25 14:05 TheJulianJES

Maybe we should leave these as buttons and just rename them "Toggle Relay X"

Any clues to why only the first button shows up? The relay functions with true or false on the same DP depending on the door_status open/closed

Bruners avatar May 31 '25 20:05 Bruners

Hi, is it clear what’s holding this up from release? I recently got a TS0601 _TZE204_nklqjk62 to open my garage door, but it’s currently not exposing any entities to HA.

I agree with other commenters that this is a toggle button. Doesn’t make sense to wait longer for a “nice to have” cover feature over basic functionality anyway.

Thanks

dpatterson87 avatar Jul 18 '25 14:07 dpatterson87

Hi, is it clear what’s holding this up from release? I recently got a TS0601 _TZE204_nklqjk62 to open my garage door, but it’s currently not exposing any entities to HA.

Got the same device. However - Got entities via 'zigpy.quirks.v2.CustomDeviceV2', but sensor is not working.

Nykaer avatar Sep 19 '25 09:09 Nykaer

same here, can we merge?

pabloopez avatar Sep 28 '25 08:09 pabloopez

Exposing as a toggle is fine. Zigbee2mqtt does that and its easy to create a valid switch with some automations. It would be nice to have this as many of us are getting this device.

danielfrg avatar Sep 28 '25 23:09 danielfrg

For what it's worth I have been using that device for a while with z2m and it wasn't working fine for me, for a simple reason, the trigger it exposes does not trigger the garage door opener when you switch it, there is a more complex logic behind that with the reed sensor identifying if the door is closed and the timer for open/close that need to elapse until your presses are considered... All in all I ditched the device for a custom esphome with an extra reed switch when the door is fully opened. I know wifi ain't ZigBee but still I feel 2 separate ZigBee devices :1 relay and 1 door sensor are better than this device. That said it's also amazing that it's still not managed by ZHA...

toxic0berliner avatar Sep 28 '25 23:09 toxic0berliner

For what it's worth I have been using that device for a while with z2m and it wasn't working fine for me, for a simple reason, the trigger it exposes does not trigger the garage door opener when you switch it, there is a more complex logic behind that with the reed sensor identifying if the door is closed and the timer for open/close that need to elapse until your presses are considered... All in all I ditched the device for a custom esphome with an extra reed switch when the door is fully opened. I know wifi ain't ZigBee but still I feel 2 separate ZigBee devices :1 relay and 1 door sensor are better than this device. That said it's also amazing that it's still not managed by ZHA...

Not sure I follow this comment..? I’ve been manually setting the cluster attributes for the button.

  • Set true to start opening from closed
  • Set false to start closing from fully open
  • setting false/true stops movement whilst partially open/closed

it’s a PITA without exposed sensors/buttons, but the device seems solid enough.

dpatterson87 avatar Sep 29 '25 06:09 dpatterson87

Sorry my comment was a bit off topic, but if you set the timer right and only use this device to manipulate the door it can work just fine for you. I was just sharing that on my side due to the wife using something else to open/close the door and maybe my not setting the timer properly I often had issues with the door stopping mid-way or having to press the open button several times before getting the door to open. Might also be my ZigBee network that was a bit slow to transfer the messages.

That said it can in some circumstances work well enough for some people to value this so it should be made compatible with ZHA and expose the switch the sensor the timer and the alarm status as Z2M does.

toxic0berliner avatar Sep 29 '25 06:09 toxic0berliner

Anyone with any luck with this device?? _TZE204_nklqjk62 Had an extra device, that I added to fresh installed HAOS.. Same thing there. No entities...

Nykaer avatar Oct 17 '25 19:10 Nykaer

Anyone with any luck with this device?? _TZE204_nklqjk62 Had an extra device, that I added to fresh installed HAOS.. Same thing there. No entities...

This old version is still working for me. Of course it's not with the garage cover:

ts0601_garage.py

"""Tuya based cover and blinds.""" from typing import Dict

from zigpy.profiles import zha from zigpy.quirks import CustomDevice import zigpy.types as t from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time from zigpy.zcl.clusters.security import IasZone

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

from zhaquirks.tuya import TuyaLocalCluster, TuyaDPType from zhaquirks.tuya.mcu import DPToAttributeMapping, TuyaMCUCluster, TuyaOnOff from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM

ZONE_TYPE = 0x0001

class ContactSwitchCluster(TuyaLocalCluster, IasZone): """Tuya ContactSwitch Sensor."""

_CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}

def _update_attribute(self, attrid, value):
    self.debug("_update_attribute '%s': %s", attrid, value)
    super()._update_attribute(attrid, value)

class TuyaGarageManufCluster(TuyaMCUCluster): """Tuya garage door opener."""

attributes = TuyaMCUCluster.attributes.copy()
attributes.update(
    {
        # ramdom attribute IDs
        0xEF02: ("dp_2", t.uint32_t, True),
        0xEF04: ("dp_4", t.uint32_t, True),
        0xEF05: ("dp_5", t.uint32_t, True),
        0xEF0B: ("dp_11", t.Bool, True),
        0xEF0C: ("dp_12", t.enum8, True),
    }
)

dp_to_attribute: Dict[int, DPToAttributeMapping] = {
    # garage door trigger ¿on movement, on open, on closed?
    1: DPToAttributeMapping(
        TuyaOnOffNM.ep_attribute,
        "on_off",
        TuyaDPType.BOOL,
    ),
    2: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_2",
        TuyaDPType.VALUE,
    ),
    3: DPToAttributeMapping(
        ContactSwitchCluster.ep_attribute,
        "zone_status",
        #TuyaDPType.BOOL,
        lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,
        endpoint_id=2,
    ),
    4: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_4",
        TuyaDPType.VALUE,
    ),
    5: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_5",
        TuyaDPType.VALUE,
    ),
    11: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_11",
        TuyaDPType.BOOL,
    ),
    # garage door status (open, closed, ...)
    12: DPToAttributeMapping(
        TuyaMCUCluster.ep_attribute,
        "dp_12",
        TuyaDPType.ENUM,
    ),
}

data_point_handlers = {
    1: "_dp_2_attr_update",
    2: "_dp_2_attr_update",
    3: "_dp_2_attr_update",
    4: "_dp_2_attr_update",
    5: "_dp_2_attr_update",
    11: "_dp_2_attr_update",
    12: "_dp_2_attr_update",
}

class TuyaGarageSwitchTO(CustomDevice): """Tuya Garage switch."""

signature = {
    MODELS_INFO: [
        ("_TZE204_nklqjk62", "TS0601"),
    ],
    ENDPOINTS: {
        # <SimpleDescriptor endpoint=1 profile=260 device_type=0x0051
        # input_clusters=[0, 4, 5, 61184]
        # output_clusters=[10, 25]>
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaGarageManufCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
        # input_clusters=[]
        # output_clusters=[33]
        242: {
            PROFILE_ID: 41440,
            DEVICE_TYPE: 97,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}

replacement = {
    ENDPOINTS: {
        1: {
            DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaGarageManufCluster,
                TuyaOnOffNM,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
            INPUT_CLUSTERS: [
                ContactSwitchCluster
            ],
            OUTPUT_CLUSTERS: [],
        },
        242: {
            PROFILE_ID: 0xA1E0,
            DEVICE_TYPE: 0x0061,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [0x0021],
        },
    },
}

XrmBoost avatar Oct 26 '25 13:10 XrmBoost