On each Run: Pick Random Element from List, Remove from List, if list empty, reset list to original contents

What I currently have is a script that, when called, picks a playlist randomly from a list of playlists (called by name) and plays this playlist on our Sonos.

What I’d like is to extend this so that it cycles through the list of playlists and resets.
So it selects a random playlist from the list of playlists, removes it from that list so that next time it can’t pick it anymore, until the list is empty and then it resets the list to the original contents minus the just selected playlist.

My code thus far is as follows:

In configuration.yaml

input_text:
  playlist_chosen_random_source:
    name: Playlist Chosen Random Source
    initial: Haven't picked a playlist

In scripts.yaml:

random_music_script:
  sequence:
  - service: input_text.set_value
    data_template:
      entity_id: input_text.playlist_chosen_random_source
      value: '{{ ["Dinner Playlist", "Jazz & Classic Playlist", "Instrumental Playlist",
        "Easy Playlist", "Electronic Playlist", "Rock Playlist"] | random}}

        '
  - service: media_player.select_source
    data:
      entity_id: media_player.dining
    data_template:
      source: '{{ states("input_text.playlist_chosen_random_source") }}

        '
  - service: media_player.turn_on
    data:
      entity_id: media_player.dining
  - service: script.what_playlist_is_playing_script

How would I best extend this so that it does the additional steps?

1 Like

What I would do is use an input_select with all of the options for the source listed instead of an input_text.

then you could use the ‘options’ attribute in the random template which also will return a list:

{{state_attr('input_select.sources', 'options') }}

then test to see which option is selected and create a new options list without the last option used in the list. eventually you will get to the point that you have removed all options and then you can test the list of options again for being 0 and reload the input selects to reset the input select to the original set of options.

{{state_attr('input_select.sources', 'options') | length == 0 }}

I know it sounds kind of confusing. but start here:

and if you need additional help I (or some other smarter person than me :wink:) could try to cobble something together. But since you seem ok with using templates give it a try first to see what you can come up with.

I’ve been trying a bit but no luck so far - so any additional help would be welcome.
Otherwise, I will tinker further :wink:

Thanks!

what have you got so far?

So far I have the following:

In Configuration.yaml:

input_select:
  playlist_options_full:
    options:
      - Dinner Playlist
      - Jazz & Classic Playlist
      - Instrumental Playlist
      - Easy Playlist
      - Electronic Playlist
      - Rock Playlist
  playlist_options_filtered:
    options:
      - Dinner Playlist
      - Jazz & Classic Playlist
      - Instrumental Playlist
      - Easy Playlist
      - Electronic Playlist
      - Rock Playlist

Where I was thinking to use the playlist_options_full to reset the filtered version

Now I’m trying to generate the list as follows:

random_music_script:
  sequence:
  - service: input_text.set_value
    data_template:
      entity_id: input_text.playlist_chosen_random_source
      value: '{{ {{state_attr('input_select.playlist_options_filtered', 'options') }} | random}}'
  - service: media_player.select_source
    data:
      entity_id: media_player.dining
    data_template:
      source: '{{ states("input_text.playlist_chosen_random_source") }}

But this already throws a lot of errors :-/
After this I was thinking of doing the check for 1, filter or reset through set_options and the playlist_options_filtered. But again, already stuck.

your script syntax was way off…

try this:

random_music_script:
    sequence:
    - service: input_text.set_value
      data:
        entity_id: input_text.playlist_chosen_random_source
        value: "{{ state_attr('input_select.playlist_options_filtered', 'options') | random }}"
    - service: media_player.select_source
      data:
        entity_id: media_player.dining
        source: "{{ states('input_text.playlist_chosen_random_source') }}"

Also, as an FYI, unless you click the reply button in my post opr you tag me by using @ then my username I don’t see your reply to me unless I check my unread topic list. Which I do less often than if I get a notification.

Thanks! @finity

Some progress but now I’m working on the filtering of the playlist_options_filtered.

So I made an automation that triggers whenever the input_text.playlist_chosen_random_source is changed.
I first check if the playlist_options_filtered (an input_select) is empty, if so, I set its options to playlist_options_full (an input_select)
Otherwise, I’d like to set its options to ( playlist_options_filtered - input_text.playlist_chosen_random_source) but this step is the thing I’m unsure about.
Any chance you could help? This is jinja right? I’ll look into templating a bit more.

What I have so far:

- id: '1611062838637'
  alias: automation_filter_playlist
  description: ''
  trigger:
  - platform: state
    entity_id: input_text.playlist_chosen_random_source
  condition: []
  action:
  - choose:
    - conditions:
      - condition: template
        value_template: '{{state_attr(''input_select.playlist_options_filtered'', ''options'') | length
          == 0 }}'
      sequence:
      - service: input_select.set_options
        data:
          options: state_attr('input_select.playlist_options_full')
        entity_id: input_select.playlist_options_filtered
    - conditions:
      - condition: template
        value_template: '{{state_attr(''input_select.playlist_options_filtered'', ''options'') | length
          > 0 }}'
      sequence:
      - service: input_select.set_options
        data:
          options:
        entity_id: input_select.playlist_options_filtered
    default: []
  mode: single

Solved it with much help from Discord as well. Thank you again!

Solution:

- id: "1611062838637"
  alias: automation_filter_playlist
  description: ""
  trigger:
    - platform: state
      entity_id: input_text.playlist_chosen_random_source
  condition: []
  action:
    - choose:
        - conditions:
            - condition: template
              value_template:
                "{{state_attr('input_select.playlist_options_filtered', 'options') | length
                == 1 }}"
          sequence:
            - service: input_select.set_options
              data:
                options: ({{ state_attr('input_select.playlist_options_full', 'options') }})
              entity_id: input_select.playlist_options_filtered
        - conditions:
            - condition: template
              value_template:
                "{{state_attr('input_select.playlist_options_filtered', 'options') | length
                > 1 }}"
          sequence:
            - service: input_select.set_options
              data:
                options: ({% set ns = namespace(list=[]) %}
                  {% for option in state_attr("input_select.playlist_options_filtered", "options") if option != states("input_text.playlist_chosen_random_source") %}
                  {% set ns.list = ns.list+[option] %}
                  {%endfor%}
                  {{ns.list}})
              entity_id: input_select.playlist_options_filtered
      default: []
  mode: single
2 Likes