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
682 stars 631 forks source link

[Device Support Request] Aqara H1 EU Switch Double Rocker WS-EUK04 #2251

Open j0hann3s opened 1 year ago

j0hann3s commented 1 year ago

Is your feature request related to a problem? Please describe. I can not capture any used energy measurements in my home assistant instance's history due to missing energy reporting. I also miss the feature to be able to get the device temperature, set the power outage memory setting, turn the indicator led on and off on the device, and set the operation mode to coupled/decoupled.

Describe the solution you'd like An added attribute publishing the sum of consumed energy (kWh) as well as an instantaneous power measurement. Moreover, a device temperature report, being able to set the power outage memory, enable/disable the indicator led, and choosing the operation mode.

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=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": "0x0000", "in_clusters": [ "0x0000", "0x0002", "0x0003", "0x0004", "0x0005", "0x0006", "0x0009", "0x0012", "0x0702", "0xfcc0" ], "out_clusters": [ "0x000a", "0x0019" ] }, "2": { "profile_id": 260, "device_type": "0x0000", "in_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0x0012", "0xfcc0" ], "out_clusters": [] }, "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": [] }, "42": { "profile_id": 260, "device_type": "0x0100", "in_clusters": [ "0x0012" ], "out_clusters": [] }, "51": { "profile_id": 260, "device_type": "0x0100", "in_clusters": [ "0x0012" ], "out_clusters": [] }, "61": { "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.n2aeu1", "class": "zhaquirks.xiaomi.aqara.opple_switch.XiaomiOpple2ButtonSwitchFace2" } ```
Diagnostic information ```yaml { "home_assistant": { "installation_type": "Home Assistant OS", "version": "2023.3.1", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.10.10", "docker": true, "arch": "x86_64", "timezone": "Europe/Stockholm", "os_name": "Linux", "os_version": "5.15.90", "supervisor": "2023.01.1", "host_os": "Home Assistant OS 9.5", "docker_version": "20.10.22", "chassis": "vm", "run_as_root": true }, "custom_components": { "pyscript": { "version": "1.3.3", "requirements": [ "croniter==1.3.4", "watchdog==2.1.6" ] }, "spotcast": { "version": "v3.6.30", "requirements": [] }, "reversotts": { "version": "1.0.2", "requirements": [ "pyttsreverso==0.4" ] }, "hacs": { "version": "1.31.0", "requirements": [ "aiogithubapi>=22.10.1" ] }, "nodered": { "version": "1.1.3", "requirements": [] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "after_dependencies": [ "onboarding", "usb" ], "codeowners": [ "@dmulcahey", "@adminiuga", "@puddly" ], "config_flow": true, "dependencies": [ "file_upload" ], "documentation": "https://www.home-assistant.io/integrations/zha", "iot_class": "local_polling", "loggers": [ "aiosqlite", "bellows", "crccheck", "pure_pcapy3", "zhaquirks", "zigpy", "zigpy_deconz", "zigpy_xbee", "zigpy_zigate", "zigpy_znp" ], "requirements": [ "bellows==0.34.9", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.93", "zigpy-deconz==0.19.2", "zigpy==0.53.2", "zigpy-xbee==0.16.2", "zigpy-zigate==0.10.3", "zigpy-znp==0.9.3" ], "usb": [ { "vid": "10C4", "pid": "EA60", "description": "*2652*", "known_devices": [ "slae.sh cc2652rb stick" ] }, { "vid": "1A86", "pid": "55D4", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus v2" ] }, { "vid": "10C4", "pid": "EA60", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus" ] }, { "vid": "10C4", "pid": "EA60", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*zigstar*", "known_devices": [ "ZigStar Coordinators" ] }, { "vid": "1CF1", "pid": "0030", "description": "*conbee*", "known_devices": [ "Conbee II" ] }, { "vid": "10C4", "pid": "8A2A", "description": "*zigbee*", "known_devices": [ "Nortek HUSBZB-1" ] }, { "vid": "0403", "pid": "6015", "description": "*zigate*", "known_devices": [ "ZiGate+" ] }, { "vid": "10C4", "pid": "EA60", "description": "*zigate*", "known_devices": [ "ZiGate" ] }, { "vid": "10C4", "pid": "8B34", "description": "*bv 2010/10*", "known_devices": [ "Bitron Video AV2010/10" ] } ], "zeroconf": [ { "type": "_esphomelib._tcp.local.", "name": "tube*" }, { "type": "_zigate-zigbee-gateway._tcp.local.", "name": "*zigate*" }, { "type": "_zigstar_gw._tcp.local.", "name": "*zigstar*" }, { "type": "_slzb-06._tcp.local.", "name": "slzb-06*" } ], "is_built_in": true }, "data": { "ieee": "**REDACTED**", "nwk": 38020, "manufacturer": "LUMI", "model": "lumi.switch.n2aeu1", "name": "LUMI lumi.switch.n2aeu1", "quirk_applied": true, "quirk_class": "zhaquirks.xiaomi.aqara.opple_switch.XiaomiOpple2ButtonSwitchFace2", "manufacturer_code": 4447, "power_source": "Mains", "lqi": 255, "rssi": -52, "last_seen": "2023-03-03T20:31:21", "available": true, "device_type": "Router", "signature": { "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=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": "0x0000", "in_clusters": [ "0x0000", "0x0002", "0x0003", "0x0004", "0x0005", "0x0006", "0x0009", "0x0012", "0x0702", "0xfcc0" ], "out_clusters": [ "0x000a", "0x0019" ] }, "2": { "profile_id": 260, "device_type": "0x0000", "in_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0x0012", "0xfcc0" ], "out_clusters": [] }, "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": [] }, "42": { "profile_id": 260, "device_type": "0x0100", "in_clusters": [ "0x0012" ], "out_clusters": [] }, "51": { "profile_id": 260, "device_type": "0x0100", "in_clusters": [ "0x0012" ], "out_clusters": [] }, "61": { "profile_id": 260, "device_type": "0x0100", "in_clusters": [ "0x0012" ], "out_clusters": [] }, "242": { "profile_id": 41440, "device_type": "0x0061", "in_clusters": [], "out_clusters": [ "0x0021" ] } } }, "active_coordinator": false, "entities": [ { "entity_id": "button.lumi_lumi_switch_n2aeu1_identify_2", "name": "LUMI lumi.switch.n2aeu1" }, { "entity_id": "switch.lumi_lumi_switch_n2aeu1_switch_3", "name": "LUMI lumi.switch.n2aeu1" }, { "entity_id": "switch.lumi_lumi_switch_n2aeu1_switch_4", "name": "LUMI lumi.switch.n2aeu1" } ], "neighbors": [ { "device_type": "Coordinator", "rx_on_when_idle": "On", "relationship": "Parent", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x0000", "permit_joining": "Unknown", "depth": "0", "lqi": "114" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xDCC0", "permit_joining": "Unknown", "depth": "1", "lqi": "125" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xF263", "permit_joining": "Unknown", "depth": "1", "lqi": "111" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xAB74", "permit_joining": "Unknown", "depth": "1", "lqi": "71" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xE61F", "permit_joining": "Unknown", "depth": "1", "lqi": "73" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x3683", "permit_joining": "Unknown", "depth": "1", "lqi": "93" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xD265", "permit_joining": "Unknown", "depth": "1", "lqi": "94" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xE117", "permit_joining": "Unknown", "depth": "1", "lqi": "94" } ], "routes": [ { "dest_nwk": "0x0000", "route_status": "Validation_Underway", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x0000" }, { "dest_nwk": "0xF263", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xF263" }, { "dest_nwk": "0xAB74", "route_status": "Discovery_Underway", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xFFFE" }, { "dest_nwk": "0xE61F", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xE61F" }, { "dest_nwk": "0xBC9A", "route_status": "Discovery_Underway", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xFFFE" }, { "dest_nwk": "0x3683", "route_status": "Discovery_Underway", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xFFFE" }, { "dest_nwk": "0xE117", "route_status": "Validation_Underway", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xE117" }, { "dest_nwk": "0xD265", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xD265" }, { "dest_nwk": "0xDCC0", "route_status": "Discovery_Underway", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xFFFE" } ], "endpoint_names": [ { "name": "ON_OFF_SWITCH" }, { "name": "ON_OFF_SWITCH" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "unknown 97 device_type of 0xa1e0 profile id" } ], "user_given_name": null, "device_reg_id": "8ed3bc9d22587e221a4c605666085ea0", "area_id": null, "cluster_details": { "1": { "device_type": { "name": "ON_OFF_SWITCH", "id": 0 }, "profile_id": 260, "in_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0006": { "attribute_name": "date_code", "value": "01-29-2021" } }, "unsupported_attributes": {} }, "0x0002": { "endpoint_attribute": "device_temperature", "attributes": {}, "unsupported_attributes": {} }, "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 0 } }, "unsupported_attributes": { "0x4003": { "attribute_name": "start_up_on_off" } } }, "0x0009": { "endpoint_attribute": "alarms", "attributes": {}, "unsupported_attributes": {} }, "0x0012": { "endpoint_attribute": "multistate_input", "attributes": {}, "unsupported_attributes": {} }, "0x0702": { "endpoint_attribute": "smartenergy_metering", "attributes": {}, "unsupported_attributes": { "0x0300": { "attribute_name": "unit_of_measure" }, "0x0301": { "attribute_name": "multiplier" }, "0x0302": { "attribute_name": "divisor" }, "0x0303": { "attribute_name": "summation_formatting" }, "0x0304": { "attribute_name": "demand_formatting" }, "0x0306": { "attribute_name": "metering_device_type" } } }, "0xfcc0": { "endpoint_attribute": "opple_cluster", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": { "0x000a": { "endpoint_attribute": "time", "attributes": {}, "unsupported_attributes": {} }, "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} } } }, "2": { "device_type": { "name": "ON_OFF_SWITCH", "id": 0 }, "profile_id": 260, "in_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": {}, "unsupported_attributes": {} }, "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 0 } }, "unsupported_attributes": { "0x4003": { "attribute_name": "start_up_on_off" } } }, "0x0012": { "endpoint_attribute": "multistate_input", "attributes": {}, "unsupported_attributes": {} }, "0xfcc0": { "endpoint_attribute": "opple_cluster", "attributes": { "0x0009": { "attribute_name": "mode", "value": 1 } }, "unsupported_attributes": {} } }, "out_clusters": {} }, "21": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x000c": { "endpoint_attribute": "analog_input", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": {} }, "31": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x000c": { "endpoint_attribute": "analog_input", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": {} }, "41": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0012": { "endpoint_attribute": "multistate_input", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": {} }, "42": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0012": { "endpoint_attribute": "multistate_input", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": {} }, "51": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0012": { "endpoint_attribute": "multistate_input", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": {} }, "61": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0012": { "endpoint_attribute": "multistate_input", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": {} }, "242": { "device_type": { "name": "unknown", "id": 97 }, "profile_id": 41440, "in_clusters": {}, "out_clusters": { "0x0021": { "endpoint_attribute": "green_power", "attributes": {}, "unsupported_attributes": {} } } } } } } ```
Additional logs ``` Paste any additional debug logs here. Don't remove the extra line breaks outside the ``` marks. ```

Additional context Here is a screenshot of how it looks in ZHA right now. I am using the SkyConnect adapter. Screenshot from 2023-03-03 20-33-24

Here is a screenshot of how the same switch looks inside Z2M and what attributes it exposes. Screenshot from 2023-03-03 20-34-26

amoshydra commented 1 year ago

I just figured out this yesterday.

Apparently the implementation is already done for zhaquirks.xiaomi.aqara.opple_switch.XiaomiOpple2ButtonSwitchFace1, see: https://github.com/zigpy/zha-device-handlers/blob/0.0.93/zhaquirks/xiaomi/aqara/opple_switch.py#L56-L61

How to enable decoupled mode:

Step 1 - Manage Zigbee Device

  1. In your Device view, under Device info, click on the 3 dots menu
  2. Manage zigbee device

image

Step 2 - Choose OppleSwitchCluster

image

Inside the cluster dropdown menu, you will find:

Select OppleSwitchCluster and choose the attribute operation_mode (id: 0x0200)

image

You can read the current value by pressing "READ ATTRIBUTE"

image

The operation_mode will be one of:

Step 3 - Change Operation Mode

You can change the operation mode by writing a numeric value into the value like this:

image

image


You can repeat the same for the another button

timoei commented 1 year ago

I just figured out this yesterday.

Apparently the implementation is already done for zhaquirks.xiaomi.aqara.opple_switch.XiaomiOpple2ButtonSwitchFace1, see: https://github.com/zigpy/zha-device-handlers/blob/0.0.93/zhaquirks/xiaomi/aqara/opple_switch.py#L56-L61

How to enable decoupled mode:

Step 1 - Manage Zigbee Device

1. In your Device view, under Device info, click on the 3 dots menu

2. Manage zigbee device

image

Step 2 - Choose OppleSwitchCluster

image

Inside the cluster dropdown menu, you will find:

* OppleSwitchCluster (Endpoint id: 1) - This correspond to button_1 (left side)

* OppleSwitchCluster (Endpoint id: 2) - This correspond to button_2 (right side)

Select OppleSwitchCluster and choose the attribute operation_mode (id: 0x0200)

image

You can read the current value by pressing "READ ATTRIBUTE"

image

The operation_mode will be one of:

* OppleOperationMode.Decoupled - `0`

* OppleOperationMode.Coupled - `1`

Step 3 - Change Operation Mode

You can change the operation mode by writing a numeric value into the value like this:

image

image

You can repeat the same for the another button

As I was looking for this option quite long: It is important to have the ZHA quirks enabled in the config.yaml!

tarosk commented 11 months ago

It seems support for single rocker version is already merged in issue #1369 pull requeste #2385

Can this be replicated to double rocker version as well?

danielshiloah commented 9 months ago

I have the same problem of missing the attributes power, temp and configurations. has there been any updates? cant find anything on the web but this device support request?

Jolanrensen commented 8 months ago

Thanks @timoei! I was looking for the decoupled mode :) It looks like all supported features in zigbee2mqtt for this switch need to be enabled here too :)

sattath commented 1 week ago

Is there any way to control the LEDs in decoupled mode (as described in this comment: https://github.com/zigpy/zha-device-handlers/issues/2251#issuecomment-1483929748)?