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
719 stars 664 forks source link

[Device Support Request] AQARA Switch E1 double - lumi.switch.b2nc01 (QBKG41LM) #2690

Open albalaing opened 10 months ago

albalaing commented 10 months ago

Problem description

This switch uses the OppleCluster for its configuration which is not implemented

Solution description

I have added the following attributes to OppleCluster 0x0200 Bdecoupled mode 0x0201 Power outage memory 0x00F0 Flip indicator light

Screenshots/Video

Screenshots/Video [Paste/upload your media here]

Device signature

Device signature ```json [Paste the device signature here] ```

Diagnostic information

Diagnostic information ```json [Paste the diagnostic information here] ```

Logs

Logs ```python ```

Custom quirk

Custom quirk ```python from zigpy import types as t from zigpy.profiles import zha from zigpy.quirks import CustomCluster from zigpy.zcl.clusters.general import ( AnalogInput, Basic, BinaryOutput, DeviceTemperature, Groups, Identify, MultistateInput, OnOff, Ota, Scenes, Time, GreenPowerProxy, ) 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, XiaomiAqaraE1Cluster, ) ATTRIBUTE_PRESENT_VALUE = "present_value" class QBKG41LM(XiaomiCustomDevice): """Aqara double key switch device.""" class OppleCluster(XiaomiAqaraE1Cluster): """Add Opple cluster for power outage memory attribute.""" attributes = { 0x200: ("decoupled_mode", t.uint8_t, True), 0x201: ("power_outage_memory", t.uint8_t, True), 0x0F0: ("flip_indicator_light", 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.b2nc01")], 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, MultistateInput.cluster_id, OppleCluster.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, MultistateInput.cluster_id, OppleCluster.cluster_id, ], OUTPUT_CLUSTERS: [], }, 41: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [MultistateInput.cluster_id], OUTPUT_CLUSTERS: [], }, 42: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [MultistateInput.cluster_id], OUTPUT_CLUSTERS: [], }, 51: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [MultistateInput.cluster_id], OUTPUT_CLUSTERS: [], }, 242: { PROFILE_ID: 0xa1e0, DEVICE_TYPE: 0x0061, INPUT_CLUSTERS: [], OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id], }, }, } replacement = { SKIP_CONFIGURATION: True, ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [ Basic.cluster_id, Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, OnOffCluster, OppleCluster, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, 2: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [ Basic.cluster_id, Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, OnOffCluster, OppleCluster, ], OUTPUT_CLUSTERS: [], }, 41: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [WallSwitchMultistateInputCluster], OUTPUT_CLUSTERS: [], }, 42: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [WallSwitchMultistateInputCluster], OUTPUT_CLUSTERS: [], }, 51: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [WallSwitchMultistateInputCluster], OUTPUT_CLUSTERS: [], }, }, } device_automation_triggers = { (SHORT_PRESS, BUTTON_1): { ENDPOINT_ID: 41, CLUSTER_ID: 18, COMMAND: COMMAND_ATTRIBUTE_UPDATED, ARGS: {ATTRIBUTE_ID: 85, ATTRIBUTE_NAME: ATTRIBUTE_PRESENT_VALUE, VALUE: 1}, }, (DOUBLE_PRESS, BUTTON_1): { ENDPOINT_ID: 41, CLUSTER_ID: 18, COMMAND: COMMAND_ATTRIBUTE_UPDATED, ARGS: {ATTRIBUTE_ID: 85, ATTRIBUTE_NAME: ATTRIBUTE_PRESENT_VALUE, VALUE: 2}, }, (SHORT_PRESS, BUTTON_2): { ENDPOINT_ID: 42, CLUSTER_ID: 18, COMMAND: COMMAND_ATTRIBUTE_UPDATED, ARGS: {ATTRIBUTE_ID: 85, ATTRIBUTE_NAME: ATTRIBUTE_PRESENT_VALUE, VALUE: 1}, }, (DOUBLE_PRESS, BUTTON_2): { ENDPOINT_ID: 42, CLUSTER_ID: 18, COMMAND: COMMAND_ATTRIBUTE_UPDATED, ARGS: {ATTRIBUTE_ID: 85, ATTRIBUTE_NAME: ATTRIBUTE_PRESENT_VALUE, VALUE: 2}, }, (SHORT_PRESS, BUTTON_3): { ENDPOINT_ID: 51, CLUSTER_ID: 18, COMMAND: COMMAND_ATTRIBUTE_UPDATED, ARGS: {ATTRIBUTE_ID: 85, ATTRIBUTE_NAME: ATTRIBUTE_PRESENT_VALUE, VALUE: 1}, }, (DOUBLE_PRESS, BUTTON_3): { ENDPOINT_ID: 51, CLUSTER_ID: 18, COMMAND: COMMAND_ATTRIBUTE_UPDATED, ARGS: {ATTRIBUTE_ID: 85, ATTRIBUTE_NAME: ATTRIBUTE_PRESENT_VALUE, VALUE: 2}, }, } ```

Additional information

No response

Muxa1L commented 8 months ago

@albalaing why this quirk may not work? Or it's not supposed to? Got following log messages trying to add device again

[0xC1C7:3:0x0006]: 'async_configure' stage failed: 'uint8_t' object is not subscriptable
[0x5B12:3:0x0006]: 'async_configure' stage failed: 'uint8_t' object is not subscriptable
[0x7A37:3:0x0006]: 'async_configure' stage failed: 'uint8_t' object is not subscriptable

But these may be from another source (dunno)

albalaing commented 8 months ago

@Muxa1L I have a switch that works without problem. This switch has the endpoints [1,2,41,42,51,242] and version 22

Since I had an unconfigured switch, I added it and the quirks did not work because it was identified with the enpoints [1,2,3,41,42,51,242]. I bought this switch later and it has version 25. Although I did not use the Quirks, it worked without problems. But it didn't give me that error.

Tell me the signature of your switch and the version to see if we can add it.

Note: The version is seen in: Basic Clusters (Endpoint id: 1, Id: 0x0000, Type: in) app_version attributes (id: 0x0001)

scotie commented 7 months ago

@albalaing For me your quirk doesn't seem to work, but I didn't have to look into it yet. I do have an issue open already with the signature if it helps. #2514

I'll try again a bit later and report back

FerrumLogic commented 1 month ago

Current quirk doesn't applied to my lumi.switch.b2nc01