Pairing IKEA KAJPLATS and BILRESA Devices Over Matter-over-Thread and Building a Home Assistant Blueprint

IKEA KAJPLATS bulb and BILRESA remotes commissioned over Matter-over-Thread into Home Assistant

IKEA's new KAJPLATS bulb and BILRESA remotes ship with Matter-over-Thread firmware and a Zigbee-capable radio. Pair them the way the quick-start card suggests and they bond to each other over Zigbee Touchlink, which pulls both devices off Thread and out of Home Assistant. This guide commissions them over Matter with a QR code instead, explains why the remotes cannot bind directly to the bulb, and finishes with two reusable Home Assistant Blueprints, one for the BILRESA two-way switch and one for the scroll wheel.

For the story behind this build, read Fun with the New IKEA Smart Devices on Frizzle Tech Blog.

Prerequisites

You need a working Home Assistant install with the Matter Server add-on running, at least one Thread border router on the same network, and the Home Assistant Companion App on a phone. Matter commissioning relies on local IPv6 and mDNS, so the phone, the border router, and Home Assistant must share a LAN that passes multicast traffic.

  • IKEA KAJPLATS E26 smart bulb, plus a lamp to hold it.
  • IKEA BILRESA two-way switch (dual button) and BILRESA scroll wheel, with AAA batteries.
  • A Thread border router (for example a Home Assistant Connect ZBT-2, a Nest Hub, or a HomePod).
  • Home Assistant with the Matter Server add-on, and the Companion App on your phone.
  • An IPv6-enabled LAN with working local mDNS discovery.

Step 1: Sync Thread Credentials and Commission Over Matter

Do not hold the remote near the bulb and press the pairing button four times. That starts Zigbee Touchlink, which bonds the two devices directly and removes them from Thread. Commission each device separately instead.

On a new Android phone, Bluetooth transfer can succeed while the local Matter handshake times out. Fix that before you scan anything. In the Companion App, open Settings, then Companion App, then Troubleshooting, and choose Sync Thread credentials. Next, confirm your preferred Thread network under Android Settings, then Google, then Devices & sharing, then Thread networks. If the handshake still times out, turn off Private DNS temporarily and restart the phone so Google Play Services picks up the fresh Thread dataset.

Put the device in Matter pairing mode. For a BILRESA, hold the pairing button inside the battery compartment for about 10 seconds, until the LED pulses. For a KAJPLATS, power cycle it 6 times. Then open Settings, then Devices & Services, then Add Device, choose Add Matter device, and scan the QR code on the packaging. Repeat for each remote and the bulb.

Step 2: Understand Touchlink, Zigbee, and the Matter Switch Endpoint

Zigbee is a valid alternative. The radios are dual-protocol, so the four-press sequence can pair a device to a Zigbee coordinator such as ZHA or Zigbee2MQTT. There, standard cluster binding with genOnOff and genLevelCtrl works, so a remote can control a bulb without the hub in the loop. The tradeoff is that you lose Matter multi-admin onboarding and Thread routing for that device, and you must commit to one stack per device.

On Matter, the Matter Server web UI on port 5580 shows what IKEA built. The node interview for the scroll wheel reports the following:

VendorName: IKEA of Sweden
ProductName: BILRESA scroll wheel
Matter version: 1.3.0
All device types: Ota Requestor / Power Source / Root Node / Generic Switch

The remotes are Generic Switch (0x000F) devices with no Binding cluster (0x001E). They cannot send unicast commands to a bulb, so each press arrives in Home Assistant as an event entity with types such as multi_press_1, long_press, and long_release. Something on the hub has to turn those events into light commands, and a Blueprint is the cleanest way to do that.

Step 3: Deploy the BILRESA Two-Way Switch Blueprint

Save this file to /path/to/homeassistant/blueprints/automation/ikea/bilresa_dual_button_matter.yaml. Button 1 turns the light on and a long press brightens it. Button 2 turns it off and a long press dims it. The actions strictly filter on multi_press_1 for clicks so Home Assistant does not fire on both initial_press and release.

blueprint:
  name: IKEA BILRESA Two-Way Switch (Matter) Light Controller
  description: >
    Bind an IKEA BILRESA dual-button Matter-over-Thread remote to a target light
    or light group with single-press On/Off and long-press brightness stepping.
  domain: automation
  input:
    button_1_event:
      name: Button 1 (Up / On) Event Entity
      description: The Matter event entity for Button 1 (for example, event.bilresa_dual_button_button_1)
      selector:
        entity:
          filter:
            - domain: event
              integration: matter
    button_2_event:
      name: Button 2 (Down / Off) Event Entity
      description: The Matter event entity for Button 2 (for example, event.bilresa_dual_button_button_2)
      selector:
        entity:
          filter:
            - domain: event
              integration: matter
    target_light:
      name: Target Light
      description: The KAJPLATS bulb or light group to control
      selector:
        target:
          entity:
            - domain: light
    dim_step_pct:
      name: Long-Press Brightness Step (%)
      description: Percentage to brighten or dim on long press
      default: 20
      selector:
        number:
          min: 5
          max: 50
          unit_of_measurement: "%"

mode: queued
max: 10

triggers:
  - trigger: state
    entity_id: !input button_1_event
    id: button_1
  - trigger: state
    entity_id: !input button_2_event
    id: button_2

conditions:
  - condition: template
    value_template: >
      {{ trigger.to_state.state not in ['unavailable', 'unknown'] }}

actions:
  - variables:
      event_type: "{{ trigger.to_state.attributes.event_type | default('') }}"
  - choose:
      - conditions:
          - condition: trigger
            id: button_1
          - condition: template
            value_template: "{{ event_type == 'multi_press_1' }}"
        sequence:
          - action: light.turn_on
            target: !input target_light
      - conditions:
          - condition: trigger
            id: button_1
          - condition: template
            value_template: "{{ event_type == 'long_press' }}"
        sequence:
          - action: light.turn_on
            target: !input target_light
            data:
              brightness_step_pct: !input dim_step_pct
      - conditions:
          - condition: trigger
            id: button_2
          - condition: template
            value_template: "{{ event_type == 'multi_press_1' }}"
        sequence:
          - action: light.turn_off
            target: !input target_light
      - conditions:
          - condition: trigger
            id: button_2
          - condition: template
            value_template: "{{ event_type == 'long_press' }}"
        sequence:
          - action: light.turn_on
            target: !input target_light
            data:
              brightness_step_pct: "{{ -1 * (dim_step_pct | int) }}"

Reload automations, then create an automation from the Blueprint. Pick the two event entities (for example event.bilresa_dual_button_button_1 and event.bilresa_dual_button_button_2) and your target light (for example light.kajplats_desk_lamp).

Step 4: Deploy the BILRESA Scroll Wheel Blueprint

The BILRESA scroll wheel exposes 9 distinct event entities across its 3 selectable hardware channels. On the physical hardware, the endpoints map as follows:

  • **Buttons 1, 4, and 7**: Spinning the wheel to the right (Clockwise / Up / Brighten).
  • **Buttons 2, 5, and 8**: Spinning the wheel to the left (Counter-Clockwise / Down / Dim).
  • **Buttons 3, 6, and 9**: Center push action (Toggle Light).

Channel 1 uses endpoints 1 to 3; Channel 2 uses endpoints 4 to 6; and Channel 3 uses endpoints 7 to 9. Home Assistant prefixes these event entities using the device name chosen during commissioning, such as event.bilresa_scroll_wheel_button_1 through event.bilresa_scroll_wheel_button_9.

When you first commission the scroll wheel, many of these entities are disabled by default in the Home Assistant entity registry. Enable them under Settings, then Devices and Services, then Matter, then your BILRESA device. Note that endpoints 4 through 9 display Unavailable or Unknown until each channel is actively clicked on the physical hardware for the first time.

Because the hardware gives you three independent channels, you can control three different rooms or lights from a single remote without building complex routing automations. To do that, instantiate this Blueprint three separate times: create one automation instance for Channel 1 (buttons 1 to 3) mapped to your primary desk lamp, a second instance for Channel 2 (buttons 4 to 6) mapped to a nightstand lamp, and a third instance for Channel 3 (buttons 7 to 9) mapped to your bedroom ceiling fixture. Switching channels on the remote shifts control across fixtures immediately.

Because IKEA implemented the wheel rotation under Matter's Generic Switch cluster rather than an analog dial, spinning the wheel emits button press events: turning 1 tick fires multi_press_1 ("Pressed once"), 2 ticks fires multi_press_2 ("Pressed twice"), and spinning faster fires multi_press_3 through multi_press_8 ("Pressed x times", where x is 3 to 8). The blueprint extracts the tick count directly from totalNumberOfPressesCounted (and event_type), scaling the brightness step proportionally so a gentle turn steps gently and a fast spin sweeps across the full brightness range smoothly.

Save the blueprint below to /path/to/homeassistant/blueprints/automation/ikea/bilresa_scroll_wheel_matter.yaml.

blueprint:
  name: IKEA BILRESA Scroll Wheel (Matter) Light & Dimmer Controller
  description: >
    Control lights with an IKEA BILRESA Scroll Wheel Matter remote.
    Supports single-press toggle on center push (Buttons 3, 6, or 9) and dynamic
    velocity-scaled brightness adjustments when spinning the wheel (Buttons 1/4/7
    for clockwise up, Buttons 2/5/8 for counter-clockwise down), scaling smoothly
    across pressed once (1 tick), pressed twice (2 ticks), and pressed x times
    (3 to 8 ticks).
  domain: automation
  input:
    press_event:
      name: Wheel Center Press Event Entity (Button 3, 6, or 9)
      description: The Matter event entity for center push (e.g., event.bilresa_scroll_wheel_button_3 for Ch 1, button_6 for Ch 2, button_9 for Ch 3)
      selector:
        entity:
          filter:
            - domain: event
              integration: matter
    scroll_up_event:
      name: Scroll Clockwise / Up Event Entity (Button 1, 4, or 7)
      description: The Matter event entity for clockwise scroll (e.g., event.bilresa_scroll_wheel_button_1 for Ch 1, button_4 for Ch 2, button_7 for Ch 3)
      selector:
        entity:
          filter:
            - domain: event
              integration: matter
    scroll_down_event:
      name: Scroll Counter-Clockwise / Down Event Entity (Button 2, 5, or 8)
      description: The Matter event entity for counter-clockwise scroll (e.g., event.bilresa_scroll_wheel_button_2 for Ch 1, button_5 for Ch 2, button_8 for Ch 3)
      selector:
        entity:
          filter:
            - domain: event
              integration: matter
    target_light:
      name: Target Light
      description: The KAJPLATS bulb or light group to toggle and dim
      selector:
        target:
          entity:
            - domain: light
    scroll_step_pct:
      name: Base Brightness Step Per Scroll Tick (%)
      description: Percentage to adjust brightness per tick. Scales dynamically for 1 tick (pressed once), 2 ticks (pressed twice), and 3-8 ticks (pressed x times).
      default: 5
      selector:
        number:
          min: 1
          max: 25
          unit_of_measurement: "%"

mode: restart

triggers:
  - trigger: state
    entity_id: !input press_event
    id: wheel_press
  - trigger: state
    entity_id: !input scroll_up_event
    id: wheel_up
  - trigger: state
    entity_id: !input scroll_down_event
    id: wheel_down

conditions:
  - condition: template
    value_template: >
      {{ trigger.to_state.state not in ['unavailable', 'unknown'] }}

actions:
  - variables:
      step: !input scroll_step_pct
      event_type: "{{ trigger.to_state.attributes.event_type | default('') }}"
      raw_count: "{{ trigger.to_state.attributes.totalNumberOfPressesCounted | default(0) | int }}"
      ticks: >-
        {% if raw_count in [1, 2, 3, 4, 5, 6, 7, 8] %}
          {{ raw_count }}
        {% elif event_type.startswith('multi_press_') %}
          {{ [([event_type.replace('multi_press_', '') | int(1), 1] | max), 8] | min }}
        {% else %}
          1
        {% endif %}
      step_val: "{{ [((step | int) * (ticks | int)), 100] | min }}"
  - choose:
      - conditions:
          - condition: trigger
            id: wheel_press
          - condition: template
            value_template: "{{ event_type in ['multi_press_1', 'initial_press', ''] }}"
        sequence:
          - action: light.toggle
            target: !input target_light
      - conditions:
          - condition: trigger
            id: wheel_up
        sequence:
          - action: light.turn_on
            target: !input target_light
            data:
              brightness_step_pct: "{{ step_val }}"
      - conditions:
          - condition: trigger
            id: wheel_down
        sequence:
          - action: light.turn_on
            target: !input target_light
            data:
              brightness_step_pct: "{{ -1 * (step_val | int) }}"

Early KAJPLATS firmware can add one to two seconds of delay because each press travels from the remote to the border router, to Home Assistant, and back to the bulb. Keep transitions short and leave the mode on restart for the wheel so fast scrolling does not pile up.

Hardware & Gear Used in This Guide

  • IKEA KAJPLATS Smart Bulb: Matter-over-Thread bulb (E26 1100lm globe or E12 WS globe 800lm) that joins the mesh with a QR code.
  • IKEA BILRESA Two-Way Switch: Dual-button remote that fires Up and Down events.
  • IKEA BILRESA Scroll Wheel: Clickable wheel with three channels and nine event entities.
  • IKEA GRILLPLATS Smart Outlet: Matter outlet that works with the same Blueprint pattern.
  • Thread Border Router: Bridges your Thread mesh to the LAN so Home Assistant can reach each device.

What You Can Do Next

  • Read the companion story on Frizzle Tech Blog for how the Touchlink surprise happened in a real house.
  • Point the Blueprints at a light group so one remote controls every KAJPLATS bulb in a room, and tune the brightness step to taste.
  • Set short transition times on the target lights to hide hub latency, then try the 3D-printed Skadis pegboard mount for a Tertial lamp that holds the bulb.

Later,
     SteveO