ZHA - IKEA STYRBAR E2313 - Media Player Control (White 4-button remote)

ZHA - IKEA STYRBAR E2313 - Media Player Control (White 4-button remote)
Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.
Hey everyone! :wave:
I’ve been working on a blueprint for controlling a media player with the IKEA STYRBAR E2313 (the white 4-button remote) via ZHA, and after some debugging I’m happy to share it here.

:joystick: Button Layout
Button Short press Long press
â–² Top Play / Pause Mute toggle
▼ Bottom Stop (empty — customize freely)
:arrow_backward: Left Previous track Volume down (repeating)
:arrow_forward: Right Next track Volume up (repeating)

:wrench: Features
Play/Pause, Stop, Next/Previous track on short press
Smooth volume control on long press — holds and repeats until you release the button
Mute toggle on long hold of the top button
Configurable volume step and repeat interval
Works with any media_player entity (Sonos, Chromecast, Music Assistant, VLC, etc.)

:bug: Quirks handled
This remote has two known ZHA quirks that required special handling:

  1. The on-event quirk on left/right hold
    When you hold the :arrow_forward: or :arrow_backward: button, the remote fires this sequence of events:
press → on → hold → release

The extra on event would incorrectly trigger Play/Pause mid-hold. This blueprint uses wait_for_trigger with a 400ms window to detect whether a hold follows the on event — if so, Play/Pause is skipped.
2. Asymmetric hold behaviour on left vs. right
The :arrow_backward: left button repeats hold events natively while held down. The :arrow_forward: right button only sends a single hold event followed by release. Both volume actions now use the same loop pattern: adjust volume → wait for release or timeout → repeat if no release received.

:gear: Configuration
Setting Default Description
Remote — Your IKEA STYRBAR device in ZHA
Media player — The media player entity to control
Volume step 0.05 How much volume changes per tick (0.01–0.20)
Repeat interval 300ms Speed of volume repeat while holding (100–1000ms)

:inbox_tray: Blueprint YAML
Paste the YAML below into a new file in /config/blueprints/automation/ and reload blueprints, or use the import button.

blueprint:
  name: IKEA STYRBAR E2313 - Media Player (ZHA)
  description: >
    Control a media player with the IKEA STYRBAR E2313 (white 4-button remote) via ZHA.

    Button layout:
      ▲ Short press  → Play / Pause
      ▲ Long press   → Mute toggle
      ▼ Short press  → Stop
      ▼ Long press   → (empty / customize freely)
      ◀ Short press  → Previous track
      ◀ Long press   → Volume down (repeating)
      ▶ Short press  → Next track
      ▶ Long press   → Volume up (repeating)

    Also compatible with E2001 (silver variant).

  domain: automation
  input:
    remote:
      name: STYRBAR Remote
      description: Select your IKEA STYRBAR device from ZHA.
      selector:
        device:
          integration: zha
          manufacturer: IKEA of Sweden
          model: Remote Control N2

    media_player:
      name: Media Player
      description: The media player entity to control.
      selector:
        entity:
          domain: media_player

    volume_step:
      name: Volume Step
      description: How much volume changes per tick (0.01–0.20).
      default: 0.05
      selector:
        number:
          min: 0.01
          max: 0.20
          step: 0.01
          mode: slider

    volume_repeat_ms:
      name: Repeat Interval (ms)
      description: How fast volume changes while the button is held.
      default: 300
      selector:
        number:
          min: 100
          max: 1000
          step: 50
          unit_of_measurement: ms
          mode: slider

mode: restart
max_exceeded: silent

variables:
  player: !input media_player
  vol_step: !input volume_step
  vol_repeat_ms: !input volume_repeat_ms

trigger:
  - platform: event
    event_type: zha_event
    event_data:
      device_id: !input remote

action:
  - variables:
      command: "{{ trigger.event.data.command }}"
      args: "{{ trigger.event.data.args }}"

  - choose:

      # ▲ Short press → Play / Pause
      # Waits briefly to detect if a hold follows (left/right quirk guard)
      - conditions:
          - condition: template
            value_template: "{{ command == 'on' }}"
        sequence:
          - wait_for_trigger:
              - platform: event
                event_type: zha_event
                event_data:
                  device_id: !input remote
                  command: hold
            timeout:
              milliseconds: 400
            continue_on_timeout: true
          - condition: template
            value_template: "{{ wait.trigger is none }}"
          - action: media_player.media_play_pause
            target:
              entity_id: !input media_player

      # ▲ Long press → Mute toggle
      - conditions:
          - condition: template
            value_template: "{{ command == 'move_with_on_off' }}"
        sequence:
          - action: media_player.volume_mute
            target:
              entity_id: !input media_player
            data:
              is_volume_muted: >
                {{ not state_attr(player, 'is_volume_muted') }}

      # ▼ Short press → Stop
      - conditions:
          - condition: template
            value_template: "{{ command == 'off' }}"
        sequence:
          - action: media_player.media_stop
            target:
              entity_id: !input media_player

      # ▼ Long press → (no action)
      - conditions:
          - condition: template
            value_template: "{{ command == 'move' }}"
        sequence: []

      # ◀ Short press → Previous track
      - conditions:
          - condition: template
            value_template: "{{ command == 'press' and args == [257, 13, 0] }}"
        sequence:
          - action: media_player.media_previous_track
            target:
              entity_id: !input media_player

      # ◀ Long press → Volume down (loop until release)
      - conditions:
          - condition: template
            value_template: "{{ command == 'hold' and args == [3329, 0] }}"
        sequence:
          - repeat:
              while:
                - condition: template
                  value_template: "{{ true }}"
              sequence:
                - action: media_player.volume_set
                  target:
                    entity_id: !input media_player
                  data:
                    volume_level: >
                      {{ [state_attr(player, 'volume_level') - vol_step, 0] | max }}
                - wait_for_trigger:
                    - platform: event
                      event_type: zha_event
                      event_data:
                        device_id: !input remote
                        command: release
                  timeout:
                    milliseconds: !input volume_repeat_ms
                  continue_on_timeout: true
                - condition: template
                  value_template: "{{ wait.trigger is none }}"

      # ▶ Short press → Next track
      - conditions:
          - condition: template
            value_template: "{{ command == 'press' and args == [256, 13, 0] }}"
        sequence:
          - action: media_player.media_next_track
            target:
              entity_id: !input media_player

      # ▶ Long press → Volume up (loop until release)
      - conditions:
          - condition: template
            value_template: "{{ command == 'hold' and args == [3328, 0] }}"
        sequence:
          - repeat:
              while:
                - condition: template
                  value_template: "{{ true }}"
              sequence:
                - action: media_player.volume_set
                  target:
                    entity_id: !input media_player
                  data:
                    volume_level: >
                      {{ [state_attr(player, 'volume_level') + vol_step, 1] | min }}
                - wait_for_trigger:
                    - platform: event
                      event_type: zha_event
                      event_data:
                        device_id: !input remote
                        command: release
                  timeout:
                    milliseconds: !input volume_repeat_ms
                  continue_on_timeout: true
                - condition: template
                  value_template: "{{ wait.trigger is none }}"

Tested on HA 2025.x with a STYRBAR E2313 (firmware 2.4.17) and Music Assistant. Let me know if you run into any issues or have suggestions! :slightly_smiling_face:

Hello Jesper Mann Stjernholm,

Thanks for contributing to the community with a new Blueprint.
I have a suggestion for you. Many people who are not familiar with directory structures will have problems installing this without the Home Assistant MY tools.
Adding a MY link for this Blueprint to your top post would help them a lot.
Here is the link to make that.
Create a link – My Home Assistant

I believe this IKEA remote is more intuitive as a media remote.