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
727 stars 672 forks source link

[Device Support Request] Ecodim 05 #2865

Open mano3m opened 8 months ago

mano3m commented 8 months ago

Problem description

My Ecodim 05 two gang dimmer (see https://www.ecodim.nl/nl/eco-dim05.html) does not report its status back to ZHA (in a way it understands it anyways). This gives errors and results in out of sync issues, see for example: https://community.home-assistant.io/t/eco-dim-05-dual-dimmer-not-supported-in-zha/623843

Solution description

In Z2M Ecodim devices have their own herdsman converter: https://github.com/Koenkk/zigbee-herdsman-converters/blob/master/src/devices/ecodim.ts

It would be great if that can be converted to a quirk.

Screenshots/Video

Screenshots/Video [Paste/upload your media here]

Device signature

Device signature ```json { "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=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, 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": "0x0104", "device_type": "0x0101", "input_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0x0008", "0x1000" ], "output_clusters": [ "0x0019" ] }, "2": { "profile_id": "0x0104", "device_type": "0x0101", "input_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0x0008", "0x1000" ], "output_clusters": [ "0x0019" ] }, "242": { "profile_id": "0xa1e0", "device_type": "0x0061", "input_clusters": [], "output_clusters": [ "0x0021" ] } }, "manufacturer": "EcoDim BV", "model": "EcoDim-Zigbee 3.0", "class": "zigpy.device.Device" } ```

Diagnostic information

Diagnostic information ```json { "home_assistant": { "installation_type": "Home Assistant OS", "version": "2023.12.3", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.11.6", "docker": true, "arch": "aarch64", "timezone": "Europe/Amsterdam", "os_name": "Linux", "os_version": "6.1.58-haos-raspi", "supervisor": "2023.12.0", "host_os": "Home Assistant OS 11.2", "docker_version": "24.0.7", "chassis": "embedded", "run_as_root": true }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "after_dependencies": [ "onboarding", "usb" ], "codeowners": [ "@dmulcahey", "@adminiuga", "@puddly", "@TheJulianJES" ], "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", "universal_silabs_flasher" ], "requirements": [ "bellows==0.37.3", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.107", "zigpy-deconz==0.22.2", "zigpy==0.60.1", "zigpy-xbee==0.20.1", "zigpy-zigate==0.12.0", "zigpy-znp==0.12.0", "universal-silabs-flasher==0.0.15", "pyserial-asyncio-fast==0.11" ], "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": "0403", "pid": "6015", "description": "*conbee*", "known_devices": [ "Conbee III" ] }, { "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": "_uzg-01._tcp.local.", "name": "uzg-01*" }, { "type": "_slzb-06._tcp.local.", "name": "slzb-06*" } ], "is_built_in": true }, "data": { "ieee": "**REDACTED**", "nwk": 50680, "manufacturer": "EcoDim BV", "model": "EcoDim-Zigbee 3.0", "name": "EcoDim BV EcoDim-Zigbee 3.0", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "quirk_id": null, "manufacturer_code": 4098, "power_source": "Mains", "lqi": 124, "rssi": -69, "last_seen": "2023-12-27T21:24:13", "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=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, 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": "0x0104", "device_type": "0x0101", "input_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0x0008", "0x1000" ], "output_clusters": [ "0x0019" ] }, "2": { "profile_id": "0x0104", "device_type": "0x0101", "input_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0x0008", "0x1000" ], "output_clusters": [ "0x0019" ] }, "242": { "profile_id": "0xa1e0", "device_type": "0x0061", "input_clusters": [], "output_clusters": [ "0x0021" ] } }, "manufacturer": "EcoDim BV", "model": "EcoDim-Zigbee 3.0" }, "active_coordinator": false, "entities": [ { "entity_id": "button.ecodim_bv_ecodim_zigbee_3_0_identify_2", "name": "EcoDim BV EcoDim-Zigbee 3.0" }, { "entity_id": "light.ecodim_bv_ecodim_zigbee_3_0_light", "name": "EcoDim BV EcoDim-Zigbee 3.0" }, { "entity_id": "light.ecodim_bv_ecodim_zigbee_3_0_light_2", "name": "EcoDim BV EcoDim-Zigbee 3.0" }, { "entity_id": "number.ecodim_bv_ecodim_zigbee_3_0_on_level_2", "name": "EcoDim BV EcoDim-Zigbee 3.0" }, { "entity_id": "number.ecodim_bv_ecodim_zigbee_3_0_on_level_3", "name": "EcoDim BV EcoDim-Zigbee 3.0" } ], "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": "118" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x1848", "permit_joining": "Unknown", "depth": "15", "lqi": "82" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x5521", "permit_joining": "Unknown", "depth": "15", "lqi": "107" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x5DAE", "permit_joining": "Unknown", "depth": "15", "lqi": "120" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x5E77", "permit_joining": "Unknown", "depth": "15", "lqi": "96" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x6696", "permit_joining": "Unknown", "depth": "15", "lqi": "127" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x6FEF", "permit_joining": "Unknown", "depth": "15", "lqi": "72" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xF38F", "permit_joining": "Unknown", "depth": "15", "lqi": "92" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xF81F", "permit_joining": "Unknown", "depth": "15", "lqi": "64" } ], "routes": [ { "dest_nwk": "0x0000", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x0000" }, { "dest_nwk": "0x0294", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x5DAE" }, { "dest_nwk": "0x1848", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x5DAE" }, { "dest_nwk": "0x5E77", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x5521" }, { "dest_nwk": "0x6696", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x6696" }, { "dest_nwk": "0xBEEF", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x6696" }, { "dest_nwk": "0x5DAE", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x5DAE" }, { "dest_nwk": "0x6FEF", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x5521" }, { "dest_nwk": "0x9938", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x5DAE" }, { "dest_nwk": "0xF38F", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xF38F" }, { "dest_nwk": "0xF81F", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xF38F" }, { "dest_nwk": "0x5521", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xF38F" } ], "endpoint_names": [ { "name": "DIMMABLE_LIGHT" }, { "name": "DIMMABLE_LIGHT" }, { "name": "PROXY_BASIC" } ], "user_given_name": "Dimmer", "device_reg_id": "0c23918ae16b9dc263fed9fe49e7b0fb", "area_id": "woonkamer", "cluster_details": { "1": { "device_type": { "name": "DIMMABLE_LIGHT", "id": 257 }, "profile_id": 260, "in_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0004": { "attribute_name": "manufacturer", "value": "EcoDim BV" }, "0x0005": { "attribute_name": "model", "value": "EcoDim-Zigbee 3.0" } }, "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": { "0xfffd": { "attribute_name": "cluster_revision", "value": 2 }, "0x0000": { "attribute_name": "on_off", "value": 1 } }, "unsupported_attributes": { "0x4000": { "attribute_name": "global_scene_control" }, "0xfffe": { "attribute_name": "reporting_status" }, "0x4002": { "attribute_name": "off_wait_time" }, "0x4003": { "attribute_name": "start_up_on_off" } } }, "0x0008": { "endpoint_attribute": "level", "attributes": { "0x0000": { "attribute_name": "current_level", "value": 190 }, "0x0011": { "attribute_name": "on_level", "value": 255 } }, "unsupported_attributes": { "0x4000": { "attribute_name": "start_up_current_level" }, "0x0010": { "attribute_name": "on_off_transition_time" }, "0x0012": { "attribute_name": "on_transition_time" }, "0x0013": { "attribute_name": "off_transition_time" }, "0x0014": { "attribute_name": "default_move_rate" } } }, "0x1000": { "endpoint_attribute": "lightlink", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": { "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} } } }, "2": { "device_type": { "name": "DIMMABLE_LIGHT", "id": 257 }, "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" } } }, "0x0008": { "endpoint_attribute": "level", "attributes": { "0x0000": { "attribute_name": "current_level", "value": 210 }, "0x0011": { "attribute_name": "on_level", "value": 210 } }, "unsupported_attributes": { "0x4000": { "attribute_name": "start_up_current_level" }, "0x0010": { "attribute_name": "on_off_transition_time" }, "0x0012": { "attribute_name": "on_transition_time" }, "0x0013": { "attribute_name": "off_transition_time" }, "0x0014": { "attribute_name": "default_move_rate" } } }, "0x1000": { "endpoint_attribute": "lightlink", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": { "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} } } }, "242": { "device_type": { "name": "PROXY_BASIC", "id": 97 }, "profile_id": 41440, "in_clusters": {}, "out_clusters": { "0x0021": { "endpoint_attribute": "green_power", "attributes": {}, "unsupported_attributes": {} } } } } } } ```

Logs

Logs ```python Logger: homeassistant.components.websocket_api.http.connection Source: components/websocket_api/commands.py:238 Integration: Home Assistant WebSocket API ([documentation](https://www.home-assistant.io/integrations/websocket_api), [issues](https://github.com/home-assistant/core/issues?q=is%3Aissue+is%3Aopen+label%3A%22integration%3A+websocket_api%22)) First occurred: 02:03:57 (2 occurrences) Last logged: 02:04:15 [547173777728] Failed to send request: device did not respond Traceback (most recent call last): File "/usr/local/lib/python3.11/site-packages/zigpy/device.py", line 316, in request return await req.result ^^^^^^^^^^^^^^^^ asyncio.exceptions.CancelledError The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/components/zha/core/cluster_handlers/__init__.py", line 64, in wrap_zigpy_exceptions yield File "/usr/src/homeassistant/homeassistant/components/zha/core/cluster_handlers/__init__.py", line 84, in wrapper return await RETRYABLE_REQUEST_DECORATOR(func)(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/zigpy/util.py", line 137, in retry return await func() ^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/zigpy/zcl/__init__.py", line 377, in request return await self._endpoint.request( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/zigpy/endpoint.py", line 253, in request return await self.device.request( ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/zigpy/device.py", line 315, in request async with asyncio_timeout(timeout): File "/usr/local/lib/python3.11/asyncio/timeouts.py", line 111, in __aexit__ raise TimeoutError from exc_val TimeoutError The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 238, in handle_call_service response = await hass.services.async_call( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/core.py", line 2067, in async_call response_data = await coro ^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/core.py", line 2104, in _execute_service return await target(service_call) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 272, in handle_service return await service.entity_service_call( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 878, in entity_service_call single_response = await _handle_entity_call( ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 948, in _handle_entity_call result = await task ^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/light/__init__.py", line 591, in async_handle_light_off_service await light.async_turn_off(**filter_turn_off_params(light, params)) File "/usr/src/homeassistant/homeassistant/components/zha/light.py", line 471, in async_turn_off result = await self._on_off_cluster_handler.off() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/zha/core/cluster_handlers/__init__.py", line 83, in wrapper with wrap_zigpy_exceptions(): File "/usr/local/lib/python3.11/contextlib.py", line 155, in __exit__ self.gen.throw(typ, value, traceback) File "/usr/src/homeassistant/homeassistant/components/zha/core/cluster_handlers/__init__.py", line 66, in wrap_zigpy_exceptions raise HomeAssistantError( homeassistant.exceptions.HomeAssistantError: Failed to send request: device did not respond ```

Custom quirk

Custom quirk ```python [Paste your custom quirk here] ```

Additional information

No response

alrassia commented 8 months ago

I have exactly the same device and do not have the issues you describe. The device seems to follow the zigbee spec and should not really need a quirk. Looking at the z2m converter it does not seem to do anything out of the ordinary.

Duchadian commented 8 months ago

I have exactly the same issue @mano3m is describing. Also have another Ecodim dimmer ( a Dim.07 ), which works perfectly fine.

Don't have the knowledge of Zigbee to figure out what is going on, but I can do some checks or debug if anyone can tell me how to do so.

mano3m commented 8 months ago

Hi Duchadian. Do you have both dimmer channels connected to a lamp or only one?

I had contact with EcoDim support recently. They are going on a Home Assistant course soon, but currently dont support HA. They did tell me both channels need to be connected to a lamp/load (which is not the case for me). I wanted to use the dimmer to dim one dumb led lamp and use the other channel through HA to dim a Philips Hue lamp (so without using the actual dimmer, just the Zigbee signal). EcoDim support told me this is not possible.... :(

I also tried to debug the notifiations the EcoDim sends back to ZHA, but it seems it doesnt send anything back.

Note I indeed also have a EcoDim 07, and that one works fine.

alrassia commented 8 months ago

The dimmer is not manufactured or developed by ecodim, its actually an oem branded device by HZC electric. So their support might also be limited in their capacity to really diagnose the issue.

the oem product you cannot easily find but here is a link: https://x.alibaba.com/AvRCTo?ck=pdp I tried to order directly considering the price versus the ecodim price, but they claim not to ship to the netherlands.

Duchadian commented 8 months ago

@mano3m , for me both channels are connected to lamps.

Exactly the same issue regardless. Interestingly, sometimes when both channels are turned on, and I turn the second one off via HA, the first channel starts switching on/off a couple of times before going back to the right state. Haven't yet encountered this behaviour the other way around, but that might be a matter of time.

@alrassia, interesting. I didn't expect Ecodim to make / design them in-house, so I tried finding it as well. Seems like you succeeded where I didn't :)

mano3m commented 8 months ago

@Duchadian Hmm, I have only connected the first channel. I though Home Assistant retries a few times before giving up. If I turn it on, then off, it goes on and off a few times. I am beginning to suspect we have a faulty unit........?

JIK12345 commented 8 months ago

Exactly the same issue here with botch channels connected to a lamp.

Pantsema commented 7 months ago

One additional vote for this device support. Both channels connected and dimming is working, but on/off commands lead into a device did not respond error in HA. Work around is using automations to set brightness to 100% and 0%. Triggering these automations do turn on and off the lights, but when dimming to 0% (thus turning off the lights) the status in HA is off sync (keeps reporting on on the last know brightness level).

odinson394 commented 5 months ago

Hi, I am experiencing exactly the same issue, also with two lamps connected. Would be great if this can be solved, couldn’t find any other duo dimmer solutions!

diekgait commented 2 days ago

Same issue here, two lamps connected. I'd be happy to do some testing.