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

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.

2 Likes

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:

Hi All,

I am having trouble with my hue wall module in combination with a double rocker wall switch. Here is the issue:

  • I have two normal wall switches than can be switched on or off. So two single rocker switches. See picture

  • I want to connect both rocker switches to a single wall module, on port one and two. So I assume I need to set the wall module to mode 3 instead of the default 1. Agree?

  • Changing to mode 2 was succesfull thanks to this guide / @Rudd-O and @Regenbui

Now I have two issues:

  1. The rocker on input 1 fires two events → Right press rlease and remote button short press right event. The rocker on input 2 also fires two events → left press release and remote button short press turn on. The remote button events differ between the rockers and I don’t understand why each rocker gives two events?

Can I ignore this and only attach a automation to one of the events? Which should I use? Or is the wall module set to the wrong mode? Why turn on and the other right event?

image

  1. I am missing the left trigger in the automations? Only right and turn on is visble. When pressing the rocker I do see LEFT being mentioned. How did you resolve this?

Yes, that is normal and you can ignore whichever event you find least useful. Happy to have been helpful!

I have just a single Rocker Switch RDM004 module but needed this script anyway.

Is it correct that the Hue switch module cannot differentiate on or off, so I need to create an if/then/else automation which checks if the light is on and changes state, so emulate the standard rocker switch?

You can use the light.toggle service in that case. Hue modules do not know on from off.

I just cant get my RDM004 to work.
I have it connected to the zigbee dongle, just like my other zigbee devices.
I have installed the script exactly as posted above, but the Philips cluster doesnt show up.
Not only that, but it also doesnt give me any entities to control my lights with.
Can anybody help?

> {
>   "home_assistant": {
>     "installation_type": "Home Assistant OS",
>     "version": "2024.5.5",
>     "dev": false,
>     "hassio": true,
>     "virtualenv": false,
>     "python_version": "3.12.2",
>     "docker": true,
>     "arch": "x86_64",
>     "timezone": "Europe/Amsterdam",
>     "os_name": "Linux",
>     "os_version": "6.6.25-haos",
>     "supervisor": "2024.06.0",
>     "host_os": "Home Assistant OS 12.2",
>     "docker_version": "25.0.5",
>     "chassis": "embedded",
>     "run_as_root": true
>   },
>   "custom_components": {
>     "hacs": {
>       "documentation": "https://hacs.xyz/docs/configuration/start",
>       "version": "1.34.0",
>       "requirements": [
>         "aiogithubapi>=22.10.1"
>       ]
>     },
>     "epex_spot": {
>       "documentation": "https://github.com/mampfes/ha_epex_spot",
>       "version": "2.3.5",
>       "requirements": [
>         "beautifulsoup4"
>       ]
>     }
>   },
>   "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.38.4",
>       "pyserial==3.5",
>       "pyserial-asyncio==0.6",
>       "zha-quirks==0.0.115",
>       "zigpy-deconz==0.23.1",
>       "zigpy==0.64.0",
>       "zigpy-xbee==0.20.1",
>       "zigpy-zigate==0.12.0",
>       "zigpy-znp==0.12.1",
>       "universal-silabs-flasher==0.0.18",
>       "pyserial-asyncio-fast==0.11"
>     ],
>     "usb": [
>       {
>         "vid": "10C4",
>         "pid": "EA60",
>         "description": "*2652*",
>         "known_devices": [
>           "slae.sh cc2652rb stick"
>         ]
>       },
>       {
>         "vid": "10C4",
>         "pid": "EA60",
>         "description": "*slzb-07*",
>         "known_devices": [
>           "smlight slzb-07"
>         ]
>       },
>       {
>         "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": 63057,
>     "manufacturer": "Signify Netherlands B.V.",
>     "model": "RDM004",
>     "name": "Signify Netherlands B.V. RDM004",
>     "quirk_applied": false,
>     "quirk_class": "zigpy.device.Device",
>     "quirk_id": null,
>     "manufacturer_code": 4107,
>     "power_source": "Battery or Unknown",
>     "lqi": 144,
>     "rssi": null,
>     "last_seen": "2024-06-25T15:49:25",
>     "available": true,
>     "device_type": "EndDevice",
>     "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=4107, maximum_buffer_size=82, maximum_incoming_transfer_size=128, server_mask=11264, maximum_outgoing_transfer_size=128, 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": "0x0830",
>           "input_clusters": [
>             "0x0000",
>             "0x0001",
>             "0x0003",
>             "0xfc00"
>           ],
>           "output_clusters": [
>             "0x0000",
>             "0x0003",
>             "0x0004",
>             "0x0006",
>             "0x0008",
>             "0x0019"
>           ]
>         }
>       },
>       "manufacturer": "Signify Netherlands B.V.",
>       "model": "RDM004"
>     },
>     "active_coordinator": false,
>     "entities": [
>       {
>         "entity_id": "sensor.keuken_wandmodule_battery",
>         "name": "Signify Netherlands B.V. RDM004"
>       },
>       {
>         "entity_id": "update.keuken_wandmodule_firmware",
>         "name": "Signify Netherlands B.V. RDM004"
>       },
>       {
>         "entity_id": "button.keuken_wandmodule_identify",
>         "name": "Signify Netherlands B.V. RDM004"
>       }
>     ],
>     "neighbors": [],
>     "routes": [],
>     "endpoint_names": [
>       {
>         "name": "NON_COLOR_SCENE_CONTROLLER"
>       }
>     ],
>     "user_given_name": "keuken-wandmodule",
>     "device_reg_id": "9c5b83a738a23d2c883bbf944c35dfa6",
>     "area_id": "keuken",
>     "cluster_details": {
>       "1": {
>         "device_type": {
>           "name": "NON_COLOR_SCENE_CONTROLLER",
>           "id": 2096
>         },
>         "profile_id": 260,
>         "in_clusters": {
>           "0x0000": {
>             "endpoint_attribute": "basic",
>             "attributes": {
>               "0x0004": {
>                 "attribute_name": "manufacturer",
>                 "value": "Signify Netherlands B.V."
>               },
>               "0x0005": {
>                 "attribute_name": "model",
>                 "value": "RDM004"
>               }
>             },
>             "unsupported_attributes": {}
>           },
>           "0x0001": {
>             "endpoint_attribute": "power",
>             "attributes": {
>               "0x0021": {
>                 "attribute_name": "battery_percentage_remaining",
>                 "value": 200
>               },
>               "0x0020": {
>                 "attribute_name": "battery_voltage",
>                 "value": 30
>               }
>             },
>             "unsupported_attributes": {
>               "0x0031": {
>                 "attribute_name": "battery_size"
>               },
>               "0x0033": {
>                 "attribute_name": "battery_quantity"
>               }
>             }
>           },
>           "0x0003": {
>             "endpoint_attribute": "identify",
>             "attributes": {},
>             "unsupported_attributes": {}
>           },
>           "0xfc00": {
>             "endpoint_attribute": "manufacturer_specific",
>             "attributes": {},
>             "unsupported_attributes": {}
>           }
>         },
>         "out_clusters": {
>           "0x0019": {
>             "endpoint_attribute": "ota",
>             "attributes": {
>               "0x0002": {
>                 "attribute_name": "current_file_version",
>                 "value": 33569808
>               }
>             },
>             "unsupported_attributes": {}
>           },
>           "0x0000": {
>             "endpoint_attribute": "basic",
>             "attributes": {},
>             "unsupported_attributes": {}
>           },
>           "0x0003": {
>             "endpoint_attribute": "identify",
>             "attributes": {},
>             "unsupported_attributes": {}
>           },
>           "0x0004": {
>             "endpoint_attribute": "groups",
>             "attributes": {},
>             "unsupported_attributes": {}
>           },
>           "0x0006": {
>             "endpoint_attribute": "on_off",
>             "attributes": {},
>             "unsupported_attributes": {}
>           },
>           "0x0008": {
>             "endpoint_attribute": "level",
>             "attributes": {},
>             "unsupported_attributes": {}
>           }
>         }
>       }
>     }
>   }
> }

I’ve created a blueprint to get the double, triple, quadruple and long presses working with the RDM004 (and probably the RDM001).

1 Like

Truly awesome. Thanks!