zigpy / zha-device-handlers

ZHA device handlers bridge the functionality gap created when manufacturers deviate from the ZCL specification, handling deviations and exceptions by parsing custom messages to and from Zigbee devices.
Apache License 2.0
729 stars 675 forks source link

[Device Support Request] Quirk for QBKG39LM (lumi.switch.b2lc04) to support decoupled mode #1810

Open xardas-eu opened 1 year ago

xardas-eu commented 1 year ago

Is your feature request related to a problem? Please describe.

Hi. I'm trying to get the decoupled mode on this switch working. I was using https://github.com/zigpy/zha-device-handlers/issues/365 as inspiration, but writing the attribute to that cluster does not change the way the device functions.

I think a quirk is needed to set this attribute at setup time (may be mistaken, still a Zigbee-noob)

Describe the solution you'd like A custom quirk that allows to use this device in decoupled mode (so that pressing the buttons sends events instead of triggering the relay)

Device signature ```yaml { "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4447, maximum_buffer_size=127, maximum_incoming_transfer_size=100, server_mask=11264, maximum_outgoing_transfer_size=100, descriptor_capability_field=, *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": 260, "device_type": "0x0100", "in_clusters": [ "0x0000", "0x0002", "0x0003", "0x0004", "0x0005", "0x0006", "0x0012", "0xfcc0" ], "out_clusters": [ "0x000a", "0x0019" ] }, "2": { "profile_id": 260, "device_type": "0x0100", "in_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0x0012", "0xfcc0" ], "out_clusters": [] }, "41": { "profile_id": 260, "device_type": "0x0100", "in_clusters": [ "0x0012" ], "out_clusters": [] }, "42": { "profile_id": 260, "device_type": "0x0100", "in_clusters": [ "0x0012" ], "out_clusters": [] }, "51": { "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.b2lc04", "class": "zigpy.device.Device" } ```
Diagnostic information ```yaml ```
Additional logs ``` ```

Thanks!

javicalle commented 1 year ago

Just create a quirk file with your device signature, and in the replacement part just put the same and replace the BasicCluster with the BasicClusterDecoupled class.

You can take the CtrlLn class as 'inspiration' because probably you will need also replace the MultistateInput cluster:

Inside that class there are both 'new' classes implemented.

typhoon2099 commented 1 year ago

@xardas-eu Did you manage to create a quirk for this switch? I'm trying to use decoupled mode in ZHA but have no idea how to replicate the device signature in the quirk class (as @javicalle suggested doing). There are too many imported values to be able to easily tell if I have set up the signature correctly.

EDIT: Also, my device signature looks quite different:

{
  "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=4447, maximum_buffer_size=127, maximum_incoming_transfer_size=100, server_mask=11264, maximum_outgoing_transfer_size=100, 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": 260,
      "device_type": "0x0100",
      "in_clusters": [
        "0x0000",
        "0x0002",
        "0x0003",
        "0x0004",
        "0x0005",
        "0x0006",
        "0x0009"
      ],
      "out_clusters": [
        "0x000a",
        "0x0019"
      ]
    },
    "2": {
      "profile_id": 260,
      "device_type": "0x0100",
      "in_clusters": [
        "0x0000",
        "0x0003",
        "0x0004",
        "0x0005",
        "0x0006"
      ],
      "out_clusters": []
    },
    "242": {
      "profile_id": 41440,
      "device_type": "0x0061",
      "in_clusters": [],
      "out_clusters": [
        "0x0021"
      ]
    }
  },
  "manufacturer": "LUMI",
  "model": "lumi.switch.b2lc04",
  "class": "zigpy.device.Device"
}
typhoon2099 commented 1 year ago

I have this so far but it's not getting picked up, so I've done something wrong (and have no way of knowing what I've done wrong since I'm just guessing):

"""Xiaomi aqara single key wall switch devices."""

from zigpy import types as t
from zigpy.profiles import zha
from zigpy.zcl.clusters.general import (
    AnalogInput,
    Basic,
    BinaryOutput,
    DeviceTemperature,
    Groups,
    Identify,
    MultistateInput,
    OnOff,
    Ota,
    Scenes,
    Time,
)

from zhaquirks import Bus, EventableCluster
from zhaquirks.const import (
    ARGS,
    ATTRIBUTE_ID,
    ATTRIBUTE_NAME,
    BUTTON_1,
    BUTTON_2,
    BUTTON_3,
    CLUSTER_ID,
    COMMAND,
    COMMAND_ATTRIBUTE_UPDATED,
    DEVICE_TYPE,
    DOUBLE_PRESS,
    ENDPOINT_ID,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
    SHORT_PRESS,
    SKIP_CONFIGURATION,
    VALUE,
)
from zhaquirks.xiaomi import (
    LUMI,
    AnalogInputCluster,
    BasicCluster,
    OnOffCluster,
    XiaomiCustomDevice,
    XiaomiPowerConfiguration,
)

ATTRIBUTE_PRESENT_VALUE = "present_value"

class CtrlLn(XiaomiCustomDevice):
    """Aqara double key switch device."""

    class BasicClusterDecoupled(BasicCluster):
        """Adds attributes for decoupled mode."""

        # Known Options for 'decoupled_mode_<button>':
        # * 254 (decoupled)
        # * 18 (relay controlled)
        attributes = BasicCluster.attributes.copy()
        attributes.update(
            {
                0xFF22: ("decoupled_mode_left", t.uint8_t, True),
                0xFF23: ("decoupled_mode_right", t.uint8_t, True),
            }
        )

    class WallSwitchMultistateInputCluster(EventableCluster, MultistateInput):
        """WallSwitchMultistateInputCluster: fire events corresponding to press type."""

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

    signature = {
        MODELS_INFO: [(LUMI, "lumi.switch.b2lc04")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    XiaomiPowerConfiguration.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    Time.cluster_id,
                    BinaryOutput.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    BinaryOutput.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id, 
                ],
                OUTPUT_CLUSTERS: [],
            },
            242: {
                # "profile_id": 41440,
                # "device_type": "0x0061",
                # "in_clusters": [],
                # "out_clusters": ["0x0021"]
                PROFILE_ID: 0xA1E0,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [0x0021],
            },
        },
    }

    replacement = {
        SKIP_CONFIGURATION: True,
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    BasicClusterDecoupled,
                    XiaomiPowerConfiguration.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOffCluster,
                    Time.cluster_id,
                    BinaryOutput.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    BinaryOutput.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id, 
                ],
                OUTPUT_CLUSTERS: [],
            },
            242: {
                # "profile_id": 41440,
                # "device_type": "0x0061",
                # "in_clusters": [],
                # "out_clusters": ["0x0021"]
                PROFILE_ID: 0xA1E0,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [0x0021],
            },
        },
    }

    device_automation_triggers = {
        (SHORT_PRESS, BUTTON_1): {
            ENDPOINT_ID: 5,
            CLUSTER_ID: 18,
            COMMAND: COMMAND_ATTRIBUTE_UPDATED,
            ARGS: {ATTRIBUTE_ID: 85, ATTRIBUTE_NAME: ATTRIBUTE_PRESENT_VALUE, VALUE: 1},
        },
        (DOUBLE_PRESS, BUTTON_1): {
            ENDPOINT_ID: 5,
            CLUSTER_ID: 18,
            COMMAND: COMMAND_ATTRIBUTE_UPDATED,
            ARGS: {ATTRIBUTE_ID: 85, ATTRIBUTE_NAME: ATTRIBUTE_PRESENT_VALUE, VALUE: 2},
        },
        (SHORT_PRESS, BUTTON_2): {
            ENDPOINT_ID: 6,
            CLUSTER_ID: 18,
            COMMAND: COMMAND_ATTRIBUTE_UPDATED,
            ARGS: {ATTRIBUTE_ID: 85, ATTRIBUTE_NAME: ATTRIBUTE_PRESENT_VALUE, VALUE: 1},
        },
        (DOUBLE_PRESS, BUTTON_2): {
            ENDPOINT_ID: 6,
            CLUSTER_ID: 18,
            COMMAND: COMMAND_ATTRIBUTE_UPDATED,
            ARGS: {ATTRIBUTE_ID: 85, ATTRIBUTE_NAME: ATTRIBUTE_PRESENT_VALUE, VALUE: 2},
        },
        (SHORT_PRESS, BUTTON_3): {
            ENDPOINT_ID: 7,
            CLUSTER_ID: 18,
            COMMAND: COMMAND_ATTRIBUTE_UPDATED,
            ARGS: {ATTRIBUTE_ID: 85, ATTRIBUTE_NAME: ATTRIBUTE_PRESENT_VALUE, VALUE: 1},
        },
        (DOUBLE_PRESS, BUTTON_3): {
            ENDPOINT_ID: 7,
            CLUSTER_ID: 18,
            COMMAND: COMMAND_ATTRIBUTE_UPDATED,
            ARGS: {ATTRIBUTE_ID: 85, ATTRIBUTE_NAME: ATTRIBUTE_PRESENT_VALUE, VALUE: 2},
        },
    }

Any advise would be greatly appreciated.

javicalle commented 1 year ago

You need to match the signature from your device with the one in the quirk. Your's device signature for endpoint 1 is:

    "1": {
      "profile_id": 260,
      "device_type": "0x0100",
      "in_clusters": [
        "0x0000",
        "0x0002",
        "0x0003",
        "0x0004",
        "0x0005",
        "0x0006",
        "0x0009"
      ],
      "out_clusters": [
        "0x000a",
        "0x0019"
      ]
    },

And your quirk have:

            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    XiaomiPowerConfiguration.cluster_id,
                    DeviceTemperature.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    Time.cluster_id,
                    BinaryOutput.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },

Check the cluster_id from here (or other classes): https://github.com/zigpy/zigpy/blob/dev/zigpy/zcl/clusters/general.py

I believe that other endpoints are fine, but I'm checking from mobile.

typhoon2099 commented 1 year ago

Ah, that seems to have been the problem!

I've got the option to Read/Write decoupled mode for the switches now, but still haven't actually managed to set decoupled mode. The attribute seems to update but the switch doesn't change. I've added the manufacturer override (4447) and get a big green tick from Home Assistant, but don't see anything change. The relay is still firing and I don't get any ZHA events, which suggests that something isn't right still...

typhoon2099 commented 1 year ago

I think I'm missing the MultiStateInput clusters (0x0012), which means I don't have access to the events I need. Does this sound right? I'm not sure why I have a different signature, could this be related to the coordinator I'm using?

javicalle commented 1 year ago

Quick & dirty proposal:

Add the EventableOnOffCluster class:

    class EventableOnOffCluster(EventableCluster, OnOff):
        """Eventable OnOff cluster: fire events corresponding to press type."""

Use it in the replacement part in sustitution to the OnOff cluster (for endpoint 1 & 2):

            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    BinaryOutput.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    EventableOnOffCluster, 
                ],
                OUTPUT_CLUSTERS: [],
            },

Save changes, delete any __pycache__ folder from local quirk, restart HA and test again.

typhoon2099 commented 1 year ago

Quick & dirty proposal:

Add the EventableOnOffCluster class:

    class EventableOnOffCluster(EventableCluster, OnOff):
        """Eventable OnOff cluster: fire events corresponding to press type."""

Use it in the replacement part in sustitution to the OnOff cluster (for endpoint 1 & 2):

            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    BinaryOutput.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    EventableOnOffCluster, 
                ],
                OUTPUT_CLUSTERS: [],
            },

Save changes, delete any __pycache__ folder from local quirk, restart HA and test again.

That's sorted events working, but only on off, no double click (which I assume is because I can't convince the switches to decouple). It's that or the device_automation_triggers buttons are set up incorrectly (which I also wouldn't be surprised by).

javicalle commented 1 year ago

Z2M implementation is here:

Seems being using 4447 as manufacturer code (for using it in the decouple command). Also seems that device is using a custom cluster or similar for the MultistateInput not sure which one. I would try to add the WallSwitchMultistateInputCluster in the replacement part for both enpoints.

typhoon2099 commented 1 year ago

I've used 4447 as the manufacturer code, it doesn't work. I've also tried updating using zha.set_zigbee_cluster_attribute service and get an error.

WallSwitchMultistateInputCluster doesn't seem to make a difference to the reported events (and I confirmed by replacing EventableOnoffCluster with OnOff.cluster_id which stopped all events.

I'm starting to wonder if something is wrong with the device. I don't have the same signature that @xardas-eu has, and the extra endpoints that I'm missing seem to be something to do with multi state input...

MattWestb commented 1 year ago

@typhoon2099 Witch coordinator are you using and witch firmware is it running ?

typhoon2099 commented 1 year ago

Well, it looks like if I set up the replacement to look like @xardas-eu's signature then I can get events working. I had to revert to OnOff.cluster_id to prevent multiple events.

I still can't get the device decoupled, that's a work in progress.

@MattWestb I'm on firmware 6.0.3-64, I couldn't tell you what coordinator it is, I got it from either Amazon or eBay around 3 years ago, so I can't find a device name. Home Assistant sees it as EZSP = Silicon Labs EmberZNet protocol: Elelabs, HUSBZB-1, Telegesis by ZHA. I've looked at a firmware updater which reported the following:

{"ports": [{"port": "/dev/ttyUSB0", "vid": "1A86", "pid": "7523", "deviceType": "zigbee", "stackVersion": "6.0.3-64"}]}

I got scared to do a firmware update, then when I decided to give it a go it failed because it needed a gbl file and the firmware updater only had ebl files included.

I don't think this is a coordinator issue though, I have an Aqara D1 (2 gang, no neutral) and was able to decouple that just a few days ago.

MattWestb commented 1 year ago

EZSP shall working OK with setting manufacture code for strange device but i dont knowing if its working OK on very old 6.0.X firmware.

Do you have some picture of the device / chip ? If its one standard design its very likely we have getting new cooked firmware for it. And its many bugs in the old stack that can being good getting fixed (but not one must). If the bootloader is very old is only supporting EBL files and if its little more modern it supporting both EBL and GBL files for updating so it shall being OK.

javicalle commented 1 year ago

I still can't get the device decoupled, that's a work in progress.

Not sure which one is the aqaraOpple cluster in Z2M, but seems that the decouple attribute is 0x0200: https://github.com/Koenkk/zigbee-herdsman-converters/blob/b06b48efee3df32a87bfa1b7f6fb2f00bda7aa15/converters/toZigbee.js#L2460-L2471

typhoon2099 commented 1 year ago

Looks like it might be 0xfcc0. There's an example in https://github.com/zigpy/zha-device-handlers/blob/a1cf999160f73556c1ba0c8302fd00b9e0b65ae3/zhaquirks/xiaomi/aqara/opple_remote.py and it's mentioned in the signature that @xardas-eu posted. I'll try that tomorrow.

typhoon2099 commented 1 year ago

Success! I imported OppleCluster and added it to endpoints 1 and 2, which gave me working options for decoupling. If I get a chance I'll try and contribute this back to the repo.

Thanks for the help!

javicalle commented 1 year ago

If I get a chance I'll try and contribute this back to the repo.

Do it please. Probably quirk needs to be tweaked but it will be easier from a PR.

typhoon2099 commented 1 year ago

Yul, probably a bunch of stuff in there I don't actually need. When it gets to PR I'll point out the difference in signatures, just in case that's an issue.

@MattWestb Here's a photo of the coordinator, I forgot it had a model code on it (ELU013): IMG_20230311_100746

EDIT: Which of course returns plenty of search results: https://elelabs.com/products/elelabs-usb-adapter.html

EDIT2: And here's the upgrade utility

MattWestb commented 1 year ago

The ZHA team have making one stable EZSP 6.7.8 that is the recommended version stable version for production systems. https://github.com/zha-ng/EZSP-Firmware/tree/master/Elelabs-ELU013#efr32mg13p-v8-678-sw-115200

I shall being safe flashing it on your dongle and most of the community users and devs is running it for over 2 years now.

Sadly they have not making one EZSP 6.10.3.0 that is the most up to date for this chips but perhaps is coming.

Its only recommended updating the firmware not one must !!!

DeadlySin2 commented 1 year ago

Can you please share a quirk file please. I have the same switch and want to add this feature to ZHA

typhoon2099 commented 1 year ago
"""Xiaomi aqara single key wall switch devices."""

from zigpy import types as t
from zigpy.profiles import zha
from zigpy.zcl.clusters.general import (
    AnalogInput,
    Basic,
    BinaryOutput,
    DeviceTemperature,
    Groups,
    Identify,
    MultistateInput,
    OnOff,
    Ota,
    Scenes,
    Time,
    Alarms,
)

from zhaquirks import Bus, EventableCluster
from zhaquirks.const import (
    ARGS,
    ATTRIBUTE_ID,
    ATTRIBUTE_NAME,
    BUTTON_1,
    BUTTON_2,
    CLUSTER_ID,
    COMMAND,
    COMMAND_ATTRIBUTE_UPDATED,
    DEVICE_TYPE,
    DOUBLE_PRESS,
    ENDPOINT_ID,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
    SHORT_PRESS,
    SKIP_CONFIGURATION,
    VALUE,
)
from zhaquirks.xiaomi import (
    LUMI,
    AnalogInputCluster,
    BasicCluster,
    OnOffCluster,
    XiaomiCustomDevice,
    XiaomiPowerConfiguration,
)
from zhaquirks.xiaomi.aqara.opple_switch import (
    OppleSwitchCluster,
)

ATTRIBUTE_PRESENT_VALUE = "present_value"

class CtrlLn(XiaomiCustomDevice):
    """Aqara double key switch device."""

    class WallSwitchMultistateInputCluster(EventableCluster, MultistateInput):
        """WallSwitchMultistateInputCluster: fire events corresponding to press type."""

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

    # 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=4447, maximum_buffer_size=127, maximum_incoming_transfer_size=100, server_mask=11264, maximum_outgoing_transfer_size=100, 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)",
    signature = {
        #  "manufacturer": "LUMI",
        #  "model": "lumi.switch.b2lc04",
        MODELS_INFO: [(LUMI, "lumi.switch.b2lc04")],
        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,
                ],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id, 
                ],
                OUTPUT_CLUSTERS: [],
            },
            242: {
                PROFILE_ID: 0xA1E0,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [0x0021],
            },
        },
    }

    replacement = {
        SKIP_CONFIGURATION: True,
        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,
                    OppleSwitchCluster,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    OppleSwitchCluster,
                ],
                OUTPUT_CLUSTERS: [],
            },
            41: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    WallSwitchMultistateInputCluster,
                ],
                OUTPUT_CLUSTERS: [],
            },
            42: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    WallSwitchMultistateInputCluster,
                ],
                OUTPUT_CLUSTERS: [],
            },
            51: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    WallSwitchMultistateInputCluster,
                ],
                OUTPUT_CLUSTERS: [],
            },
            242: {
                PROFILE_ID: 0xA1E0,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [0x0021],
            },
        },
    }

I still need to get this into a PR with some proper testing, but this should work fine (does for me anyway).

TheJulianJES commented 8 months ago

Whilst looking at https://github.com/zigpy/zha-device-handlers/pull/2912 (thanks for the PR!), I noticed that both signatures shared in this issue might already match existing quirks when the model name is added. I've opened up another PR:

You should be able to install the linked file from that PR as a custom quirk to see if it fixes your issue. Since there seem to be at least two different signatures for this device, please all let me know if those changes work for you.

github-actions[bot] commented 2 months ago

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. Please make sure to update to the latest version and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue has now been marked as stale and will be closed if no further activity occurs. Thank you for your contributions.

typhoon2099 commented 2 months ago

I mean, I guess this is still active. I'm not sure what the state of the PRs are that are open for this though. I couldn't get the recommended quirk to work like my own, but I know that my PR needs some attention to get it up to standard...

czartm commented 1 month ago

Hello @typhoon2099

I just tried to install quirk for Aqara E1 but nothing changes in "manage device" section.

In YAML configuration I add lines for quirks:

zha:
  enable_quirks: true
  custom_quirks_path: /config/custom_zha_quirks/

and I add file called b2lc04.py into /config/custom_zha_quirks/

But there is no new clusters under ZigBee devices (see attachment):

lumi switch b2lc04

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=4447, maximum_buffer_size=127, maximum_incoming_transfer_size=100, server_mask=11264, maximum_outgoing_transfer_size=100, 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": "0x0100",
      "input_clusters": [
        "0x0000",
        "0x0002",
        "0x0003",
        "0x0004",
        "0x0005",
        "0x0006",
        "0x0009"
      ],
      "output_clusters": [
        "0x000a",
        "0x0019"
      ]
    },
    "2": {
      "profile_id": "0x0104",
      "device_type": "0x0100",
      "input_clusters": [
        "0x0000",
        "0x0003",
        "0x0004",
        "0x0005",
        "0x0006",
        "0x0012",
        "0xfcc0"
      ],
      "output_clusters": []
    },
    "242": {
      "profile_id": "0xa1e0",
      "device_type": "0x0061",
      "input_clusters": [],
      "output_clusters": [
        "0x0021"
      ]
    }
  },
  "manufacturer": "LUMI",
  "model": "lumi.switch.b2lc04",
  "class": "zigpy.device.Device"
}

Any idea? Something changed in quirks in ZHA? Thanks for help!