Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Device Support Request] Aqara T1 with neutral (lumi.switch.n0agl1) switch_type Support #1231

Closed
alex-mikhaylov opened this issue Dec 26, 2021 · 41 comments · Fixed by #2513
Closed
Labels
workaround available The issue can be worked around

Comments

@alex-mikhaylov
Copy link

Is your feature request related to a problem? Please describe.
By default the Aqara's T1 with neutral (lumi.switch.n0agl1) switch_type is set to a rocker switch by default and cannot be changed via ZHA. This makes it impossible to use the switch with a momentary (push) button.

Describe the solution you'd like
Making it possible to change the switch_type attribute via ZHA.

Device signature - this can be acquired by removing the device from ZHA and pairing it again from the add devices screen. Be sure to add the entire content of the log panel after pairing the device to a code block below this line.

  "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, manufacturer_code=4447, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *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": 260,
      "device_type": "0x0100",
      "in_clusters": [
        "0x0000",
        "0x0002",
        "0x0003",
        "0x0004",
        "0x0005",
        "0x0006",
        "0x0009",
        "0x000a",
        "0x0702",
        "0x0b04",
        "0xfcc0"
      ],
      "out_clusters": [
        "0x0019"
      ]
    },
    "21": {
      "profile_id": 260,
      "device_type": "0x0100",
      "in_clusters": [
        "0x000c"
      ],
      "out_clusters": []
    },
    "31": {
      "profile_id": 260,
      "device_type": "0x0100",
      "in_clusters": [
        "0x000c"
      ],
      "out_clusters": []
    },
    "41": {
      "profile_id": 260,
      "device_type": "0x0100",
      "in_clusters": [
        "0x0012"
      ],
      "out_clusters": []
    },
    "242": {
      "profile_id": 41440,
      "device_type": "0x0061",
      "in_clusters": [],
      "out_clusters": [
        "0x0021"
      ]
    }
  },
  "manufacturer": "LUMI",
  "model": "lumi.switch.n0agl1",
  "class": "zigpy.device.Device"
}

Additional context
Zigbee2MQTT supports changing the switch_type - link.

@Hedda
Copy link
Contributor

Hedda commented May 10, 2022

By default the Aqara's T1 with neutral (lumi.switch.n0agl1) switch_type is set to a rocker switch by default and cannot be changed via ZHA. This makes it impossible to use the switch with a momentary (push) button.

FYI, there is a similar request for "switch_type" configuration in #1145 for Tuya 3 gang switch TS0003 module (TZ3000_odzoiovu).

dumpfheimer mentioned you should be able to build a similar quirk using his from this other PR as a base -> #1391

See related developers discussion here for reference -> zigpy/zigpy#934

Originally posted by @dumpfheimer in zigpy/zigpy#934 (comment)

dmulcahey has been working on exposing the configuration entities here: https://github.com/dmulcahey/home-assistant/tree/dm/zha-zcl-select

Also, I have a similar PR pending here: zigpy/zha-device-handlers#1391 And I have added the necessary entites here: https://github.com/dumpfheimer/core/tree/dumpfheimer/zha-expose-configuration-entities

All three together make this setting available for Aqara H1 Switches but porting it for T1 should not be very difficult.

PS: There also looks to be a related discussion about this device in Home Assistant community forum here:

https://community.home-assistant.io/t/aqara-switch-module-t1-rebound-switch/345580/

@w-marco
Copy link

w-marco commented Jun 27, 2022

Any progress regarding implementation to change the switch type ?
Or any way to do it manually ?

Currently my module is essentially useless because I use a momentary rocker.
I am willing to test if necessary

@kurtwarwick-new
Copy link

kurtwarwick-new commented Aug 4, 2022

  • 1 for this request.

I have just moved my smart home to Home Assistant with ZHA, which includes a few hundred devices. So, I was far too long into the journey before I noticed this to reasonably go back…

It would be so amazing to have this added! 😊

@jrlacharnay
Copy link

Waiting for it as well. This is a bit similar to this request : #1693

@Anymn
Copy link

Anymn commented Sep 23, 2022

+1 It would be very nice to have this resolved. I rather use ZHA instead of zigbee2mqtt.

@kurtwarwick-new
Copy link

kurtwarwick-new commented Oct 4, 2022

Hi

I just wanted to post a quick update on this topic. I have become unable to wait for this option to be available "natively" through ZHA, so, I have managed to put together a custom quirk.

For those who are interested but don't know how to do that, simply do the following:

In configuration.yaml, simply add the following section:

zha:
  enable_quirks: true
  custom_quirks_path: /config/zha_quirks

Then in the config folder, create a new folder called zha_quirks.

In that new folder, add the following code snippet and restart Home Assistant.

import copy

from enum import Enum

from zigpy import types as t
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import (
    Basic,
    DeviceTemperature,
    Groups,
    Identify,
    OnOff,
    Ota,
    Scenes,
    Alarms,
    Time,
    GreenPowerProxy,
)
from zigpy.zcl.clusters.smartenergy import (
    Metering,
)
from zigpy.zcl.clusters.homeautomation import (
    ElectricalMeasurement,
)

from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)
from zhaquirks.xiaomi import (
    LUMI,
    XiaomiAqaraE1Cluster,
    XiaomiCustomDevice,
)

class XiaomiAqaraT1SwitchType(t.uint8_t, Enum):

    Toggle = 0x01
    Momentary = 0x02

class XiaomiAqaraT1Cluster(XiaomiAqaraE1Cluster):

    ep_attribute = "aqara_cluster"
    cluster_id = XiaomiAqaraE1Cluster.cluster_id
    attributes = {
        0x000A: ("switch_type", t.uint8_t, True)
        # 0x000A: ("switch_type", XiaomiAqaraT1SwitchType, True) - This doesn't work
    }

class AqaraSingleSwitchModelT1WithoutNeutral(XiaomiCustomDevice):
    """Aqara Single Switch Model T1 Without Neutral"""

    signature = {
        MODELS_INFO: [(LUMI, "lumi.switch.l0agl1")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    Alarms.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id
                ]
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x00061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [
                    GreenPowerProxy.cluster_id
                ]
            }
        }
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    Alarms.cluster_id,
                    XiaomiAqaraT1Cluster,
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id
                ]
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x00061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [
                    GreenPowerProxy.cluster_id
                ]
            }
        }
    }

class AqaraSingleSwitchModelT1WithNeutral(XiaomiCustomDevice):
    """Aqara Single Switch Model T1 With Neutral"""

    signature = {
        MODELS_INFO: [(LUMI, "lumi.switch.n0agl1")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    Alarms.cluster_id,
                    Time.cluster_id,
                    Metering.cluster_id,
                    ElectricalMeasurement.cluster_id,
                    XiaomiAqaraE1Cluster.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    OnOff.cluster_id,
                    Time.cluster_id,
                    Ota.cluster_id,
                ]
            },
            21: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            },
            31: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            },
            41: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x00061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [
                    GreenPowerProxy.cluster_id
                ]
            }
        }
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    Alarms.cluster_id,
                    Time.cluster_id,
                    Metering.cluster_id,
                    ElectricalMeasurement.cluster_id,
                    XiaomiAqaraT1Cluster,
                ],
                OUTPUT_CLUSTERS: [
                    OnOff.cluster_id,
                    Time.cluster_id,
                    Ota.cluster_id,
                ]
            },
            21: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
            },
            31: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
            },
            41: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x00061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [
                    GreenPowerProxy.cluster_id
                ]
            }
        }
    }

That should apply the custom quirk to both the T1 with and without neutral.

image

Doing so will

  1. Expose a new cluster called XiaomiAqaraT1Cluster and an attribute called switch_type.
  2. Expose the device as a switch instead of a light.

The switch_type attribute only supports an integer value, and not an Enum as I would have preferred. This is due to an issue where I was unable to update the value. The code to support the Enum options is there, but it just doesn't work at the moment.

image

These are the errors I was getting when I tried to use the Enum:

image

I really hope that this helps ease the pain of waiting for some of you! :)

Kurt

@w-marco
Copy link

w-marco commented Oct 10, 2022

@kurtwarwick-new thanks for your work. I tried it with the version with neutral included and the quirk does not apply to it sadly. I copied your code and created a custom quirk (I have another custom quirk working, so it's not a config issue), but as you can see, the quirk isn't applied:

Screenshot 2022-10-10 at 11 28 35

@kurtwarwick-new
Copy link

Hi @w-marco

Thanks for the update! It seems that after updating to 2022.10, this quirk is no longer being applied. I am seeing the same thing.

I will need to check it out to see what the deal is! That's assuming you have updated to 2022.10.

Watch this space!

Kurt

@w-marco
Copy link

w-marco commented Oct 10, 2022

Hi @kurtwarwick-new, thanks for confirming. I indeed updated to 2022.10.

I’ll be looking out for a possible fix and am happy to report back if you find out what the issue is.

Thanks again!

@w-marco
Copy link

w-marco commented Oct 21, 2022

Hi @kurtwarwick-new just curious:

did you find a way to fix the quirk with the new version so it’s recognized again? Would be great to get this merged into official release if it’s fixed.

@eesdil
Copy link

eesdil commented Oct 28, 2022

I have it now "working" the "With Neutral" version.
Seemingly I have 2 alternatives from it.
I have two issues with it.

  1. it is showing some extra electric measurement stuff, which are Unknown
  2. when I switch the physical switch, it is not syncing to HA

the quirk:

import copy

from enum import Enum

from zigpy import types as t
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import (
    Basic,
    DeviceTemperature,
    Groups,
    Identify,
    OnOff,
    Ota,
    AnalogInput,
    Scenes,
    Alarms,
    Time,
    GreenPowerProxy,
    MultistateInput,
)
from zigpy.zcl.clusters.smartenergy import (
    Metering,
)
from zigpy.zcl.clusters.homeautomation import (
    ElectricalMeasurement,
)

from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)
from zhaquirks.xiaomi import (
    LUMI,
    XiaomiAqaraE1Cluster,
    XiaomiCustomDevice,
)

class XiaomiAqaraT1Cluster(XiaomiAqaraE1Cluster):

    ep_attribute = "aqara_cluster"
    cluster_id = XiaomiAqaraE1Cluster.cluster_id
    attributes = {
        0x000A: ("switch_type", t.uint8_t, True)
    }

class SwitchN0AGL1(XiaomiCustomDevice):
    """lumi.switch.n0agl1 switch"""

    signature = {
        MODELS_INFO: [(LUMI, "lumi.switch.n0agl1")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    Alarms.cluster_id,
                    Time.cluster_id,
                    0xfcc0
                ],
                OUTPUT_CLUSTERS: [
                    Ota.cluster_id
                ]
            },
            21: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    AnalogInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            31: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    AnalogInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            41: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    MultistateInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [
                    GreenPowerProxy.cluster_id
                ]
            }
        }
    }

    replacement = { 
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    Alarms.cluster_id,
                    Time.cluster_id,
                    Metering.cluster_id,
                    ElectricalMeasurement.cluster_id,
                    XiaomiAqaraT1Cluster,
                ],
                OUTPUT_CLUSTERS: [
                    OnOff.cluster_id,
                    Time.cluster_id,
                    Ota.cluster_id,
                ]
            },
            21: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
            },
            31: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
            },
            41: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [
                    GreenPowerProxy.cluster_id
                ]
            }
        }
    }

class SwitchN0AGL1Alt1(SwitchN0AGL1):
    """lumi.switch.n0agl1 switch with alternative signature"""

    signature = {
        MODELS_INFO: [(LUMI, "lumi.switch.n0agl1")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    Alarms.cluster_id,
                    Time.cluster_id,
                    0xfcc0
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                    0xffff
                ]
            },
            21: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    AnalogInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            31: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    AnalogInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            41: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    MultistateInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [
                    GreenPowerProxy.cluster_id
                ]
            }
        }
    }

    replacement = SwitchN0AGL1.replacement

@alex-mikhaylov
Copy link
Author

Does anyone have a working quirk by any chance?

@SkywiperSolutions
Copy link

I have it now "working" the "With Neutral" version. Seemingly I have 2 alternatives from it. I have two issues with it.

  1. it is showing some extra electric measurement stuff, which are Unknown
  2. when I switch the physical switch, it is not syncing to HA

the quirk:

import copy

from enum import Enum

from zigpy import types as t
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import (
    Basic,
    DeviceTemperature,
    Groups,
    Identify,
    OnOff,
    Ota,
    AnalogInput,
    Scenes,
    Alarms,
    Time,
    GreenPowerProxy,
    MultistateInput,
)
from zigpy.zcl.clusters.smartenergy import (
    Metering,
)
from zigpy.zcl.clusters.homeautomation import (
    ElectricalMeasurement,
)

from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)
from zhaquirks.xiaomi import (
    LUMI,
    XiaomiAqaraE1Cluster,
    XiaomiCustomDevice,
)

class XiaomiAqaraT1Cluster(XiaomiAqaraE1Cluster):

    ep_attribute = "aqara_cluster"
    cluster_id = XiaomiAqaraE1Cluster.cluster_id
    attributes = {
        0x000A: ("switch_type", t.uint8_t, True)
    }

class SwitchN0AGL1(XiaomiCustomDevice):
    """lumi.switch.n0agl1 switch"""

    signature = {
        MODELS_INFO: [(LUMI, "lumi.switch.n0agl1")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    Alarms.cluster_id,
                    Time.cluster_id,
                    0xfcc0
                ],
                OUTPUT_CLUSTERS: [
                    Ota.cluster_id
                ]
            },
            21: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    AnalogInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            31: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    AnalogInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            41: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    MultistateInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [
                    GreenPowerProxy.cluster_id
                ]
            }
        }
    }

    replacement = { 
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    Alarms.cluster_id,
                    Time.cluster_id,
                    Metering.cluster_id,
                    ElectricalMeasurement.cluster_id,
                    XiaomiAqaraT1Cluster,
                ],
                OUTPUT_CLUSTERS: [
                    OnOff.cluster_id,
                    Time.cluster_id,
                    Ota.cluster_id,
                ]
            },
            21: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
            },
            31: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
            },
            41: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [
                    GreenPowerProxy.cluster_id
                ]
            }
        }
    }

class SwitchN0AGL1Alt1(SwitchN0AGL1):
    """lumi.switch.n0agl1 switch with alternative signature"""

    signature = {
        MODELS_INFO: [(LUMI, "lumi.switch.n0agl1")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    Alarms.cluster_id,
                    Time.cluster_id,
                    0xfcc0
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                    0xffff
                ]
            },
            21: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    AnalogInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            31: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    AnalogInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            41: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    MultistateInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [
                    GreenPowerProxy.cluster_id
                ]
            }
        }
    }

    replacement = SwitchN0AGL1.replacement

I tried the custom quirk and the sync when pressing the physical button works!

@stoffies00711
Copy link

I have enabled and loaded the quirk. All my Aqara devices now has a quirk reference under their "device info" except this switch. What am I doing wrong?

@rofo69
Copy link

rofo69 commented Feb 8, 2023

There is another variant of this switch now.

I've put both device signatures here (without any quirks loaded):-

https://www.diffchecker.com/249fR60w/

The new one is on the right, and despite it only differing from the n0agl1 by having three more output clusters on endpoint 1, I'm totally failing on how to make a quirk for it. (I cant seem to get the signature right, the quirk never gets adopted by the device).

Any help appreciated to get this working!

@stoffies00711
Copy link

I have given up with this switch. It's now wired into a ceiling outlet box in my passage acting only as a router/repeater with ZHA.

@rofo69
Copy link

rofo69 commented Feb 9, 2023

I finally figured out the solution and am leaving it here for anyone else who gets an Aqara T1 module with the same variant (lumi.switch.n0acn2).

Simply use the quirk above and change the models line from this:-

MODELS_INFO: [(LUMI, “lumi.switch.n0agl1”)],

to

MODELS_INFO: [(LUMI, “lumi.switch.n0agl1”),(LUMI, “lumi.switch.n0acn2”)],

And it starts working.!

@TheJulianJES TheJulianJES added the workaround available The issue can be worked around label Feb 9, 2023
@stoffies00711
Copy link

stoffies00711 commented Feb 10, 2023

Hey @rofo69

Edited both the main and alternate "Model" lines. Deleted the device, Restarted and Added it again. Had to physically re-plug my Zigbee dongle and finally we are moving in the right direction. The power and other sensors are either unknown or not updating after connecting a small load BUT at least now I have the Switch which now at least makes this device a little but more usable.
Thank you.
Does your power sensor work?

image

@SkywiperSolutions
Copy link

Same here. Switch can be controlled, but Active Power is 0.0 W.
I still don't get why this device broke/was removed in the first place. It did work until late 2022.

@rofo69
Copy link

rofo69 commented Feb 11, 2023

No, I never got the power monitoring stuff working.

@Bazsy
Copy link

Bazsy commented Feb 25, 2023

Same here. Switch is working but nothing else (power and consumption)

1 similar comment
@donjohann
Copy link

Same here. Switch is working but nothing else (power and consumption)

@Takacsk76
Copy link

Thanks for the solution! Unfortunately, only the switch works for me, but at least there is a switch.

@ninoweg
Copy link

ninoweg commented Jun 12, 2023

I had to edit the replacement signature of the quirk posted by @eesdil slightly to also get data on Active Power (tested with lumi.switch.n0agl1).

import copy

from enum import Enum

from zigpy import types as t
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import (
    Basic,
    DeviceTemperature,
    Groups,
    Identify,
    OnOff,
    Ota,
    AnalogInput,
    Scenes,
    Alarms,
    Time,
    GreenPowerProxy,
    MultistateInput,
)
from zigpy.zcl.clusters.smartenergy import (
    Metering,
)
from zigpy.zcl.clusters.homeautomation import (
    ElectricalMeasurement,
)

from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)
from zhaquirks.xiaomi import (
    LUMI,
    XiaomiAqaraE1Cluster,
    XiaomiCustomDevice,
    BasicCluster,
    DeviceTemperatureCluster,
    XiaomiMeteringCluster,
    OnOffCluster
)

class XiaomiAqaraT1Cluster(XiaomiAqaraE1Cluster):

    ep_attribute = "aqara_cluster"
    cluster_id = XiaomiAqaraE1Cluster.cluster_id
    attributes = {
        0x000A: ("switch_type", t.uint8_t, True)
    }

class SwitchN0AGL1(XiaomiCustomDevice):
    """lumi.switch.n0agl1 switch"""

    signature = {
        MODELS_INFO: [(LUMI, "lumi.switch.n0agl1")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    Alarms.cluster_id,
                    Time.cluster_id,
                    0xfcc0
                ],
                OUTPUT_CLUSTERS: [
                    Ota.cluster_id
                ]
            },
            21: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    AnalogInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            31: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    AnalogInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            41: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    MultistateInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [
                    GreenPowerProxy.cluster_id
                ]
            }
        }
    }

    replacement = { 
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
                INPUT_CLUSTERS: [
                    BasicCluster,
                    DeviceTemperatureCluster,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOffCluster,
                    Alarms.cluster_id,
                    Time.cluster_id,
                    XiaomiMeteringCluster,
                    ElectricalMeasurement.cluster_id,
                    XiaomiAqaraT1Cluster,
                ],
                OUTPUT_CLUSTERS: [
                    OnOffCluster,
                    Time.cluster_id,
                    Ota.cluster_id,
                ]
            },
            21: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
            },
            31: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
            },
            41: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [
                    GreenPowerProxy.cluster_id
                ]
            }
        }
    }

class SwitchN0AGL1Alt1(SwitchN0AGL1):
    """lumi.switch.n0agl1 switch with alternative signature"""

    signature = {
        MODELS_INFO: [(LUMI, "lumi.switch.n0agl1")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    Alarms.cluster_id,
                    Time.cluster_id,
                    0xfcc0
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                    0xffff
                ]
            },
            21: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    AnalogInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            31: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    AnalogInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            41: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    MultistateInput.cluster_id
                ],
                OUTPUT_CLUSTERS: []
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [
                    GreenPowerProxy.cluster_id
                ]
            }
        }
    }

    replacement = SwitchN0AGL1.replacement

@stoffies00711
Copy link

Thanks @ninoweg
Will give it a go this weekend

@stoffies00711
Copy link

Couldn't wait for the weekend... Copied the quirk exactly and now have an "Active Power" of 0.0 W.
I connected a 12W LED light to the load but the entity does not update. Stays on zero.

@chrisandsally
Copy link

Hi, new to this as just got a T1 with neutral and have the same issues. Added lines in configuration.yaml. Created a directory, but what do I called the file? And File Extension?

I have just called it T1, rebooted but Quirk not loaded under Zigbee Integration.

sorry for the noob question!

@stoffies00711
Copy link

Hi @chrisandsally

I got this in my yaml...

zha:
enable_quirks: true
custom_quirks_path: /config/zha_custom_quirks/

the last line is where I placed the file. Called it aqaralumiswitch.py
I don't think the name matters, just the extension. I think ZHA will identify the device and associate the quirk.

Also a noob so I could be completely wrong here. if so, hopefully someone will correct me.

@rofo69
Copy link

rofo69 commented Jun 14, 2023

Correct zha doesn't care what the file is called, it decides whether or not to apply the quirk based on the signature code in the file itself. A file can have one or more signature and replacement sections.

@chrisandsally
Copy link

Thanks stoffies00711 and rofo69

I have checked the configuration file and quirks file now ends in .py

I removed the device, rebooted HA.

Re - added device, however quirk not showing under info and no change in Active power under load.

Screenshot 2023-06-14 at 18 39 44

@stoffies00711
Copy link

Not sure. I picked up an error on my HA core logs with the quirk (") and couldn't resolve it. So I deleted the .py file and created a new one copying the quirk above exactly, removed device, rebooted HA and added it again. quirk then applied.

@Takacsk76
Copy link

Takacsk76 commented Aug 29, 2023

I tried Zigbee2mqtt on T1. It works perfectly with it. I ported 41 devices, there was only a problem with one led control type, but that was also resolved. Z2M can do more than anything and is probably being developed by more people. Overall, I like the ZHA better, but the Z2M might do better. Z2M entity handling is not good yet, but hopefully it will be fixed. The switch.devicename entity is deprecated from 2024, but neither is switch.devicename_switch. Thanks for your help.
One more thing. It looks like the Chinese devices will have Z2M support by default, making them easier to implement into Z2M. Unfortunately, mqtt discovery renames the entity names and they are not imported into HA with the original entity name. I don't know what the identification is based on, but it would be nice to improve it. The ZHA is currently in a secret state, it can be restored. Sorry if I didn't write something well, but I don't speak English.
Have a challenge for every day!

@jrlacharnay
Copy link

jrlacharnay commented Oct 16, 2023

Hello,

I'm using ZHA and still I can't configure the switch type (toggle or push button) of my Aqara SSM-U01 (the initial problem reported).

Or did I miss something?
Should I create another ticket?

Zigbee signature:

{
  "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.FullFunctionDevice|MainsPowered|RxOnWhenIdle|AllocateAddress: 142>, manufacturer_code=4447, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *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": "0x0100",
      "input_clusters": [
        "0x0000",
        "0x0002",
        "0x0003",
        "0x0004",
        "0x0005",
        "0x0006",
        "0x0009",
        "0x000a",
        "0x0702",
        "0x0b04",
        "0xfcc0"
      ],
      "output_clusters": [
        "0x0019"
      ]
    },
    "21": {
      "profile_id": "0x0104",
      "device_type": "0x0100",
      "input_clusters": [
        "0x000c"
      ],
      "output_clusters": []
    },
    "31": {
      "profile_id": "0x0104",
      "device_type": "0x0100",
      "input_clusters": [
        "0x000c"
      ],
      "output_clusters": []
    },
    "41": {
      "profile_id": "0x0104",
      "device_type": "0x0100",
      "input_clusters": [
        "0x0012"
      ],
      "output_clusters": []
    },
    "242": {
      "profile_id": "0xa1e0",
      "device_type": "0x0061",
      "input_clusters": [],
      "output_clusters": [
        "0x0021"
      ]
    }
  },
  "manufacturer": "LUMI",
  "model": "lumi.switch.n0agl1",
  "class": "zigpy.device.Device"
}

@w-marco
Copy link

w-marco commented Oct 28, 2023

I also still cannot edit the switch_type with my Aqara T1.

I noticed, that the device info shows no quirk applied, even though there is one present in zhaquirks.
So it looks like matching the quirk to the device doesn't work.

TheJulianJES added a commit to TheJulianJES/zha-device-handlers that referenced this issue Oct 28, 2023
@TheJulianJES
Copy link
Collaborator

@jrlacharnay You can try to download the file from #2684 and test it as a custom quirk.

In the future, just open a new issue please. I only saw this because someone else had another alternative signature for this device.

The fix will likely only be included in Home Assistant Core 2023.12.0, as the 2023.11.x beta cut is already made (for features).

TheJulianJES added a commit that referenced this issue Nov 9, 2023
* Add alternative signature to Aqara T1 Relay

* Also add `lumi.switch.n0acn2`, even though unconfirmed

* Add yet another alternative signature: #1231 (comment)
@jrlacharnay
Copy link

@TheJulianJES sorry for the late answer. First, big thanks for the works on this quirk. I tested, and after having re-paired my 3 T1 devices:

  • The light entities have been replaced by a switch entity (but I could transform them to a light entity directly in ZHA UI)
  • Still I couldn't see the "switch type" configuration.
  • I had some stability issues (disconnections from Zigbee network) so I removed the quirk. I'm not sure however if it's linked to that because I did other changes at the same time (tried to update the Zigbee channel). However, after removing the quirk, the 3 T1 devices stopped to disconnect.

I'm available (and will try to answer quicker) for any additional testing.

@w-marco
Copy link

w-marco commented Nov 19, 2023

@jrlacharnay to change the switch type go into the device, then the three dot menu, then 'manage zigbee device'.
Choose the 'OppleCluster' 0xfcc0 and then change the attribute 'swtich_type'.
1 is toggle, 2 is momentary.

as for the disconnect issues: I sporadically had that too, but also with Zigbee2MQTT so I don't think it is the quirk.
I fixed it, by forcing the disconnecting devices to report their on/off status more often, thus keeping their connection alive. Ever since then, my issues disappeared. To do that using ZHA, I installed ZHA Toolkit from HACS and then issued this command under 'Developer Tools', 'Services':

service: zha_toolkit.execute
data:
  ieee: switch.XXXXX
  command: conf_report
  endpoint: 1
  cluster: 0x0006
  attribute: 0x0000
  min_interval: 5
  max_interval: 60
  tries: 100
  event_done: zha_done

Replace switch.XXX with your entity of the device that's disconnecting.

@jrlacharnay
Copy link

jrlacharnay commented Nov 19, 2023

Thanks, indeed I can change the switch type with the OppleCluster.

Do you know if it's possible to have the setting displayed in the ZHA UI?
Currently I only have the "start-up behavior" setting:

image

Else, all non-technical people will never find how to change the switch type.

Also, I can confirm that, as soon as I activate the quirk, the devices are very often and momentarily "unavailable". I didn't try yet the conf_report command (thanks, I didn't know ZHA toolkit!), but this is for sure not happening without the quirk.

@w-marco
Copy link

w-marco commented Nov 19, 2023

I talked to @TheJulianJES about displaying them in the Discord a while ago.
It's certainly possible but no one came around to doing it yet. It needs to be implemented by the devs.

As fir the disconnects, that's interesting as I haven't had this, not sure what the cause could be with the Quirk.
But maybe the conf_report command can fix it.

@jrlacharnay
Copy link

@TheJulianJES, I had the same disconnection issues after the upgrade to HA 2023.12.
Removing devices and pairing them again didn't help (I was actually unable to pair them).

I don't know if I'm the only one impacted, and I didn't see any new issue reported for that, but I would suggest removing the device signature (which I posted above) from the quirk.

@dumpfheimer
Copy link
Contributor

dumpfheimer commented Dec 8, 2023

To be honest I have done this already but habe not come around to making a PR due to the requirements they have for PRs. Would someone want to test?

https://github.com/dumpfheimer/core/tree/dumpfheimer/zha-xiaomi-opple-configuration-entities

I have just noticed that something has changed in zhaquirks too which probably breaks this..

elupus pushed a commit to elupus/zha-device-handlers that referenced this issue Jan 17, 2024
* Add alternative signature to Aqara T1 Relay

* Also add `lumi.switch.n0acn2`, even though unconfirmed

* Add yet another alternative signature: zigpy#1231 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
workaround available The issue can be worked around
Projects
None yet
Development

Successfully merging a pull request may close this issue.