Z2M - IKEA Symfonisk Gen2 [E2123] Media Control v1.55

Hey there,

Thanks for this awesome blueprint !
I just want to know if it is possible to customize next/previous actions?
My Yamaha amplifier not handle the next/previous commands on the zone 2 when it is synchronized with the main zone sound.

Thanks a lot

Glad you like it :smiley:

The next/previous commands just call the standard media player integration for next track and previous track. Is it a bug in the Yamaha integration causing the issue?

Actually it is working great.
But some yamaha recievers have a zone 2 (or sometimes more). It appears as a separate entity on HA. So when I have set the zone 2 on the “Main Zone Sync” source, the “next” or “previous” sent to the zone 2 does nothing, because the main zone should be triggered as it is the brain of the party. I made a little workaround by editing your blueprint to let choose the main zone in the automation so it sends the command to the main zone when source is “Main Zone Sync” :

blueprint:
# Media control via IKEA Symfonisk Gen2 - Shawsky April 2023 v1.55
# Updated April 2024 - Add additional filtering to prevent triggering from other devices/false positives. Thanks kenno.
# Updated April 2024 - Add support for device rename in upcoming Z2M release & allow legacy action for Play/Pause
# Updated September 2023 - Further updates for group/non grouped behaviour / fix issue for volume hold for grouped/non grouped. Allow 100 volume steps.
# Updated August 2023 - Resolve a volume issue for media players with no group_memeber attribute
# Updated June 2023 - Resolve filtering issue where multiple devices are in use
# Updated May 2023 - Add group volume control

# Volume changes partially based on https://gist.github.com/erkr/a437ebcb98a2b5ba2deebabd02f5ffae Eric Kreuwels
# and https://gist.github.com/alexwmaustin/2c25cfa1a0ade1ab9fc1ef0940289672 Alex Austin

  name: Z2M - IKEA Symfonisk gen2 Auto (Sof version)
  description: 
    'Control the selected media player (and any joined to it) with an IKEA Symfonisk sound controller GEN2 via Zigbee2MQTT (Z2M)

    Supports single press on media buttons and single, double and long press for the "dot" buttons.'
  domain: automation
  input:
    remote:
      name: Remote
      description: The IKEA Symfonisk controller GEN2 to use
      selector:
          device:
            filter:
            - integration: mqtt
              manufacturer: IKEA
              model: SYMFONISK sound remote gen2 (E2123)
            - integration: mqtt
              manufacturer: IKEA
              model: SYMFONISK sound remote, gen 2 (E2123)
    base_topic:
      name: Zigbee2MQTT Base mqtt topic
      description: The base topic configured in Zigbee2MQTT. If you haven't changed this, leave the default here ("zigbee2mqtt")
      default: zigbee2mqtt
    media_player:
      name: Media Player
      description: The media player to control with this automation
      selector:
        entity:
          domain: media_player
          multiple: false
    media_player_main_zone:
      name: Main Zone synced to 
      description: The main entity behind the controlled zone
      selector:
        entity:
          domain: media_player
          multiple: false
    volume_steps:
      name: Volume number of steps
      description: Controls the volume scale. The default of 25 is the same scale as the Sonos app.
      default: 25
      selector:
        number:
          min: 5
          max: 100
          step: 5
          unit_of_measurement: "Num"
          mode: slider
    single_dot:
      name: Single Dot (Single)
      description: Action to run on single dot press
      default: []
      selector:
        action: {}
    single_dot_double_press:
      name: Single Dot (Double)
      description: Action to run on single dot double press
      default: []
      selector:
        action: {}
    single_dot_long_press:
      name: Single Dot (Long)
      description: Action to run on single dot long press
      default: []
      selector: 
        action: {}
    double_dot:
      name: Double Dot (Single)
      description: Action to run on double dot press
      default: []
      selector:
        action: {}
    double_dot_double_press:
      name: Double Dot (Double)
      description: Action to run on double dot double press
      default: []
      selector:
        action: {}
    double_dot_long_press:
      name: Double Dot (Long)
      description: Action to run on double dot long press
      default: []
      selector:
        action: {}
      
mode: restart
max_exceeded: silent

trigger_variables:
  base_topic: !input base_topic
  controller: !input remote

trigger:
  - platform: mqtt
    topic: "{{ base_topic }}/+/action"
condition:
  - condition: template
    value_template: "{{ trigger.topic == base_topic+'/'+device_attr(controller, 'name')+'/action' }} "  
action:
  - variables:
      controllertopic: "{{ base_topic }}/{{ device_attr(controller, 'name') }}/action"
      player: !input 'media_player'
      steps: !input volume_steps
      stepsize: '{{ 1.0 / steps }}'
  - choose:
    - conditions:
      - "{{ trigger.payload != ''}}"
      - "{{ trigger.topic == controllertopic }}"
      sequence:
        - choose:
          ## Commands

          # Play / Pause
          - conditions: "{{ trigger.payload == 'toggle' or trigger.payload == 'play_pause' }}"
            sequence:
            - service: media_player.media_play_pause
              entity_id: !input 'media_player'

          # Next Track
          - conditions: "{{ trigger.payload == 'track_next' }}"
            sequence:
              - if:
                  - condition: state
                    entity_id: !input 'media_player'
                    attribute: source
                    state: Main Zone Sync
                then:
                  - service: media_player.media_next_track
                    target:
                      entity_id: !input 'media_player_main_zone'
                    data: {}
                else:
                  - service: media_player.media_next_track
                    metadata: {}
                    data: {}
                    target:
                      entity_id: !input 'media_player'


              
          # Previous Track
          - conditions: "{{ trigger.payload == 'track_previous' }}"
            sequence:
              - if:
                  - condition: state
                    entity_id: !input 'media_player'
                    attribute: source
                    state: Main Zone Sync
                then:
                  - service: media_player.media_previous_track
                    data: {}
                    target:
                      entity_id: !input 'media_player_main_zone'
                else:
                  - service: media_player.media_previous_track
                    data: {}
                    target:
                      entity_id: !input 'media_player'

          
          ## Volume for media players supporting groups

          # Volume Up Press
          - conditions: "{{ trigger.payload == 'volume_up' and state_attr(player, 'group_members') != none and state_attr(player, 'group_members') != [] }}"
            sequence:
              - repeat:
                  for_each: "{{ state_attr(player, 'group_members') }}"
                  sequence:
                  - service: media_player.volume_set
                    target:
                      entity_id: "{{ repeat.item }}"
                    data:
                      volume_level: >-
                        {% set volume = state_attr(repeat.item, "volume_level") + stepsize %}
                        {{ 1.0 if volume > 1.0 else volume }}

          # Volume Down Press
          - conditions: "{{ trigger.payload == 'volume_down' and state_attr(player, 'group_members') != none and state_attr(player, 'group_members') != [] }}"
            sequence:
              - repeat:
                  for_each: "{{ state_attr(player, 'group_members') }}"
                  sequence:
                  - service: media_player.volume_set
                    target:
                      entity_id: "{{ repeat.item }}"
                    data:
                      volume_level: >-
                        {% set volume = state_attr(repeat.item, "volume_level") - stepsize %}
                        {{ 0.0 if volume < 0.0 else volume }}

          # Volume Up Hold
          - conditions: "{{ trigger.payload == 'volume_up_hold' and state_attr(player, 'group_members') != none and state_attr(player, 'group_members') != [] }}"
            sequence:
              - repeat:
                  for_each: "{{ state_attr(player, 'group_members') }}"
                  sequence:
                  - service: media_player.volume_up
                    target:
                      entity_id: "{{ repeat.item }}"

          # Volume Down Hold
          - conditions: "{{ trigger.payload == 'volume_down_hold' and state_attr(player, 'group_members') != none and state_attr(player, 'group_members') != [] }}"
            sequence:
              - repeat:
                  for_each: "{{ state_attr(player, 'group_members') }}"
                  sequence:
                  - service: media_player.volume_down
                    target:
                      entity_id: "{{ repeat.item }}"

          ## Volume for media players not supporting groups

          # Volume Up
          - conditions: "{{ trigger.payload == 'volume_up' and (state_attr(player, 'group_members') == none or state_attr(player, 'group_members') == []) }}"
            sequence:
              - service: media_player.volume_set
                target:
                  entity_id: "{{ player }}"
                data:
                  volume_level: >-
                    {% set volume = state_attr(player, "volume_level") + stepsize %}
                    {{ 1.0 if volume > 1.0 else volume }}
           
          # Volume Down Press
          - conditions: "{{ trigger.payload == 'volume_down' and (state_attr(player, 'group_members') == none or state_attr(player, 'group_members') == []) }}"
            sequence:
              - service: media_player.volume_set
                target:
                  entity_id: "{{ player }}"
                data:
                    volume_level: >-
                      {% set volume = state_attr(player, "volume_level") - stepsize %}
                      {{ 0.0 if volume < 0.0 else volume }}
          
          # Volume Up Hold
          - conditions: "{{ trigger.payload == 'volume_up_hold' and (state_attr(player, 'group_members') == none or state_attr(player, 'group_members') == []) }}"
            sequence:
              - service: media_player.volume_up
                target:
                  entity_id: "{{ player }}"
          
          # Volume Down Hold
          - conditions: "{{ trigger.payload == 'volume_down_hold' and (state_attr(player, 'group_members') == none or state_attr(player, 'group_members') == []) }}"
            sequence:
              - service: media_player.volume_down
                target:
                  entity_id: "{{ player }}"

          ## Actions

          # Single Dot Press
          - conditions: "{{ trigger.payload == 'dots_1_short_release' }}"
            sequence: !input single_dot
          # Single Dot Double Press
          - conditions: "{{ trigger.payload == 'dots_1_double_press' }}"
            sequence: !input single_dot_double_press
          # Single Dot Long Press
          - conditions: "{{ trigger.payload == 'dots_1_long_press' }}"
            sequence: !input single_dot_long_press
          # Double Dot Press
          - conditions: "{{ trigger.payload == 'dots_2_short_release' }}"
            sequence: !input double_dot
          # Double Dot Double Press
          - conditions: "{{ trigger.payload == 'dots_2_double_press' }}"
            sequence: !input double_dot_double_press
          # Double Dot Long Press
          - conditions: "{{ trigger.payload == 'dots_2_long_press' }}"
            sequence: !input double_dot_long_press
1 Like