Aqara Light Switch H2 EU in ZHA: Enable Decoupled Mode with a Custom Quirk

The Aqara Light Switch H2 EU (Zigbee model lumi.switch.agl009) only works in a rudimentary way under Home Assistant’s ZHA integration: a switch entity, power and energy readings, and little else. No decoupled mode, no click events, no LED or power-on control. A custom quirk brings back the full feature set – without switching to Zigbee2MQTT. This guide walks you through it step by step; it was carried out and verified on six switches on 1 September 2026.

Why the H2 only half-works under ZHA

Pair the H2 in ZHA and you get a switch entity, power, an energy meter, LQI/RSSI, Identify and firmware info – nothing more. For comparison: the exact same device is fully supported under Zigbee2MQTT. The reason shows up in the device diagnostics. Download them (Settings → Devices → the device → menu → “Download diagnostics”) and you will see:

"quirk_applied": false,
"quirk_class": "zigpy.device.Device"

So no quirk applies at all – zigpy only parses the raw ZCL profile. The manufacturer-specific cluster 0xFCC0 is present on several endpoints, but its attribute list is empty. Yet that is exactly where decoupled mode, LED control, power-on behaviour, relay lock and multi-click live. On top of that, the multistate_input clusters stay silent, so no button-press events are generated. Without a matching quirk, ZHA simply cannot know these attributes. If you first want to sort out the fundamental differences between the two Zigbee paths, see our comparison Zigbee2MQTT vs. ZHA.

Requirements

  • Home Assistant 2026.8 or newer (tested with 2026.8.3 on HA OS 18.2)
  • An active ZHA integration (tested with zha 2.1.0 / zha-quirks 2.2.0)
  • Access to the /config directory, e.g. via the “Advanced SSH & Web Terminal” or “File editor” add-on
  • The H2 EU as lumi.switch.agl009 (2 buttons/1 channel) – the quirk also covers agl010, agl004, agl005 and agl006

The finished quirk comes from the still-open pull request zigpy/zha-device-handlers #4141 (“Add Aqara H2 switches (EU+US)”). Because it is not yet part of zha-quirks 2.2.0, we add it as a local custom quirk.

Matching device: Aqara Light Switch H2 EU

Exactly the model used in this guide: 2-in-1 (with/without neutral), 2 buttons / 1 channel, Thread & Matter, Zigbee model lumi.switch.agl009.

Affiliate link – buying through it supports netguide.io at no extra cost to you.

Step 1: Create the quirk folder and add it to the YAML

ZHA loads custom quirks from a directory you define in configuration.yaml:

zha:
  enable_quirks: true
  custom_quirks_path: /config/zha_quirks/

Mind the order: Home Assistant validates the path at startup with cv.isdir. If the folder does not exist yet, the config check fails. So create the /config/zha_quirks/ directory first and add the YAML afterwards. There is no field for this in the integration’s options dialog – it is YAML-only configuration.

Step 2: Install the quirk file

The most robust approach is to download the file pinned to a fixed commit – that way its contents will not change while the PR keeps evolving. In the HA terminal:

wget -O /config/zha_quirks/switch_h2.py \
  https://raw.githubusercontent.com/lonevvolf/zha-device-handlers/c06083b1d655c1787f5c0c2f56edd84b970328d4/zhaquirks/xiaomi/aqara/switch_h2.py

# verify integrity (optional but recommended)
sha256sum /config/zha_quirks/switch_h2.py
# fc846cbd24a37a51964196d999d46bc6516662d937227b9b1b2e1ed1410e017a  (19761 bytes, 575 lines)

ha core restart

The checksum matches commit c06083b from 27 August 2026. If it matches on your side, you have exactly the same file as in this guide.

Step 3: Restart and verify

After the restart, download the diagnostics for the same device again. It should now read:

"quirk_applied": true,
"quirk_class": "switch_h2:(Aqara / lumi.switch.agl009)"

The system log shows the message zhaquirks: Loaded custom quirks. Please contribute them to … at WARNING level. This is not an error – it is a normal notice that a custom quirk is active.

The result is visible right on the device: instead of 7, each switch now exposes 13 entities. The new “Configuration” card looks like this:

Home Assistant configuration card of the Aqara H2 EU with operating mode Decoupled, LED indicator, Lock relay, Multi click and Power on mode
After the quirk, ZHA shows operating mode (Decoupled), LED indicator, Flip LED indicator, Lock relay, Multi click and Power on mode – the values are read live from the device.

The new entities you get

EntityTypeFunction
Operating modeSelectSwitch between Decoupled and Relay
Power on modeSelectBehaviour after power returns: On, Previous, Off, Inverted
LED indicatorSwitchTurn the status LED on/off
Flip LED indicatorSwitchInvert the LED logic
Lock relaySwitchFreeze the relay in its current state
Multi clickSwitchEnable multi-click detection

The values are not just created but actually read from the device – in our test the operating mode came back as Relay and the power-on mode as Previous.

Enabling Decoupled Mode safely

In decoupled mode the rocker is decoupled from the relay: the physical switch no longer cuts power, it only reports the button press to Home Assistant. That is exactly what you want when smart bulbs sit behind the switch and need permanent power. So that the bulbs are never left without power, follow this order:

  • First turn on the switch entity (relay closed, the bulbs have constant power).
  • Then set the operating mode to Decoupled (the rocker can no longer cut power).
  • Optionally enable Lock relay so no accidental automation opens the relay either.

Important: In decoupled mode the light switch depends on Home Assistant being available. If HA is down, the rocker does nothing. If an ordinary (non-smart) lamp sits behind the switch, you do not need decoupled mode at all – the rocker then switches directly as usual.

Using click events in automations

The quirk makes the buttons fire the zha_event. The event command is composed of endpoint and press type. For the agl009:

  • Button 1: 1_single, 1_double, 1_hold, 1_release
  • Button 2: 4_single, 4_double, 4_hold, 4_release

Because ZHA does not create event.* entities for these switches, you trigger on the zha_event directly. Use device_ieee instead of device_id – the IEEE address survives re-pairing the device. Branch via trigger IDs and choose:

alias: Kitchen – wall switch (decoupled)
triggers:
  - trigger: event
    event_type: zha_event
    event_data:
      device_ieee: "AA:BB:CC:DD:EE:FF:00:11"
      command: "1_single"
    id: toggle
  - trigger: event
    event_type: zha_event
    event_data:
      device_ieee: "AA:BB:CC:DD:EE:FF:00:11"
      command: "1_double"
    id: bright
conditions: []
actions:
  - choose:
      - conditions:
          - condition: trigger
            id: toggle
        sequence:
          - action: light.toggle
            target:
              entity_id: light.kitchen
      - conditions:
          - condition: trigger
            id: bright
        sequence:
          - action: light.turn_on
            target:
              entity_id: light.kitchen
            data:
              brightness_pct: 100
mode: queued
max: 10

mode: queued is deliberate so that quick button sequences are not dropped. The quirk maps the press types as follows: 0 = hold, 1 = single, 2 = double, 3 = triple, 255 = release.

Limits and pitfalls

  • No direct Zigbee binding to lamps. EP 1 only exposes Time and OTA as out-clusters – no OnOff client. So the switch sends no Zigbee switching commands; it reports presses as attribute reports. Zigbee “binding” and groups are therefore out; everything runs through Home Assistant automations.
  • Writes can fail over Zigbee. The H2 report themselves as an EndDevice with “Battery or Unknown”, even though they are mains-powered. ZHA then treats them like sleeping devices at times, and a switch acknowledges with ZIGBEE_DELIVERY_FAILED. Fix: press the rocker once to wake the device, then write again.
  • LED indicator may have no effect on EU variants. Testers report that LED control has no effect on EU models, while it works on US/AU. Decoupled mode and click events are unaffected.
  • Delete the local copy after the merge. Custom quirks take precedence over built-in ones. Once the PR is merged and part of zha-quirks, remove switch_h2.py from /config/zha_quirks/ – otherwise the frozen file permanently overrides the maintained upstream quirk.

FAQ

What exactly is decoupled mode?

It decouples the physical rocker from the internal relay. The switch no longer cuts power itself; it only reports the button press – ideal for smart bulbs that need constant power.

Do I need the quirk with an ordinary lamp too?

No. If a regular, non-smart lamp sits behind the switch, the rocker works directly and reliably in the default mode (Relay) – even without Home Assistant. Decoupled mode only makes sense with smart bulbs.

What happens when the pull request is merged?

The quirk will eventually become a fixed part of zha-quirks. Delete your local switch_h2.py so the updated upstream version is used instead of your frozen copy.

Why doesn’t my LED indicator respond?

On EU variants several users report that LED control has no effect. This is known and affects neither decoupled mode nor the click events.

Can I bind the switch directly to a Zigbee lamp?

No. The switch lacks the required OnOff client cluster. You connect the button press to the lamp through a Home Assistant automation (see above).


Sources: Pull request #4141 (zha-device-handlers) · Device support request H2 EU · Zigbee2MQTT converter (attribute semantics). Note: the H2 EU dimmer (lumi.switch.agl011) is not covered by this quirk.

Scroll to Top