-
Notifications
You must be signed in to change notification settings - Fork 737
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
Support for Aqara 2 Gang switch without neutral (lumi.switch.l2aeu1) #2270
Comments
Well, I think I got as far as I could Quirk so farimport copy
from enum import Enum
from zigpy import types as t
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zhaquirks import CustomCluster
from zigpy.zcl.clusters.general import (
Basic,
DeviceTemperature,
Groups,
Identify,
OnOff,
Ota,
Scenes,
Time,
MultistateInput,
GreenPowerProxy,
Alarms,
)
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
SHORT_PRESS,
TRIPLE_PRESS,
LONG_PRESS,
ALT_DOUBLE_PRESS,
DOUBLE_PRESS,
ALT_SHORT_PRESS,
LEFT,
RIGHT,
COMMAND_TOGGLE,
COMMAND,
BUTTON,
ENDPOINT_ID,
ARGS,
CLUSTER_ID,
ATTR_ID,
PRESS_TYPE,
VALUE,
)
from zhaquirks.xiaomi import (
LUMI
)
COMMAND_SINGLE = "single"
COMMAND_DOUBLE = "double"
COMMAND_BUTTON_HOLD = "button_hold"
from zhaquirks.xiaomi.aqara.opple_switch import (OppleSwitchCluster, BOTH_BUTTONS)
from zhaquirks.xiaomi.aqara.opple_remote import (
MultistateInputCluster,
OppleCluster,
OPPLE_CLUSTER_ID
)
class XiaomiAqaraOpMode(t.uint8_t, Enum):
Decoupled = 0x00
Coupled = 0x01
class XiaomiAqaraFlickerMode(t.uint16_t, Enum):
Anti_flicker = 0x0004
Quick = 0x0001
class XiaomiAqaraIndicatorLight(t.uint8_t, Enum):
Normal = 0x00
Reverse = 0x01
class XiaomiAqaraOperationMode(t.uint8_t, Enum):
"""Opple operation_mode enum."""
Decoupled = 0x00
Coupled = 0x01
class XiaomiAqaraMasterCluster(OppleCluster):
attributes = copy.deepcopy(OppleCluster.attributes)
attributes.update(
{
0x0004: ("anti_flicker", XiaomiAqaraFlickerMode, True),
0x0002: ("power_outage_count", t.uint8_t, True),
0x0201: ("power_outage_memory", t.Bool, True),
0x0203: ("led_disabled_night", t.Bool, True),
0x00F0: ("indicator_light", XiaomiAqaraIndicatorLight, True),
0x0200: ("operation_mode", XiaomiAqaraOperationMode, True),
}
)
class XiaomiAqaraSecondaryCluster(CustomCluster):
ep_attribute = "opple_cluster"
cluster_id = OPPLE_CLUSTER_ID
attributes = (
{
0x0200: ("operation_mode", XiaomiAqaraOperationMode, True),
}
)
class XiaomiAqaraWSEUK02(CustomDevice):
"""WS-EUK02 Aqara smart wall switch H1 EU (no neutral, double rocker)"""
signature = {
MODELS_INFO: [(LUMI, "lumi.switch.l2aeu1")],
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,
MultistateInput.cluster_id,
OppleSwitchCluster.cluster_id,
],
OUTPUT_CLUSTERS: [],
},
242: {
PROFILE_ID: 0xA1E0,
DEVICE_TYPE: 0x0061,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
},
}
replacement = {
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,
XiaomiAqaraMasterCluster,
],
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,
MultistateInputCluster,
XiaomiAqaraSecondaryCluster,
],
OUTPUT_CLUSTERS: [],
},
242: {
PROFILE_ID: 0xA1E0,
DEVICE_TYPE: 0x0061,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
}
}
device_automation_triggers = {
(SHORT_PRESS, LEFT): {ENDPOINT_ID:41, CLUSTER_ID : MultistateInputCluster.cluster_id, ARGS: {ATTR_ID: 0x0055, PRESS_TYPE: COMMAND_SINGLE, VALUE: 1}},
(DOUBLE_PRESS, LEFT): {ENDPOINT_ID:41, CLUSTER_ID : MultistateInputCluster.cluster_id, ARGS: {ATTR_ID: 0x0055, PRESS_TYPE: COMMAND_DOUBLE, VALUE: 2}},
(SHORT_PRESS, RIGHT): {ENDPOINT_ID:42, CLUSTER_ID : MultistateInputCluster.cluster_id, ARGS: {ATTR_ID: 0x0055, PRESS_TYPE: COMMAND_SINGLE, VALUE: 1}},
(DOUBLE_PRESS, RIGHT): {ENDPOINT_ID:42, CLUSTER_ID : MultistateInputCluster.cluster_id, ARGS: {ATTR_ID: 0x0055, PRESS_TYPE: COMMAND_DOUBLE, VALUE: 2}},
(SHORT_PRESS, BOTH_BUTTONS): {ENDPOINT_ID:42, CLUSTER_ID : MultistateInputCluster.cluster_id, ARGS: {ATTR_ID: 0x0055, PRESS_TYPE: COMMAND_SINGLE, VALUE: 1}},
(DOUBLE_PRESS, BOTH_BUTTONS): {ENDPOINT_ID:42, CLUSTER_ID : MultistateInputCluster.cluster_id, ARGS: {ATTR_ID: 0x0055, PRESS_TYPE: COMMAND_DOUBLE, VALUE: 2}},
(COMMAND_BUTTON_HOLD, BOTH_BUTTONS): {ENDPOINT_ID: 1, CLUSTER_ID: XiaomiAqaraMasterCluster.cluster_id, ARGS: {ATTR_ID: 0x00FC, VALUE: 0, PRESS_TYPE: COMMAND_BUTTON_HOLD}},
} The buttons work like this, left button is source_endpoint 41, right button is source_endpoint 42, both buttons is 51 It seems that ZHA cannot decode the values as event, I don't know, just a packet
Maybe you will be able to fix the problem, my head explodes now :) |
I managed to do it, it took some effort If someone want's to use it, please go ahead aqara_i2aeu1.pyimport copy
from enum import Enum
from zigpy import types as t
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zhaquirks import CustomCluster
from zigpy.zcl.clusters.general import (
Basic,
DeviceTemperature,
Groups,
Identify,
OnOff,
Ota,
Scenes,
Time,
MultistateInput,
GreenPowerProxy,
Alarms,
)
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
SHORT_PRESS,
TRIPLE_PRESS,
LONG_PRESS,
ALT_DOUBLE_PRESS,
DOUBLE_PRESS,
ALT_SHORT_PRESS,
LEFT,
RIGHT,
COMMAND_TOGGLE,
COMMAND,
BUTTON,
ENDPOINT_ID,
ARGS,
CLUSTER_ID,
ATTR_ID,
PRESS_TYPE,
VALUE,
ZHA_SEND_EVENT,
COMMAND_HOLD,
COMMAND_TRIPLE
)
from zhaquirks.xiaomi import (
LUMI
)
COMMAND_SINGLE = "single"
COMMAND_DOUBLE = "double"
BUTTON_ANY = "any"
LEFT_BUTTON_ENDPOINT=41
RIGHT_BUTTON_ENDPOINT=42
BOTH_BUTTONS_ENDPOINT=51
from zhaquirks.xiaomi.aqara.opple_switch import (OppleSwitchCluster, BOTH_BUTTONS)
from zhaquirks.xiaomi.aqara.opple_remote import (
OppleCluster,
OPPLE_CLUSTER_ID,
STATUS_TYPE_ATTR,
PRESS_TYPES
)
class XiaomiAqaraOpMode(t.uint8_t, Enum):
Decoupled = 0x00
Coupled = 0x01
class XiaomiAqaraFlickerMode(t.uint16_t, Enum):
Anti_flicker = 0x0004
Quick = 0x0001
class XiaomiAqaraIndicatorLight(t.uint8_t, Enum):
Normal = 0x00
Reverse = 0x01
class XiaomiAqaraOperationMode(t.uint8_t, Enum):
Decoupled = 0x00
Coupled = 0x01
class XiaomiAqaraMasterCluster(OppleCluster):
attributes = copy.deepcopy(OppleCluster.attributes)
attributes.update(
{
0x0004: ("anti_flicker", XiaomiAqaraFlickerMode, True),
0x0002: ("power_outage_count", t.uint8_t, True),
0x0201: ("power_outage_memory", t.Bool, True),
0x0203: ("led_disabled_night", t.Bool, True),
0x00F0: ("indicator_light", XiaomiAqaraIndicatorLight, True),
0x0200: ("operation_mode", XiaomiAqaraOperationMode, True),
}
)
def _update_attribute(self, attrid, value):
super()._update_attribute(attrid, value)
if attrid == 0x00FC and value == False:
event_args = {
BUTTON: BUTTON_ANY,
PRESS_TYPE: COMMAND_HOLD,
ATTR_ID: attrid,
VALUE: value,
}
action = "{}_{}".format(BUTTON_ANY, COMMAND_HOLD)
self.listener_event(ZHA_SEND_EVENT, action, event_args)
super()._update_attribute(0, action)
# elif attrid == 0x00f7:
# event_args = {
# BUTTON: BUTTON_ANY,
# PRESS_TYPE: COMMAND_TRIPLE,
# ATTR_ID: attrid
# }
# action = "{}_{}".format(BUTTON_ANY, COMMAND_TRIPLE)
# self.listener_event(ZHA_SEND_EVENT, action, event_args)
# super()._update_attribute(0, action)
class XiaomiAqaraSecondaryCluster(CustomCluster):
ep_attribute = "opple_cluster"
cluster_id = OPPLE_CLUSTER_ID
attributes = (
{
0x0200: ("operation_mode", XiaomiAqaraOperationMode, True),
}
)
class MultistateInputCluster(CustomCluster, MultistateInput):
cluster_id = MultistateInput.cluster_id
def __init__(self, *args, **kwargs):
self._current_state = None
super().__init__(*args, **kwargs)
async def configure_reporting(
self,
attribute,
min_interval,
max_interval,
reportable_change,
manufacturer=None,
): """Configure reporting."""
def _update_attribute(self, attrid, value):
super()._update_attribute(attrid, value)
if attrid == STATUS_TYPE_ATTR:
self._current_state = PRESS_TYPES.get(value)
event_args = {
BUTTON: self.endpoint.endpoint_id,
PRESS_TYPE: self._current_state,
ATTR_ID: attrid,
VALUE: value,
}
button = None
if self.endpoint.endpoint_id == LEFT_BUTTON_ENDPOINT:
button=LEFT
elif self.endpoint.endpoint_id == RIGHT_BUTTON_ENDPOINT:
button=RIGHT
elif self.endpoint.endpoint_id == BOTH_BUTTONS_ENDPOINT:
button=BOTH_BUTTONS
action=action = "{}_{}".format(self.endpoint.endpoint_id, self._current_state)
if button != None:
action = "{}_{}".format(button, self._current_state)
self.listener_event(ZHA_SEND_EVENT, action, event_args)
super()._update_attribute(0, action)
class XiaomiAqaraWSEUK02(CustomDevice):
"""WS-EUK02 Aqara smart wall switch H1 EU (no neutral, double rocker)"""
signature = {
MODELS_INFO: [(LUMI, "lumi.switch.l2aeu1")],
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,
MultistateInput.cluster_id,
OppleSwitchCluster.cluster_id,
],
OUTPUT_CLUSTERS: [],
},
242: {
PROFILE_ID: 0xA1E0,
DEVICE_TYPE: 0x0061,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
},
}
replacement = {
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,
MultistateInputCluster,
XiaomiAqaraMasterCluster,
],
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,
MultistateInputCluster,
XiaomiAqaraSecondaryCluster,
],
OUTPUT_CLUSTERS: [],
},
LEFT_BUTTON_ENDPOINT: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
MultistateInputCluster,
],
OUTPUT_CLUSTERS: [],
},
RIGHT_BUTTON_ENDPOINT: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
MultistateInputCluster,
],
OUTPUT_CLUSTERS: [],
},
BOTH_BUTTONS_ENDPOINT: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
MultistateInputCluster,
],
OUTPUT_CLUSTERS: [],
},
242: {
PROFILE_ID: 0xA1E0,
DEVICE_TYPE: 0x0061,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
}
}
device_automation_triggers = {
(SHORT_PRESS, LEFT): { COMMAND: "{}_{}".format(LEFT, COMMAND_SINGLE)},
(DOUBLE_PRESS, LEFT): { COMMAND: "{}_{}".format(LEFT, COMMAND_DOUBLE)},
(SHORT_PRESS, RIGHT): { COMMAND: "{}_{}".format(RIGHT, COMMAND_SINGLE)},
(DOUBLE_PRESS, RIGHT): { COMMAND: "{}_{}".format(RIGHT, COMMAND_DOUBLE)},
(SHORT_PRESS, BOTH_BUTTONS): { COMMAND: "{}_{}".format(BOTH_BUTTONS, COMMAND_SINGLE)},
(DOUBLE_PRESS, BOTH_BUTTONS): { COMMAND: "{}_{}".format(BOTH_BUTTONS, COMMAND_DOUBLE)},
(COMMAND_HOLD, BUTTON): { COMMAND: "{}_{}".format(BUTTON_ANY, COMMAND_HOLD)},
} |
FYI @TheJulianJES |
We can leave this open for now (until zha-quirks maybe fixes this). |
@sophipl thank you! Decoupling worked and both the single and double press automations work flawlessly! |
@grzegor Thanks! :) |
@sophipl hello! I just received my EDIT: I can see two clusters: EDIT2: Send a zero. I tried everything except writing a zero. Sorry! Thanks for the Quirk. You're awesome. |
@cpressland Great that you figured out! |
I needed to edit this quirk. I don't know why my switch has more Device 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",
"0x0012",
"0xfcc0"
],
"output_clusters": [
"0x000a",
"0x0019"
]
},
"2": {
"profile_id": "0x0104",
"device_type": "0x0100",
"input_clusters": [
"0x0000",
"0x0003",
"0x0004",
"0x0005",
"0x0006",
"0x0012",
"0xfcc0"
],
"output_clusters": []
},
"41": {
"profile_id": "0x0104",
"device_type": "0x0100",
"input_clusters": [
"0x0012"
],
"output_clusters": []
},
"42": {
"profile_id": "0x0104",
"device_type": "0x0100",
"input_clusters": [
"0x0012"
],
"output_clusters": []
},
"51": {
"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.l2aeu1"
} The edited quirkimport copy
from enum import Enum
from zigpy import types as t
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zhaquirks import CustomCluster
from zigpy.zcl.clusters.general import (
Basic,
DeviceTemperature,
Groups,
Identify,
OnOff,
Ota,
Scenes,
Time,
MultistateInput,
GreenPowerProxy,
Alarms,
)
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
SHORT_PRESS,
TRIPLE_PRESS,
LONG_PRESS,
ALT_DOUBLE_PRESS,
DOUBLE_PRESS,
ALT_SHORT_PRESS,
LEFT,
RIGHT,
COMMAND_TOGGLE,
COMMAND,
BUTTON,
ENDPOINT_ID,
ARGS,
CLUSTER_ID,
ATTR_ID,
PRESS_TYPE,
VALUE,
ZHA_SEND_EVENT,
COMMAND_HOLD,
COMMAND_TRIPLE
)
from zhaquirks.xiaomi import (
LUMI
)
COMMAND_SINGLE = "single"
COMMAND_DOUBLE = "double"
BUTTON_ANY = "any"
LEFT_BUTTON_ENDPOINT=41
RIGHT_BUTTON_ENDPOINT=42
BOTH_BUTTONS_ENDPOINT=51
from zhaquirks.xiaomi.aqara.opple_switch import (OppleSwitchCluster, BOTH_BUTTONS)
from zhaquirks.xiaomi.aqara.opple_remote import (
OppleCluster,
OPPLE_CLUSTER_ID,
STATUS_TYPE_ATTR,
PRESS_TYPES
)
class XiaomiAqaraOpMode(t.uint8_t, Enum):
Decoupled = 0x00
Coupled = 0x01
class XiaomiAqaraFlickerMode(t.uint16_t, Enum):
Anti_flicker = 0x0004
Quick = 0x0001
class XiaomiAqaraIndicatorLight(t.uint8_t, Enum):
Normal = 0x00
Reverse = 0x01
class XiaomiAqaraOperationMode(t.uint8_t, Enum):
Decoupled = 0x00
Coupled = 0x01
class XiaomiAqaraMasterCluster(OppleCluster):
attributes = copy.deepcopy(OppleCluster.attributes)
attributes.update(
{
0x0004: ("anti_flicker", XiaomiAqaraFlickerMode, True),
0x0002: ("power_outage_count", t.uint8_t, True),
0x0201: ("power_outage_memory", t.Bool, True),
0x0203: ("led_disabled_night", t.Bool, True),
0x00F0: ("indicator_light", XiaomiAqaraIndicatorLight, True),
0x0200: ("operation_mode", XiaomiAqaraOperationMode, True),
}
)
def _update_attribute(self, attrid, value):
super()._update_attribute(attrid, value)
if attrid == 0x00FC and value == False:
event_args = {
BUTTON: BUTTON_ANY,
PRESS_TYPE: COMMAND_HOLD,
ATTR_ID: attrid,
VALUE: value,
}
action = "{}_{}".format(BUTTON_ANY, COMMAND_HOLD)
self.listener_event(ZHA_SEND_EVENT, action, event_args)
super()._update_attribute(0, action)
# elif attrid == 0x00f7:
# event_args = {
# BUTTON: BUTTON_ANY,
# PRESS_TYPE: COMMAND_TRIPLE,
# ATTR_ID: attrid
# }
# action = "{}_{}".format(BUTTON_ANY, COMMAND_TRIPLE)
# self.listener_event(ZHA_SEND_EVENT, action, event_args)
# super()._update_attribute(0, action)
class XiaomiAqaraSecondaryCluster(CustomCluster):
ep_attribute = "opple_cluster"
cluster_id = OPPLE_CLUSTER_ID
attributes = (
{
0x0200: ("operation_mode", XiaomiAqaraOperationMode, True),
}
)
class MultistateInputCluster(CustomCluster, MultistateInput):
cluster_id = MultistateInput.cluster_id
def __init__(self, *args, **kwargs):
self._current_state = None
super().__init__(*args, **kwargs)
async def configure_reporting(
self,
attribute,
min_interval,
max_interval,
reportable_change,
manufacturer=None,
): """Configure reporting."""
def _update_attribute(self, attrid, value):
super()._update_attribute(attrid, value)
if attrid == STATUS_TYPE_ATTR:
self._current_state = PRESS_TYPES.get(value)
event_args = {
BUTTON: self.endpoint.endpoint_id,
PRESS_TYPE: self._current_state,
ATTR_ID: attrid,
VALUE: value,
}
button = None
if self.endpoint.endpoint_id == LEFT_BUTTON_ENDPOINT:
button=LEFT
elif self.endpoint.endpoint_id == RIGHT_BUTTON_ENDPOINT:
button=RIGHT
elif self.endpoint.endpoint_id == BOTH_BUTTONS_ENDPOINT:
button=BOTH_BUTTONS
action=action = "{}_{}".format(self.endpoint.endpoint_id, self._current_state)
if button != None:
action = "{}_{}".format(button, self._current_state)
self.listener_event(ZHA_SEND_EVENT, action, event_args)
super()._update_attribute(0, action)
class XiaomiAqaraWSEUK02(CustomDevice):
"""WS-EUK02 Aqara smart wall switch H1 EU (no neutral, double rocker)"""
signature = {
MODELS_INFO: [(LUMI, "lumi.switch.l2aeu1")],
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,
OppleSwitchCluster.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,
OppleSwitchCluster.cluster_id,
],
OUTPUT_CLUSTERS: [],
},
LEFT_BUTTON_ENDPOINT: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
MultistateInput.cluster_id,
],
OUTPUT_CLUSTERS: [],
},
RIGHT_BUTTON_ENDPOINT: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
MultistateInput.cluster_id,
],
OUTPUT_CLUSTERS: [],
},
BOTH_BUTTONS_ENDPOINT: {
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 = {
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,
MultistateInputCluster,
XiaomiAqaraMasterCluster,
],
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,
MultistateInputCluster,
XiaomiAqaraSecondaryCluster,
],
OUTPUT_CLUSTERS: [],
},
LEFT_BUTTON_ENDPOINT: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
MultistateInputCluster,
],
OUTPUT_CLUSTERS: [],
},
RIGHT_BUTTON_ENDPOINT: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
MultistateInputCluster,
],
OUTPUT_CLUSTERS: [],
},
BOTH_BUTTONS_ENDPOINT: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
MultistateInputCluster,
],
OUTPUT_CLUSTERS: [],
},
242: {
PROFILE_ID: 0xA1E0,
DEVICE_TYPE: 0x0061,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
}
}
device_automation_triggers = {
(SHORT_PRESS, LEFT): { COMMAND: "{}_{}".format(LEFT, COMMAND_SINGLE)},
(DOUBLE_PRESS, LEFT): { COMMAND: "{}_{}".format(LEFT, COMMAND_DOUBLE)},
(SHORT_PRESS, RIGHT): { COMMAND: "{}_{}".format(RIGHT, COMMAND_SINGLE)},
(DOUBLE_PRESS, RIGHT): { COMMAND: "{}_{}".format(RIGHT, COMMAND_DOUBLE)},
(SHORT_PRESS, BOTH_BUTTONS): { COMMAND: "{}_{}".format(BOTH_BUTTONS, COMMAND_SINGLE)},
(DOUBLE_PRESS, BOTH_BUTTONS): { COMMAND: "{}_{}".format(BOTH_BUTTONS, COMMAND_DOUBLE)},
(COMMAND_HOLD, BUTTON): { COMMAND: "{}_{}".format(BUTTON_ANY, COMMAND_HOLD)},
} |
Hi, unfortunately, neither of the quirks posted here work for my device. I don't receive any events when listening to "zha_event." My device is shown as two lights, and the right button doesn't change when I press the button physically. Can anyone help me? My device 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"
],
"output_clusters": []
},
"242": {
"profile_id": "0xa1e0",
"device_type": "0x0061",
"input_clusters": [],
"output_clusters": [
"0x0021"
]
}
},
"manufacturer": "LUMI",
"model": "lumi.switch.l2aeu1",
"class": "zigpy.device.Device"
} |
@sophipl , thanks for the quirk, it works for me (l2aeu1) from zhaquirks.xiaomi.aqara.opple_remote import (
OppleCluster,
OPPLE_CLUSTER_ID,
STATUS_TYPE_ATTR,
PRESS_TYPES
) my fix was to remove OPPLE_CLUSTER_ID from the imports and replace all usages in this file with OppleCluster.cluster_id updated version of aqara_l2aeu1.pyimport copy
from enum import Enum
from zigpy import types as t
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zhaquirks import CustomCluster
from zigpy.zcl.clusters.general import (
Basic,
DeviceTemperature,
Groups,
Identify,
OnOff,
Ota,
Scenes,
Time,
MultistateInput,
GreenPowerProxy,
Alarms,
)
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
SHORT_PRESS,
TRIPLE_PRESS,
LONG_PRESS,
ALT_DOUBLE_PRESS,
DOUBLE_PRESS,
ALT_SHORT_PRESS,
LEFT,
RIGHT,
COMMAND_TOGGLE,
COMMAND,
BUTTON,
ENDPOINT_ID,
ARGS,
CLUSTER_ID,
ATTR_ID,
PRESS_TYPE,
VALUE,
ZHA_SEND_EVENT,
COMMAND_HOLD,
COMMAND_TRIPLE
)
from zhaquirks.xiaomi import (
LUMI
)
COMMAND_SINGLE = "single"
COMMAND_DOUBLE = "double"
BUTTON_ANY = "any"
LEFT_BUTTON_ENDPOINT=41
RIGHT_BUTTON_ENDPOINT=42
BOTH_BUTTONS_ENDPOINT=51
from zhaquirks.xiaomi.aqara.opple_switch import (OppleSwitchCluster, BOTH_BUTTONS)
from zhaquirks.xiaomi.aqara.opple_remote import (
OppleCluster,
STATUS_TYPE_ATTR,
PRESS_TYPES
)
class XiaomiAqaraOpMode(t.uint8_t, Enum):
Decoupled = 0x00
Coupled = 0x01
class XiaomiAqaraFlickerMode(t.uint16_t, Enum):
Anti_flicker = 0x0004
Quick = 0x0001
class XiaomiAqaraIndicatorLight(t.uint8_t, Enum):
Normal = 0x00
Reverse = 0x01
class XiaomiAqaraOperationMode(t.uint8_t, Enum):
Decoupled = 0x00
Coupled = 0x01
class XiaomiAqaraMasterCluster(OppleCluster):
attributes = copy.deepcopy(OppleCluster.attributes)
attributes.update(
{
0x0004: ("anti_flicker", XiaomiAqaraFlickerMode, True),
0x0002: ("power_outage_count", t.uint8_t, True),
0x0201: ("power_outage_memory", t.Bool, True),
0x0203: ("led_disabled_night", t.Bool, True),
0x00F0: ("indicator_light", XiaomiAqaraIndicatorLight, True),
0x0200: ("operation_mode", XiaomiAqaraOperationMode, True),
}
)
def _update_attribute(self, attrid, value):
super()._update_attribute(attrid, value)
if attrid == 0x00FC and value == False:
event_args = {
BUTTON: BUTTON_ANY,
PRESS_TYPE: COMMAND_HOLD,
ATTR_ID: attrid,
VALUE: value,
}
action = "{}_{}".format(BUTTON_ANY, COMMAND_HOLD)
self.listener_event(ZHA_SEND_EVENT, action, event_args)
super()._update_attribute(0, action)
# elif attrid == 0x00f7:
# event_args = {
# BUTTON: BUTTON_ANY,
# PRESS_TYPE: COMMAND_TRIPLE,
# ATTR_ID: attrid
# }
# action = "{}_{}".format(BUTTON_ANY, COMMAND_TRIPLE)
# self.listener_event(ZHA_SEND_EVENT, action, event_args)
# super()._update_attribute(0, action)
class XiaomiAqaraSecondaryCluster(CustomCluster):
ep_attribute = "opple_cluster"
cluster_id = OppleCluster.cluster_id
attributes = (
{
0x0200: ("operation_mode", XiaomiAqaraOperationMode, True),
}
)
class MultistateInputCluster(CustomCluster, MultistateInput):
cluster_id = MultistateInput.cluster_id
def __init__(self, *args, **kwargs):
self._current_state = None
super().__init__(*args, **kwargs)
async def configure_reporting(
self,
attribute,
min_interval,
max_interval,
reportable_change,
manufacturer=None,
): """Configure reporting."""
def _update_attribute(self, attrid, value):
super()._update_attribute(attrid, value)
if attrid == STATUS_TYPE_ATTR:
self._current_state = PRESS_TYPES.get(value)
event_args = {
BUTTON: self.endpoint.endpoint_id,
PRESS_TYPE: self._current_state,
ATTR_ID: attrid,
VALUE: value,
}
button = None
if self.endpoint.endpoint_id == LEFT_BUTTON_ENDPOINT:
button=LEFT
elif self.endpoint.endpoint_id == RIGHT_BUTTON_ENDPOINT:
button=RIGHT
elif self.endpoint.endpoint_id == BOTH_BUTTONS_ENDPOINT:
button=BOTH_BUTTONS
action=action = "{}_{}".format(self.endpoint.endpoint_id, self._current_state)
if button != None:
action = "{}_{}".format(button, self._current_state)
self.listener_event(ZHA_SEND_EVENT, action, event_args)
super()._update_attribute(0, action)
class XiaomiAqaraWSEUK02(CustomDevice):
"""WS-EUK02 Aqara smart wall switch H1 EU (no neutral, double rocker)"""
signature = {
MODELS_INFO: [(LUMI, "lumi.switch.l2aeu1")],
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,
MultistateInput.cluster_id,
OppleSwitchCluster.cluster_id,
],
OUTPUT_CLUSTERS: [],
},
242: {
PROFILE_ID: 0xA1E0,
DEVICE_TYPE: 0x0061,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
},
}
replacement = {
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,
MultistateInputCluster,
XiaomiAqaraMasterCluster,
],
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,
MultistateInputCluster,
XiaomiAqaraSecondaryCluster,
],
OUTPUT_CLUSTERS: [],
},
LEFT_BUTTON_ENDPOINT: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
MultistateInputCluster,
],
OUTPUT_CLUSTERS: [],
},
RIGHT_BUTTON_ENDPOINT: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
MultistateInputCluster,
],
OUTPUT_CLUSTERS: [],
},
BOTH_BUTTONS_ENDPOINT: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
MultistateInputCluster,
],
OUTPUT_CLUSTERS: [],
},
242: {
PROFILE_ID: 0xA1E0,
DEVICE_TYPE: 0x0061,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
}
}
device_automation_triggers = {
(SHORT_PRESS, LEFT): { COMMAND: "{}_{}".format(LEFT, COMMAND_SINGLE)},
(DOUBLE_PRESS, LEFT): { COMMAND: "{}_{}".format(LEFT, COMMAND_DOUBLE)},
(SHORT_PRESS, RIGHT): { COMMAND: "{}_{}".format(RIGHT, COMMAND_SINGLE)},
(DOUBLE_PRESS, RIGHT): { COMMAND: "{}_{}".format(RIGHT, COMMAND_DOUBLE)},
(SHORT_PRESS, BOTH_BUTTONS): { COMMAND: "{}_{}".format(BOTH_BUTTONS, COMMAND_SINGLE)},
(DOUBLE_PRESS, BOTH_BUTTONS): { COMMAND: "{}_{}".format(BOTH_BUTTONS, COMMAND_DOUBLE)},
(COMMAND_HOLD, BUTTON): { COMMAND: "{}_{}".format(BUTTON_ANY, COMMAND_HOLD)},
} |
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. |
The quirk provided by theorlang has enabled the OppleSwitchCluster option for me. I can now decouple the switch from the button. I do see some other options now that are not supported by the Switch (e.g. Power sensor). In addition the device pages does sometimes become unresponsive. |
I would like to have the ability to trigger on double button press, which I read that this device have in Zigbee2MQTT mode.
The device has automation abilities in HA on state changes (light on, light off), but not of button presses, apparently you can have the ability to disconnect button from it's internal relay and automate it differently as well.
I didn't see any pre-existing quirks.
Sadly I understand too zigbee protocol too little to write this quirk myself.
Device signature
Diagnostic information
The text was updated successfully, but these errors were encountered: