ZHA - IKEA Symfonisk sound controller for media (the spinny one)

The events arenā€™t listed in the logbook. You can see them if you subscribe to zha_events in the developer page.

No, they work straight out of the box.

1 Like

Thanks everyone, a lot of really nice code above! That variables setting action is amazing, you have no idea the tedious workarounds Iā€™ve used so far to achieve a similar function.

In case it helps anyone, below is how Iā€™ve adapted and implemented the above in my ground floor with one Google home, one Android TV, and a Sonos home theatre system connected to the TV. I had issues with a ton of repeat events coming in from the symfonisk volume controller, but was able to solve that (at least the automation still executes in a useful manner) by introducing a delay at the end of the parent action sequence and setting the automation mode to ā€œrestartā€. Itā€™s working pretty smoothly and reliably now, but I have thoughts to implement a kind of panic off action (on double or triple press) to be able to contravene a potential runaway volume increase.

There are some quirks with my media player arrangement that result in some extra logic. Kitchen_display is a Google Home smart speaker/display that is only ever temporarily active when either the home theatre or TV + home theatre are active (i.e. when I tell Google to dim the lights while watching TV). This means when it goes idle I typically want the active media player to revert to either the home theatre or the TV, and that is why my ā€œactive media playerā€ automation doesnā€™t trigger on idle state of either the TV or home theatre. The other thing is that the TV audio always comes via the home theatre. So whenever the TV is in a ā€œplayingā€ state, the home theatre is too. This means that when the TV is active, volume changes must be done via the home theatre, and play/pause must be done via the TV. Another common use case is telling the kitchen_display to play music on the home theatre. In this case the kitchen_display starts off as active, hands off to the home theatre when it is idle, and the TV doesnā€™t come into the picture at all.

This code and functionality is getting really fun now, and using the single volume dial to control all these things is still simple and intuitive. Iā€™m wondering how many other smart things I can start to do with this single button/dial interface!

Hereā€™s the automation adapted from the above that controls three different media players.

alias: 'Symfonisk: Sound controller actions'
description: ''
trigger:
  - platform: event
    event_type: zha_event
    event_data:
      device_id: SYMFONISK_DEV_ID_HERE
condition: []
action:
  - variables:
      command: '{{ trigger.event.data.command }}'
      cluster_id: '{{ trigger.event.data.cluster_id }}'
      endpoint_id: '{{ trigger.event.data.endpoint_id }}'
      args: '{{ trigger.event.data.args }}'
      active_player: '{{ states(''input_text.active_media_player'') }}'
      volume_step: 0.04
      delay_time: 0.4
  - choose:
      - conditions:
          - condition: template
            value_template: '{{ command == ''toggle'' }}'
          - condition: template
            value_template: '{{ cluster_id == 6 }}'
          - condition: template
            value_template: '{{ endpoint_id == 1 }}'
        sequence:
          - choose:
              - conditions:
                  - condition: template
                    value_template: '{{ active_player == ''media_player.home_theatre'' }}'
                sequence:
                  - service: media_player.media_play_pause
                    target:
                      entity_id:
                        - media_player.home_theatre
              - conditions:
                  - condition: template
                    value_template: '{{ active_player == ''media_player.tv'' }}'
                sequence:
                  - service: media_player.media_play_pause
                    target:
                      entity_id:
                        - media_player.tv
            default:
              - service: media_player.media_play_pause
                target:
                  entity_id: media_player.kitchen_display
      - conditions:
          - condition: template
            value_template: '{{ command == ''step'' }}'
          - condition: template
            value_template: '{{ cluster_id == 8 }}'
          - condition: template
            value_template: '{{ endpoint_id == 1 }}'
          - condition: template
            value_template: '{{ args == [0, 1, 0] }}'
        sequence:
          - service: input_boolean.turn_on
            target:
              entity_id: input_boolean.report
      - conditions:
          - condition: template
            value_template: '{{ command == ''step'' }}'
          - condition: template
            value_template: '{{ cluster_id == 8 }}'
          - condition: template
            value_template: '{{ endpoint_id == 1 }}'
          - condition: template
            value_template: '{{ args == [1, 1, 0] }}'
        sequence:
          - service: light.turn_off
            target:
              entity_id: light.entire_house
      - conditions:
          - condition: template
            value_template: '{{ command == ''move'' }}'
          - condition: template
            value_template: '{{ cluster_id == 8 }}'
          - condition: template
            value_template: '{{ endpoint_id == 1 }}'
          - condition: template
            value_template: '{{ args == [0, 195] }}'
        sequence:
          repeat:
            while:
              - condition: template
                value_template: '{{ repeat.index < 20 }}'
            sequence:
              - choose:
                  - conditions:
                      - condition: template
                        value_template: >-
                          {{ active_player == 'media_player.home_theatre' or
                          active_player == 'media_player.tv' }}
                    sequence:
                      - service: media_player.volume_set
                        entity_id: media_player.home_theatre
                        data_template:
                          volume_level: >-
                            {{ state_attr('media_player.home_theatre' ,
                            'volume_level') | float + volume_step }}
                default:
                  - service: media_player.volume_set
                    entity_id: media_player.kitchen_display
                    data_template:
                      volume_level: >-
                        {{ state_attr('media_player.kitchen_display' ,
                        'volume_level') | float + volume_step }}
      - conditions:
          - condition: template
            value_template: '{{ command == ''move'' }}'
          - condition: template
            value_template: '{{ cluster_id == 8 }}'
          - condition: template
            value_template: '{{ endpoint_id == 1 }}'
          - condition: template
            value_template: '{{ args == [1, 195] }}'
        sequence:
          repeat:
            while:
              - condition: template
                value_template: '{{ repeat.index < 20 }}'
            sequence:
              - choose:
                  - conditions:
                      - condition: template
                        value_template: >-
                          {{ active_player == 'media_player.home_theatre' or
                          active_player == 'media_player.tv' }}
                    sequence:
                      - service: media_player.volume_set
                        entity_id: media_player.home_theatre
                        data_template:
                          volume_level: >-
                            {{ state_attr('media_player.home_theatre' ,
                            'volume_level') | float - volume_step }}
                default:
                  - service: media_player.volume_set
                    entity_id: media_player.kitchen_display
                    data_template:
                      volume_level: >-
                        {{ state_attr('media_player.kitchen_display' ,
                        'volume_level') | float - volume_step }}
  - delay: delay_time
mode: restart

And here is the automation that decides which is the active media player:

alias: 'Symfonisk: Choose active media player'
description: ''
trigger:
  - platform: device
    device_id: DEV_ID_HERE
    domain: media_player
    entity_id: media_player.kitchen_display
    type: playing
  - platform: device
    device_id: DEV_ID_HERE
    domain: media_player
    entity_id: media_player.kitchen_display
    type: idle
  - platform: device
    device_id: DEV_ID_HERE
    domain: media_player
    entity_id: media_player.home_theatre
    type: playing
  - platform: device
    device_id: DEV_ID_HERE
    domain: media_player
    entity_id: media_player.tv
    type: playing
condition: []
action:
  - service: input_text.set_value
    target:
      entity_id: input_text.active_media_player
    data:
      value: >-
        {% set player = '' %} {% if is_state('media_player.home_theatre',
        'playing') and not is_state('media_player.kitchen_display', 'playing')
        %}   {% if is_state('media_player.home_theatre', 'playing') and
        is_state('media_player.tv', 'playing') %}     {% set player =
        'media_player.tv' %}   {% else %}     {% set player =
        'media_player.home_theatre' %}   {% endif %} {% elif not
        is_state('media_player.home_theatre', 'playing') and
        is_state('media_player.kitchen_display', 'playing') %}   {% set player =
        'media_player.kitchen_display' %} {% elif
        states.media_player.home_theatre.last_updated >
        states.media_player.kitchen_display.last_updated %}   {% if
        is_state('media_player.home_theatre', 'playing') and
        is_state('media_player.tv', 'playing') %}     {% set player =
        'media_player.tv' %}   {% else %}     {% set player =
        'media_player.home_theatre' %}   {% endif %} {% else %}   {% set player
        = 'media_player.kitchen_display' %} {% endif %} {{player}}
mode: restart

Hi, Iā€™m using this version of the spinny remote blueprint because the volume change felt too slow with the original one, and I have double-click set to call ā€œmedia_player.media_next_trackā€ to skip whatever is currently playing.

However, it always skips 2 tracks with this blueprint. It works fine with the original one (with the slow volume change). I tried fiddling with the code but I donā€™t really know what Iā€™m doing, any ideas?

EDIT:

I kinda got it working, I noticed one of the changes was ā€œmodeā€ from single to repeat. I changed that back to single, and I reduced the ā€œrepeat.indexā€ to 5, and it works ok. You canā€™t continuously turn to change the volume (suspect thatā€™s what the ā€œrepeatā€ bit does) but Iā€™m happy enough.

Yeah, the ā€œrepeatā€ was so you can continuously spin it to change volume. But it seems that the handling is somewhat dodgy (I find sometimes the volume keeps going up even when Iā€™ve only spun it a little bit, for instance). I think this is HA being overrun with updates from ZHA or something like that.

I donā€™t use mine enough to feel the need to fix itā€¦ :wink:

Any suggestions on debugging. I have two of these devices connected via ZHA - but the automation (this + a media hook) Never runsā€¦

I suspect its a zha issue

How about using a different Blueprint? The one I use works great.

Had a lot of issues with ZHA and Ikea devices. Ended up having to re-pair them every few days, and the batteries drained within a week or so (I have 2x Symfonisk knobs and 1x on/off switch). I switched over to ZigBee2MQTT and everything is working much more reliably now with all the same hardware, and the Ikea device batteries are still at 100% after a week despite frequent use. Not sure what the issue was in ZHA, but perhaps this helps someone else with the same problem.

1 Like

Hi, thanks for the code it works well for the quicker volume control. I am having an issue though where the battery has drained over a 2 day period. I am seeing hourly a zha_event trigger that produces a No Action taken. I suspect this is likely the cause of the battery drain. Thoughts?

Hey guys,

I was thinking of picking one of these up. Does anyone have it controlling Spotify volume though Alexa?

Does it work ok?

Thanks

Hi.
Thanks for this blueprint, all funktions are fine and working, but i get this error message in the log.

Can anyone help me finding the error?

Logger: homeassistant.components.automation
Source: components/automation/init.py:640
Integration: Automatisering (documentation, issues)
First occurred: 08.11.05 (1 occurrences)
Last logged: 08.11.05

Blueprint Controller - IKEA E1744 SYMFONISK Rotary Remote generated invalid automation with inputs OrderedDict([(ā€˜integrationā€™, ā€˜ZHAā€™), (ā€˜controller_deviceā€™, ā€˜490c4d4ed891a9597fdec15ddf243897ā€™), (ā€˜helper_last_controller_eventā€™, ā€˜input_text.ikea_sound_controleā€™), (ā€˜action_rotate_leftā€™, [OrderedDict([(ā€˜device_idā€™, ā€˜334729b3c4920d8a4fdb3bfc095976c0ā€™), (ā€˜domainā€™, ā€˜numberā€™), (ā€˜entity_idā€™, ā€˜number.kokken_trebleā€™), (ā€˜typeā€™, ā€˜set_valueā€™)])])]): required key not provided @ data[ā€˜valueā€™]. Got None

Continuously spinning the wheel only results in on incremental change in volume. Is there any way to change this, so that continuously spinning the wheel will result in a continuous increase of the volume?

Thanks @sparkydave ! Somewhat more complicated to set up, but it works well for me.

I would still be interested if the Symfonisk Sound Controller for media blueprint can be improved so that one can continuously increase/decrease the volume.

Hi, If I have deCONZ, can I use this one? do I need a different version/code. I tried the import, but that doesnt find my remote

You would need to modify the blueprint to the deconz integration and check the rest of the code based on what you see in your deconz_events

Hi Thomas

I have used your blueprint with a lot of pleasure over the last year, but sadly core-2022.4.x partly broke this blueprint. i.e. button presses are not recognized anymore. Something changed in ZHA adding some arguments to the events. The args variable now evaluates to something like:
args: '[<StepMode.Up: 0>, 1, 0, <bitmap8.0: 0>, <bitmap8.0: 0>]'.
in stead of:
args: '[0, 1, 0]'
This issue is related: ZHA ikea tradfri button up/down buttons service calls are not recognized anymore Ā· Issue #69375 Ā· home-assistant/core Ā· GitHub

It would be great to have an official fix for that. I temporary replaced the four args checks by a param attribute check (step_mode or move_mode) in the conditions part. That fixed it for me:

  - conditions:
    - '{{ command == ''step'' }}'
    - '{{ cluster_id == 8 }}'
    - '{{ endpoint_id == 1 }}'
    - '{{ trigger.event.data.params.step_mode == 0 }}'
#    - '{{ args == [0, 1, 0] }}'
    sequence: !input 'double_press'
  - conditions:
    - '{{ command == ''step'' }}'
    - '{{ cluster_id == 8 }}'
    - '{{ endpoint_id == 1 }}'
    - '{{ trigger.event.data.params.step_mode == 1 }}'
#    - '{{ args == [1, 1, 0] }}'
    sequence: !input 'triple_press'
  - conditions:
    - '{{ command == ''move'' }}'
    - '{{ cluster_id == 8 }}'
    - '{{ endpoint_id == 1 }}'
    - '{{ trigger.event.data.params.move_mode == 0}}'
#    - '{{ args == [0, 195] }}'
    sequence:
    - service: media_player.volume_up
      target: !input 'media_player'
    - delay: 1
  - conditions:
    - '{{ command == ''move'' }}'
    - '{{ cluster_id == 8 }}'
    - '{{ endpoint_id == 1 }}'
    - '{{ trigger.event.data.params.move_mode == 1 }}'
#    - '{{ args == [1, 195] }}'

regards
Eric

4 Likes

I canā€™t find my controller to test it at the minute, but it sounds like you have it working for now.

Yep, works perfect again

Will @erkr 's edit be included as an update to the ā€˜officialā€™ Blueprint?

You do realise that blueprints are created by community members, so not official?

Anyone is free to create and modify blueprints as they need, and they are shared to benefit the rest of the community.