How to configure the Philips Hue wall module to use push button (momentary) type wall switches [ZHA]

I’m not familiar with other clusters, but I do know that in HA I get distinct events “long release”, “short release” and “short press” which I can use to decide what to do when long pressing.

Did you find a solution for this in the meantime?

I was looking for this for a while now. Thank you for describing it.

The improve your blog post, please show a screenshot without “enum.undefined…” when changing the mode. Else it does not work when writing the updated mode.

1 Like

Thanks. I will soon.

Hello all,

im new to HA and I am working into moving my Hue devices to the SkyConnect Stick (via ZHA). I am facing the same issues with the Hue wall switch. I was able to connect it to the new Zigbee network but I allways get an error when I am trying to change the config to dual rocker mode. I can not set the value to 3.

What am I doing wrong?

Error:

Change “wert” from enum8.undefined_0x00 to 0, report back please.

1 Like

Thx a lot @Rudd-O! It is working now. You really saved me

1 Like

I have a few Hue Wall Switch RDM004 and HA Yellow, in zigbee zha integration I don’t have the cluster: Philips Basic Cluster.
see attached image.

What options you get with the first Basic cluster?

This is the full list of attributes of the RDM004. No mentioning of ‘mode’ or ‘0x0034’ here. Also not at the other clusters.

I have the same “problem”, no attribute to change the configuration.

Ok guys, I had the same problem as most of you, but managed to make it working.

Why don’t you see the needed configuration…well you most likely have a newer model named RDM004. Apparently this is not supported yet.

Here are my steps to make it work.

  1. Open you favourite file editor. I use Studio Code Server;
  2. Make a new folder. In my case the folder is named “custom_zha_quirks”;
  3. Make a new file named MYFILE.PY
  4. Paste the following content into it:
"""Signify RDM004 device."""
import logging
from typing import Any, List, Optional, Union

from zigpy.profiles import zha
from zigpy.quirks import CustomCluster, CustomDevice
import zigpy.types as t
from zigpy.zcl import foundation
from zigpy.zcl.clusters.general import (
    Basic,
    Groups,
    Identify,
    LevelControl,
    OnOff,
    Ota,
    PowerConfiguration,
)

from zhaquirks.const import (
    ARGS,
    BUTTON,
    COMMAND,
    COMMAND_ID,
    DEVICE_TYPE,
    DOUBLE_PRESS,
    ENDPOINTS,
    INPUT_CLUSTERS,
    LONG_PRESS,
    LONG_RELEASE,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PRESS_TYPE,
    PROFILE_ID,
    QUADRUPLE_PRESS,
    QUINTUPLE_PRESS,
    RIGHT,
    SHORT_PRESS,
    SHORT_RELEASE,
    TRIPLE_PRESS,
    TURN_ON,
    ZHA_SEND_EVENT,
)
from zhaquirks.philips import PHILIPS, SIGNIFY

DEVICE_SPECIFIC_UNKNOWN = 64512
_LOGGER = logging.getLogger(__name__)


class PhilipsBasicCluster(CustomCluster, Basic):
    """Philips Basic cluster."""

    attributes = Basic.attributes.copy()
    attributes.update(
        {
            0x0031: ("philips", t.bitmap16, True),
            0x0034: ("mode", t.enum8, True),    
        }
    )

    attr_config = {0x0031: 0x000B, 0x0034: 0x02}

    async def bind(self):
        """Bind cluster."""
        result = await super().bind()
        await self.write_attributes(self.attr_config, manufacturer=0x100B)
        return result


class PhilipsRemoteCluster(CustomCluster):
    """Philips remote cluster."""

    cluster_id = 64512
    name = "PhilipsRemoteCluster"
    ep_attribute = "philips_remote_cluster"
    client_commands = {
        0x00: foundation.ZCLCommandDef(
            "notification",
            {
                "param1": t.uint8_t,
                "param2": t.uint24_t,
                "param3": t.uint8_t,
                "param4": t.uint8_t,
                "param5": t.uint8_t,
                "param6": t.uint8_t,
            },
            is_manufacturer_specific=True,
            direction=foundation.Direction.Server_to_Client,
        )
    }
    BUTTONS = {
        1: "left",
        2: "right",
    }
    PRESS_TYPES = {0: "press", 1: "hold", 2: "press_release", 3: "hold_release"}

    def handle_cluster_request(
        self,
        hdr: foundation.ZCLHeader,
        args: List[Any],
        *,
        dst_addressing: Optional[
            Union[t.Addressing.Group, t.Addressing.IEEE, t.Addressing.NWK]
        ] = None,
    ):
        """Handle the cluster command."""
        _LOGGER.debug(
            "PhilipsRemoteCluster - handle_cluster_request tsn: [%s] command id: %s - args: [%s]",
            hdr.tsn,
            hdr.command_id,
            args,
        )

        button = self.BUTTONS.get(args[0], args[0])
        press_type = self.PRESS_TYPES.get(args[2], args[2])

        event_args = {
            BUTTON: button,
            PRESS_TYPE: press_type,
            COMMAND_ID: hdr.command_id,
            ARGS: args,
        }

        action = f"{button}_{press_type}"
        self.listener_event(ZHA_SEND_EVENT, action, event_args)


class PhilipsROM004(CustomDevice):
    """Philips ROM004 device."""

    signature = {
        #  <SimpleDescriptor endpoint=1 profile=260 device_type=2080
        #  device_version=1
        #  input_clusters=[0, 1, 3, 64512]
        #  output_clusters=[3, 4, 6, 8, 25]>
        MODELS_INFO: [(PHILIPS, "RDM004"), (SIGNIFY, "RDM004")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.NON_COLOR_SCENE_CONTROLLER,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfiguration.cluster_id,
                    Identify.cluster_id,
                    DEVICE_SPECIFIC_UNKNOWN,
                ],
                OUTPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    OnOff.cluster_id,
                    LevelControl.cluster_id,
                    Ota.cluster_id,
                ],
            }
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.NON_COLOR_CONTROLLER,
                INPUT_CLUSTERS: [
                    PhilipsBasicCluster,
                    PowerConfiguration.cluster_id,
                    Identify.cluster_id,
                    PhilipsRemoteCluster,
                ],
                OUTPUT_CLUSTERS: [
                    Ota.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    OnOff.cluster_id,
                    LevelControl.cluster_id,
                ],
            }
        }
    }

    device_automation_triggers = {
        (SHORT_PRESS, TURN_ON): {COMMAND: "left_press"},
        (LONG_PRESS, TURN_ON): {COMMAND: "left_hold"},
        (DOUBLE_PRESS, TURN_ON): {COMMAND: "left_double_press"},
        (TRIPLE_PRESS, TURN_ON): {COMMAND: "left_triple_press"},
        (QUADRUPLE_PRESS, TURN_ON): {COMMAND: "left_quadruple_press"},
        (QUINTUPLE_PRESS, TURN_ON): {COMMAND: "left_quintuple_press"},
        (SHORT_RELEASE, TURN_ON): {COMMAND: "left_short_release"},
        (LONG_RELEASE, TURN_ON): {COMMAND: "left_long_release"},
        (SHORT_PRESS, RIGHT): {COMMAND: "right_press"},
        (LONG_PRESS, RIGHT): {COMMAND: "right_hold"},
        (DOUBLE_PRESS, RIGHT): {COMMAND: "right_double_press"},
        (TRIPLE_PRESS, RIGHT): {COMMAND: "right_triple_press"},
        (QUADRUPLE_PRESS, RIGHT): {COMMAND: "right_quadruple_press"},
        (QUINTUPLE_PRESS, RIGHT): {COMMAND: "right_quintuple_press"},
        (SHORT_RELEASE, RIGHT): {COMMAND: "right_short_release"},
        (LONG_RELEASE, RIGHT): {COMMAND: "right_long_release"},
    }
  1. Open configuration. yaml
  2. add the following lines:
zha:
  enable_quirks: true
  custom_quirks_path: /config/custom_zha_quirks
  1. remove the HUE module from you devices;
  2. Restart home assistant;
  3. Go back to devices. Right now alle names mentioned in this topic should be visible.
  4. follow the steps in this blog post: Make the Philips Hue wall switch module work with push button switches in Home Assistant — Rudd-O.com
  5. please note:
  • Select in Cluster: PhilipsBasicCluster << should be available now
  • Attributes: MODE (ID: 0x0034) << should be avaible now
  • Value: enter 2. This value enables a double rocker switch

  1. NOW WAIT
  2. if i’m correct one of the two switches is working, or at lease it should be. You can see it in the log of the device. Figure out which one is working.
  3. Now before you click “write attribute” you first click the button that is working. This wakes up the device. If you don’t do this, HA/Zigbee can’t communicate with the device.
  4. Within half a second after you clicked the button of the device to wake it up, you press write.

All done, you have two rocker type buttons working perfectly.

I’m using NODE RED, which makes it easy to separate the buttons based on action and ID.

2 Likes

I just found it myself but thanks :smiley:

Got the RDM004 module working with the instruction of Regenbui and now I see many options in the automation section. Module was set to mode “3” as I have a 2 Button Rocker implemented.

When I use automations only the option “single press” is working.
All of the other options “double click”, “triple click”… don’t work.

Can somebody give an advice how to make at least the double click option running?

With the quirk it worked for me now, but same as tegner23, not the double or triple click.

Unfortunately this doesn’t work for me. I’ve installed the RDM004 device with the quirk and all options show up as expected. Now I want to make it work as a double push button, but can’t change the mode from 0 to 3. I’ve tried many times but without any luck. It keeps returning “Kan service zha/set_zigbee_cluster_attribute niet aanroepen undefined_0x00”.
Did anyone encounter the same problem?

1 Like

same problem for me, getting the error “Fehler beim Aufrufen des Diensts zha/set_zigbee_cluster_attribute. ‘undefined_0x03’” which sounds quite similar to yours.

Log from HA:

[547341280320] 'undefined_0x03'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 239, in handle_call_service
    response = await hass.services.async_call(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/core.py", line 2542, in async_call
    response_data = await coro
                    ^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/core.py", line 2579, in _execute_service
    return await target(service_call)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 1074, in _async_admin_handler
    await result
  File "/usr/src/homeassistant/homeassistant/components/zha/websocket_api.py", line 1308, in set_zigbee_cluster_attributes
    response = await zha_device.write_zigbee_attribute(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/zha/core/device.py", line 789, in write_zigbee_attribute
    response = await cluster.write_attributes(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/zigpy/zcl/__init__.py", line 625, in write_attributes
    attrs = self._write_attr_records(attributes)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/zigpy/zcl/__init__.py", line 604, in _write_attr_records
    attr.value.value = attr_def.type(value)
                       ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/zigpy/types/basic.py", line 436, in __call__
    value = cls[value[len(cls.__name__) + 1 :]].value
            ~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/enum.py", line 801, in __getitem__
    return cls._member_map_[name]
           ~~~~~~~~~~~~~~~~^^^^^^
KeyError: 'undefined_0x03'

You’re not supposed to write undefined_0x03. Just write 3.

1 Like

Thanks for the hint, I was stupid and tried to put in the value in the bottom field, not the value field… works like a charm, thanks :slight_smile: