Closed freemanm closed 2 years ago
Another Tuya dimmer device. This one with a GreenPowerProxy
.
3 gang type device Other functions:
Probably also:
Please, enable debug logging and attach the logs from interact with the physical switch:
Logs from three buttons are needed to get the necessary data.
A lot of info (thanks for that) but not exactly the one I expected.
That's what we are going to do, you need to enable the custom_zha_quirks
in your installation. Here is an explanation how to do:
Copy the ts0601_dimmer.py
file in your custom_zha_quirks
folder:
And add this class at the bottom of your local file:
class TuyaTripleSwitchDimmerGPP(TuyaDimmerSwitch):
"""Tuya double channel dimmer device."""
signature = {
# "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0,
# reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>,
# mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>,
# manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752,
# maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>,
# *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": "0x0051", "in_clusters": ["0x0000","0x0004","0x0005","0xef00"],"out_clusters": ["0x000a","0x0019"]},
# "242": {"profile_id": 41440,"device_type": "0x0061","in_clusters": [],"out_clusters": ["0x0021"]}
# },
# "manufacturer": "_TZE200_vm1gyrso",
# "model": "TS0601",
# "class": "zigpy.device.Device"
MODELS_INFO: [
("_TZE200_vm1gyrso", "TS0601"),
],
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaManufCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
242: {
PROFILE_ID: 41440,
DEVICE_TYPE: 97,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
},
}
replacement = {
ENDPOINTS: {
1: {
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaLevelControlManufCluster,
TuyaOnOffMCU,
TuyaInWallLevelControl,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
2: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
TuyaOnOffMCU,
TuyaInWallLevelControl,
],
OUTPUT_CLUSTERS: [],
},
3: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
TuyaOnOffMCU,
TuyaInWallLevelControl,
],
OUTPUT_CLUSTERS: [],
},
242: {
PROFILE_ID: 41440,
DEVICE_TYPE: 97,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
}
}
You will need to import the GreenPowerProxy
class at the beginning of the file:
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, LevelControl, Ota, Scenes, Time
Restart HA and test. If the quirk load, the device signature will change. Buttons 1 and 2 are expected to work. Button 3 don't. We need logs from all not working functions.
I've managed to decode the messages from the third button, so we could have the quirk fully functional. But that requires extra work...
(The steps in the comment above should also be done)
You'll need to copy the tuya.mcu.__init__.py
file to your custom_zha_quirks
folder:
In this file you have to modify the TuyaLevelControlManufCluster
class to add DPs 15-18:
class TuyaLevelControlManufCluster(TuyaMCUCluster):
"""Tuya with Level Control data points."""
dp_to_attribute: Dict[int, DPToAttributeMapping] = {
1: DPToAttributeMapping(
TuyaOnOff.ep_attribute,
"on_off",
dp_type=TuyaDPType.BOOL,
),
2: DPToAttributeMapping(
TuyaLevelControl.ep_attribute,
"current_level",
dp_type=TuyaDPType.VALUE,
converter=lambda x: (x * 255) // 1000,
dp_converter=lambda x: (x * 1000) // 255,
),
3: DPToAttributeMapping(
TuyaLevelControl.ep_attribute,
"minimum_level",
dp_type=TuyaDPType.VALUE,
converter=lambda x: (x * 255) // 1000,
dp_converter=lambda x: (x * 1000) // 255,
),
4: DPToAttributeMapping(
TuyaLevelControl.ep_attribute,
"bulb_type",
dp_type=TuyaDPType.ENUM,
),
7: DPToAttributeMapping(
TuyaOnOff.ep_attribute,
"on_off",
dp_type=TuyaDPType.BOOL,
endpoint_id=2,
),
8: DPToAttributeMapping(
TuyaLevelControl.ep_attribute,
"current_level",
dp_type=TuyaDPType.VALUE,
converter=lambda x: (x * 255) // 1000,
dp_converter=lambda x: (x * 1000) // 255,
endpoint_id=2,
),
9: DPToAttributeMapping(
TuyaLevelControl.ep_attribute,
"minimum_level",
dp_type=TuyaDPType.VALUE,
converter=lambda x: (x * 255) // 1000,
dp_converter=lambda x: (x * 1000) // 255,
endpoint_id=2,
),
10: DPToAttributeMapping(
TuyaLevelControl.ep_attribute,
"bulb_type",
dp_type=TuyaDPType.ENUM,
endpoint_id=2,
),
15: DPToAttributeMapping(
TuyaOnOff.ep_attribute,
"on_off",
dp_type=TuyaDPType.BOOL,
endpoint_id=3,
),
16: DPToAttributeMapping(
TuyaLevelControl.ep_attribute,
"current_level",
dp_type=TuyaDPType.VALUE,
converter=lambda x: (x * 255) // 1000,
dp_converter=lambda x: (x * 1000) // 255,
endpoint_id=3,
),
17: DPToAttributeMapping(
TuyaLevelControl.ep_attribute,
"minimum_level",
dp_type=TuyaDPType.VALUE,
converter=lambda x: (x * 255) // 1000,
dp_converter=lambda x: (x * 1000) // 255,
endpoint_id=3,
),
18: DPToAttributeMapping(
TuyaLevelControl.ep_attribute,
"bulb_type",
dp_type=TuyaDPType.ENUM,
endpoint_id=3,
),
}
Modify (a little further down) the data_point_handlers
:
data_point_handlers = {
1: "_dp_2_attr_update",
2: "_dp_2_attr_update",
3: "_dp_2_attr_update",
4: "_dp_2_attr_update",
7: "_dp_2_attr_update",
8: "_dp_2_attr_update",
9: "_dp_2_attr_update",
10: "_dp_2_attr_update",
15: "_dp_2_attr_update",
16: "_dp_2_attr_update",
17: "_dp_2_attr_update",
18: "_dp_2_attr_update",
}
Now you can go back to your local ts0601_dimmer.py
file and modify the zhaquirks.tuya.mcu
import:
# from zhaquirks.tuya.mcu import (
from custom_zha_quirks import (
TuyaInWallLevelControl,
TuyaLevelControlManufCluster,
TuyaOnOff as TuyaOnOffMCU,
)
Delete cache (any __pycache__
folder inside custom_zha_quirks
), restart HA and test.
Thanks for the info. I do this later today when I am back at my desk and let you know. THanks again for the quick response.
Probably related to #1302
Traces shows messages as manufacturer_specific=False
When I replace
from zhaquirks.tuya.mcu import (
TuyaInWallLevelControl,
TuyaLevelControlManufCluster,
TuyaOnOff as TuyaOnOffMCU,
)
with
# from zhaquirks.tuya.mcu import (
from custom_zha_quirks import (
TuyaInWallLevelControl,
TuyaLevelControlManufCluster,
TuyaOnOff as TuyaOnOffMCU,
)
My installation brakes. Up to this point it detected the Quirk on the device and loaded three switches but I did not work from HA yet. I could not turn any switch on/off from HA or when I switch any of the switches on/off on the physical device if also did not change the status in HA.
I am getting the following error when I press a button on the physical light switch:
Logger: zigpy.zcl
Source: /usr/local/lib/python3.9/site-packages/zhaquirks/tuya/__init__.py:1295
First occurred: 21:18:06 (1 occurrences)
Last logged: 21:18:06
[0x0e44:1:0xef00] No 'handle_get_data' tuya handler found for [TuyaCommand(status=0, tsn=230, dp=15, data=TuyaData(dp_type=<TuyaDPType.BOOL: 1>, function=0, raw=b'\x01', *payload=<Bool.true: 1>))]
And this is the startup error when I add the last change:
Logger: homeassistant.config_entries
Source: custom_zha_quirks/ts0601_dimmer.py:28
First occurred: 21:21:10 (1 occurrences)
Last logged: 21:21:10
Error setting up entry Sonoff Zigbee 3.0 USB Dong - /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_3ef772decbc9eb11941c914f1d69213e-if00-port0, s/n: 3ef772decbc9eb11941c914f1d69213e - ITead - 10C4:EA60 for zha
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/config_entries.py", line 335, in async_setup
result = await component.async_setup_entry(hass, self)
File "/usr/src/homeassistant/homeassistant/components/zha/__init__.py", line 99, in async_setup_entry
setup_quirks(config)
File "/usr/local/lib/python3.9/site-packages/zhaquirks/__init__.py", line 403, in setup
importer.find_module(modname).load_module(modname)
File "<frozen importlib._bootstrap_external>", line 529, in _check_name_wrapper
File "<frozen importlib._bootstrap_external>", line 1029, in load_module
File "<frozen importlib._bootstrap_external>", line 854, in load_module
File "<frozen importlib._bootstrap>", line 274, in _load_module_shim
File "<frozen importlib._bootstrap>", line 711, in _load
File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 850, in exec_module
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
File "/config/custom_zha_quirks/ts0601_dimmer.py", line 28, in <module>
from custom_zha_quirks import (
ImportError: cannot import name 'TuyaInWallLevelControl' from 'custom_zha_quirks' (unknown location)
What is the content of your custom_zha_quirks
folder?
Have you copied the class tuya.mcu.__init__.py
there?
I have the following files in my custom_zha_quirks
folder:
ts0601_dimmer.py
tuya.mcu.__init__.py
Ok, rename the file tuya.mcu.init.py
to __init__.py
(its original name).
Delete cache (all __pycache__
folders) and restart.
THe name was correct. It is just the copy to Bit that changed it. I also do not have a __pycache__
folder.
P.S When I look at the device in HA it also still show the device as a "Router" and not an "EndDevice"
Ummmm, not sure
You must have inside the custom_zha_quirks
root two files, withou any folder something like:
custom_zha_quirks
+ ts0601_dimmer.py
+ __init__.py
P.S When I look at the device in HA it also still show the device as a "Router" and not an "EndDevice"
That's what the node_descriptor
says:
"node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, .../..., *is_router=True, *is_security_capable=False)",
Did you expect something different?
It is very likely that the control from HA will not work. That issue is the one addressed in #1302
Maybe you can help us to test the solution 😉
I have now rename the file to __init__.py
as you indicated but this is the log message I get.
Logger: homeassistant.config_entries
Source: custom_zha_quirks/__init__.py:165
First occurred: 21:41:57 (1 occurrences)
Last logged: 21:41:57
Error setting up entry Sonoff Zigbee 3.0 USB Dong - /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_3ef772decbc9eb11941c914f1d69213e-if00-port0, s/n: 3ef772decbc9eb11941c914f1d69213e - ITead - 10C4:EA60 for zha
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/config_entries.py", line 335, in async_setup
result = await component.async_setup_entry(hass, self)
File "/usr/src/homeassistant/homeassistant/components/zha/__init__.py", line 99, in async_setup_entry
setup_quirks(config)
File "/usr/local/lib/python3.9/site-packages/zhaquirks/__init__.py", line 403, in setup
importer.find_module(modname).load_module(modname)
File "<frozen importlib._bootstrap_external>", line 529, in _check_name_wrapper
File "<frozen importlib._bootstrap_external>", line 1029, in load_module
File "<frozen importlib._bootstrap_external>", line 854, in load_module
File "<frozen importlib._bootstrap>", line 274, in _load_module_shim
File "<frozen importlib._bootstrap>", line 711, in _load
File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 850, in exec_module
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
File "/config/custom_zha_quirks/ts0601_dimmer.py", line 28, in <module>
from custom_zha_quirks import (
File "/config/custom_zha_quirks/__init__.py", line 127, in <module>
class TuyaMCUCluster(TuyaAttributesCluster, TuyaNewManufCluster):
File "/config/custom_zha_quirks/__init__.py", line 165, in TuyaMCUCluster
TUYA_MCU_VERSION_RSP: foundation.ZCLCommandDef(
AttributeError: module 'zigpy.zcl.foundation' has no attribute 'ZCLCommandDef'
THis is my root folder:
custom_zha_quirks
+ ts0601_dimmer.py
+ __init__.py
Ok, now the files are in place, but the Github version is updated from yours HA version. Let me see how fix it.
Would it be possible for you to upgrade to the beta version of HA?
(while I check how can I fix it)
Ok, you can get the file previous version from here:
Then implement the changes from https://github.com/zigpy/zha-device-handlers/issues/1461#issuecomment-1088085670
I am running the Ha OS version on a PI.
Let me see what I can do. I looks like the install does not find the custom_zha_quirks
folder in the HA /config folder for the import.
No, the custom_zha_quirks
seems to be working. The problem is at the zigpy
library that has been updated and you don't have yet in your HA.
If you have access to the cli it can be done as:
ha core update --version 2022.4.0b5
OK I made the changes and it now loads correct without errors. I now get the right device with the three switches AND when I press any of the three button of the physical switch to its on/off position it correctly show the right on/off status in HA.
What is not working is that I can change the switch status in HA and then the physical switch also change. It just jump back to its original state.
P.S Just to be clear. I have not upgraded to the beta version, I just updated the init file and re-apply the changes to the previous version's file.
I have not upgraded, do you want me to try this still?
Is the dimmer part working also? For all the three buttons?
What is not working is that I can change the switch status in HA and then the physical switch also change. It just jump back to its original state.
This part is expected, but to test it you need to update the zigpy
library to the latest version.
The way I can think of to do it is to update to a beta version of HA or wait until tomorrow they release v2022.05 of HA.
OK. Lets wait to tomorrow then. After tomorrows update must I change to the original init file you provided or should I keep the one I have now?
I have not upgraded, do you want me to try this still?
If it's not too much trouble, it would be very useful to us.
(I'll be back here in a while)
After tomorrows update must I change to the original init file you provided or should I keep the one I have now?
You will need to replace with the actual one (and perform again all the modifications):
@freemanm Edit title so it says -> "Moes 3 Gang Light Dimmer Switch ZS-USD3-WH-MS (Tuya "_TZE200_vm1gyrso", "TS0601")"
The current title says "Moer Dimmer LIght Switch" which wrong spelling and lack of info will not make anyone else fins this issue.
And just to make easier to read and scroll the thread, could you edit your https://github.com/zigpy/zha-device-handlers/issues/1461#issuecomment-1089234078 to put the class definitions in collapsed sections?
It would be something like:
I have the following files in my custom_zha_quirks folder:
* ts0601_dimmer.py
* tuya.mcu.__init__.py
<details>
<summary>ts0601_dimmer.py</summary>
"""Tuya based touch switch."""
from zigpy.profiles import zha
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, LevelControl, Ota, Scenes, Time
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
)
.../...
</details>
<details>
<summary>tuya.mcu.init.py</summary>
"""Tuya MCU comunications."""
import dataclasses
from typing import Any, Callable, Dict, Optional, Tuple, Union
import zigpy.types as t
from zigpy.zcl import foundation
from zigpy.zcl.clusters.general import LevelControl, OnOff
from zhaquirks import Bus
from zhaquirks.tuya import (
ATTR_ON_OFF,
TUYA_MCU_COMMAND,
TUYA_MCU_VERSION_RSP,
TUYA_SET_DATA,
Data,
PowerOnState,
TuyaCommand,
TuyaData,
TuyaLocalCluster,
TuyaNewManufCluster,
)
.../...
</details>
Thanks in advanced.
refs:
I have now done the following
__init__py
to the latest version and re-apply the changesCurrent working status
Not working
I can't see how can be related to the quirk. Any other related log? Something from zigpy or from zhaquirks?
The new version is being tested here too:
If you want to try it, the changes to make are the following:
from typing import Optional, Union
from zigpy.profiles import zha from zigpy.quirks import CustomCluster import zigpy.types as t from zigpy.zcl import foundation from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, LevelControl, Ota, Scenes, Time
from zhaquirks.const import ( .../...
* add 2 new classes before the first class in the file:
```python
class NoManufacturerCluster(CustomCluster):
"""Forces the NO manufacturer id in command."""
async def command(
self,
command_id: Union[foundation.GeneralCommand, int, t.uint8_t],
*args,
manufacturer: Optional[Union[int, t.uint16_t]] = None,
expect_reply: bool = True,
tsn: Optional[Union[int, t.uint8_t]] = None,
):
"""Override the default Cluster command."""
self.debug("Setting the NO manufacturer id in command: %s", command_id)
return await super().command(
command_id,
*args,
foundation.ZCLHeader.NO_MANUFACTURER_ID,
expect_reply,
tsn,
)
class TuyaInWallLevelControlNM(NoManufacturerCluster, TuyaInWallLevelControl):
"""Tuya Level cluster for inwall dimmable device with NoManufacturerID."""
pass
TuyaTripleSwitchDimmerGPP
class the replacement
part (replace the TuyaInWallLevelControl
):
replacement = {
ENDPOINTS: {
1: {
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaLevelControlManufCluster,
TuyaOnOffMCU,
TuyaInWallLevelControlNM,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
2: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
TuyaOnOffMCU,
TuyaInWallLevelControlNM,
],
OUTPUT_CLUSTERS: [],
},
3: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
INPUT_CLUSTERS: [
TuyaOnOffMCU,
TuyaInWallLevelControlNM,
],
OUTPUT_CLUSTERS: [],
},
242: {
PROFILE_ID: 41440,
DEVICE_TYPE: 97,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
}
}
Test the dimm function from HA and report.
Thanks in advanced.
@puddly Sorry to ping you directly, but I think that this error can be related with the zigpy version bump and all the changes related to ZCLv7:
Logger: homeassistant.components.websocket_api.http.connection
Source: components/zha/light.py:258
Integration: Home Assistant WebSocket API (documentation, issues)
First occurred: 19:34:34 (1 occurrences)
Last logged: 19:34:34
[140335046155040] 'Status' object is not subscriptable
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 193, in handle_call_service
await hass.services.async_call(
File "/usr/src/homeassistant/homeassistant/core.py", line 1634, in async_call
task.result()
File "/usr/src/homeassistant/homeassistant/core.py", line 1671, in _execute_service
await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 204, in handle_service
await service.entity_service_call(
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 677, in entity_service_call
future.result() # pop exception if have
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 955, in async_request_call
await coro
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 714, in _handle_entity_call
await result
File "/usr/src/homeassistant/homeassistant/components/light/__init__.py", line 504, in async_handle_light_on_service
await light.async_turn_on(**filter_turn_on_params(light, params))
File "/usr/src/homeassistant/homeassistant/components/zha/light.py", line 258, in async_turn_on
if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
TypeError: 'Status' object is not subscriptable
Does it rings you any bell?
Probably the fault is in any tuya
class (if not it would be a spread error) but I'm not able to see the reason.
Any advice or suggestion?
Thanks in advanced.
No worries, they probably are. What does the debug log show? Is any Tuya light class returning a list or status code directly? Any way to set a breakpoint to see what exactly result
is and why it's a bare Status
object?
No worries, they probably are. What does the debug log show? Is any Tuya light class returning a list or status code directly? Any way to set a breakpoint to see what exactly
result
is and why it's a bareStatus
object?
An affected user has open an issue. We can continue from there:
One more interesting posting for our @javicalle about MCU dimmers Z2M user have "finding" https://github.com/Koenkk/zigbee-herdsman/pull/519. The linked issues have good sniffing from tuya TBGW :-)))
I have made the additional changes you requested with the same results.
Example: When I try and turn on or off a switch from HA I get an error.
It's fine, the On/Off cluster is not fixed yet.
Can you attach the logs dimming the device from HA?
@freemanm I have ajusted the code. Could you add the await clause in the method call? Just like this:
self.debug("Setting the NO manufacturer id in command: %s", command_id)
return await super().command(
command_id,
*args,
manufacturer=zcl.foundation.ZCLHeader.NO_MANUFACTURER_ID,
expect_reply=expect_reply,
tsn=tsn,
)
(also updated in original comment)
I'm messing everything up because I have parallel conversations in several threads. @freemanm could we continue the conversation in this other thread:
Sorry for the inconvenience.
@freemanm I think this issue can be closed, since it is continued in the other one
No need to close now. When PR is created it can be linked to this (an others issues) just putting in the PR body: Fixes: #1461 This way, when PR is merged, automatically closes the related isuues
No need to close now. When PR is created it can be linked to this (an others issues) just putting in the PR body: Fixes: #1461 This way, when PR is merged, automatically closes the related isuues
Yes and another reason not to close is that sometimes can also happen that a PR is closed without being accepted and merged.
@javicalle @Hedda Okay, sorry, my mistake.
I got this working in zigbee2mqtt. Not perfect, but does the job. Here's a custom converter: https://gist.github.com/muxa/94e29b8896c89da910e4e4a80fc44894 (code needs a cleanup)
It detects and controls state (on/off) and brightness for all 3 gangs.
Known issues:
I like to request support for the Moer Zigbee Dimmer Light Switch. see signature detail below. THe switch I have is a 3-gang version
It is currently pick up as a router and not an End-Device. THis is a link to the vendor website.
Signature