Dynamic list of buttons for a data list - list spotify albums by search in dashboard

Hi,
i try to find a possibility to show a list of buttons in my dashboard. The list will be dynamic - the result of a search.

Target:

I want to provide my kids a list of spotify albums (based on a search) in the dashboard.
It should be possible to select one of the albums to play the album on a speaker.

Pieces of the puzzle

  1. With SpotifyPlus it is possible to search for albums.
action: spotifyplus.search_albums
data:
  entity_id: media_player.spotifyplus_configuration
  criteria: beatles
  limit_total: 3

The result is a list of albums:
In the list the images, IDs, URLs, Names … are in a list of items.

user_profile:
  country: <country code>
  display_name: <name>
  email: <mail>
  id: <id>
  product: premium
  type: user
  uri: spotify:user:<id>
result:
  date_last_refreshed: <timestamp>
  href: null
  limit: 3
  next: null
  offset: 0
  previous: null
  total: 902
  items:
    - album_type: album
      artists:
        - external_urls:
            spotify: https://open.spotify.com/artist/<id>
          href: https://api.spotify.com/v1/artists/<id>
          id: <albumID>
          name: The Beatles
          type: artist
          uri: spotify:artist:<id>
      available_markets:
        - AR
        - DE
        - EC
      external_urls:
        spotify: https://open.spotify.com/album/<id>
      href: https://api.spotify.com/v1/albums/<id>
      id: <id>
      image_url: https://i.scdn.co/image/<id>
      images:
        - url: https://i.scdn.co/image/<id>
          height: 640
          width: 640
        - url: https://i.scdn.co/image/<id>
          height: 300
          width: 300
        - url: https://i.scdn.co/image/<id>
          height: 64
          width: 64
      name: The Beatles (Remastered)
      release_date: "1968-11-22"
      release_date_precision: day
      restrictions: {}
      total_tracks: 30
      type: album
      uri: spotify:album:<id>
    - album_type: album
      artists:
        - external_urls:
            spotify: https://open.spotify.com/artist/<id>
          href: https://api.spotify.com/v1/artists/<id>
          id: <albumID>
          name: The Beatles
          type: artist
          uri: spotify:artist:<id>
      available_markets:
        - AR
        - DE
        - UK
      external_urls:
        spotify: https://open.spotify.com/album/<id>
      href: https://api.spotify.com/v1/albums/<id>
      id: <id>
      image_url: https://i.scdn.co/image/<id>
      images:
        - url: https://i.scdn.co/image/<id>
          height: 640
          width: 640
        - url: https://i.scdn.co/image/<id>
          height: 300
          width: 300
        - url: https://i.scdn.co/image/<id>
          height: 64
          width: 64
      name: The Beatles
      release_date: "1969-09-26"
      release_date_precision: day
      restrictions: {}
      total_tracks: 30
      type: album
      uri: spotify:album:<id>
<cut>
  1. There is also a possibility to play a album by the href with SpotifyPlus.
service: media_player.play_media
data:
  entity_id: media_player.spotifyplus_john_s
  media_content_type: album
  media_content_id: spotify:album:0LhYYU14RU6IPQ9vVMu3Yk
  1. There is a custom:auto-entities and custom:layout-card HACS Integrations which is used in this post to list radio stations based on a (dynamic) file list in a sensor.

Problem:

I did not find a possibility to load the search result of the action spotifyplus.search_albums into the list {%- for item in <add search result here> -%} of the post.

type: custom:auto-entities
card:
  type: custom:layout-card
  layout_type: custom:grid-layout
  layout:
    grid-template-columns: auto auto auto auto auto auto
    grid-template-rows: auto
filter:
  template: >
    {%- set ns = namespace(results = []) -%} 
    {%- for item in <add search result here> -%} 
        <rework data>
        {%- set
        ns.results = ns.results + [
          {
            "image": image,
            "alt_text": name,
            "type": "picture",
            "tap_action": {
              "action": "perform-action",
              "perform_action": "<play>",
              "data": {
                "media_id": name
              }
            },
            "styles": {
              "card": {
                "margin": "1px",
                "padding": "1px"
              }
            }
          }
        ]-%} 
    {% endfor %} 
    {{ ns.results }}

All of my researches are not successfull. I did not bring the pieces together :frowning: .

Question:

How can i provide the search result as list into the dynamic button creation?
Are there any other possibilities?

Thanks four your help.
busdi

Hi @busdi

Did you already tried to store the result in a input_select or input_text helper?

I tried to store the data into a text helper without success.
Also the length of the text is very long and the text is a yaml - data object. Any possibility to structure the data (e.g. in a dynamic number of entities) before storing could be a possibility.

Script:

alias: spotify_search_album
description: ""
icon: mdi:album
fields: {}
sequence:
  - action: spotifyplus.search_albums
    data:
      entity_id: media_player.spotifyplus_configuration
      criteria: beatles
      limit_total: 3
    response_variable: result
  - action: input_text.set_value
    metadata: {}
    data:
      value: "{{ result }}"
    target:
      entity_id: input_text.test_searchalbum

The result of the scipt above is an “unknown” value in the input_text.test_searchalbum helper.

eventually a template sensor with a trigger and action would be a solution. But the number of entities (each entity a album) has to be dynamic. All entities have to be part of a “group, object…”.

@busdi
I did something similar to what you are trying to do with my SoundTouchPlus integration, in that I was building a “recently played” media list; the same methodology might be able to be applied to your SpotifyPlus integration issue. Note that it’s not a ready-to-go type of thing - some heavy modification will be needed. The point is that it worked for me, until I hit the 16k data limitations.

It involves defining a template trigger to periodically pull the data and store the response data in a template. The template sensor can then be referenced in Lovelace UI cards that support templates.

Limitations

The returned list of items will be truncated if the size of the list exceeds 16k in length, which it very well could for Spotify related data. This is due to the fact that the HA trigger sensor can only store a maximum of 16k of data in the HA state database entry. You will probably run into the same limitation issue with input_select and input_text helpers as well.

Template Sensor Automation

# SoundTouchPlus Recent Station List Update Template Sensor.
# Triggered when the 'soundtouchplus_recents_lastupdated' state changes (or when HA starts).
# IMPORTANT - Always set the sensor name and unique_id to match
  - trigger:
      - platform: state
        entity_id:
          - media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID 
        attribute: soundtouchplus_recents_lastupdated
      - platform: homeassistant
        event: start
    action:
      - service: soundtouchplus.recent_list
        data:
          entity_id: media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
        response_variable: service_response
    sensor:
      - name: soundtouchplus_list_recents
        unique_id: soundtouchplus_list_recents
        state: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}"
        attributes:
          serviceResponse: "{{ service_response }}"

Lovelace UI Card Definition

This will dynamically build and format the content list into a grid with cover artwork and titles. It also supports tap actions on the grid items (via browser_mod).

type: vertical-stack
cards:
  - type: markdown
    content: |-
      # Bose SoundTouch Recent List
      Tap an item to play the content.
      Last refreshed on: {{ states('sensor.soundtouchplus_list_recents') }}
  - type: custom:auto-entities
    card:
      type: grid
      columns: 8
    card_param: cards
    filter:
      template: >-
    
        {% set serviceResponse = None -%} 
    
        {%- set itmMediaPlayerEntityId = 'media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID' -%}
    
        {%- if has_value('sensor.soundtouchplus_list_recents') -%}
    
        {%-   set serviceResponse = state_attr('sensor.soundtouchplus_list_recents','serviceResponse') -%}
    
        {%- endif -%}
    
        {%- if serviceResponse != None -%}
    
          {%- for recent in serviceResponse['recents']['recent'] -%}
          
            {%- set itmId = recent['@id'] | default(0) -%}
            {%- set itmSourceTitle = recent['@SourceTitle'] | default('') -%}
            {%- set itmContainerArt = recent['ContentItem']['containerArt'] | default('/local/images/soundtouchplus_no_image.png') -%}
            {%- set itmItemName = recent['ContentItem']['itemName'] | default('') -%}
            {%- set itmSource = recent['ContentItem']['@source'] | default('') -%}
            {%- set itmSourceAccount = recent['ContentItem']['@sourceAccount'] | default('') -%}
            {%- set itmItemType = recent['ContentItem']['@type'] | default('') -%}
            {%- set itmLocation = recent['ContentItem']['@location'] | default('') -%}
            {%- set itmIsPresetable = recent['ContentItem']['@isPresetable'] | default('') -%}
            {{
              {
        'type': 'picture-entity',   
        'entity': 'input_boolean.always_enabled_helper',
        'image': itmContainerArt,   
        'show_state': false,   
        'show_name': true,  
        'name': itmItemName,   
        'tap_action': {
          'action': 'fire-dom-event',
          'browser_mod': {
            'browser_id': 'THIS',
            'service': 'soundtouchplus.play_contentitem', 
            'data': { 
              'entity_id': itmMediaPlayerEntityId,
              'name': itmItemName,
              'source': itmSource,
              'source_account': itmSourceAccount,
              'item_type': itmItemType,
              'location': itmLocation,
              'container_art': itmContainerArt,
              'is_presetable': itmIsPresetable
                    }
                  } 
                }
              }
            }},
          {%- endfor -%}
        {%- endif -%}

Another Possibility

Do your kids have their own Spotify user accounts? e.g. under a “family” Premium account maybe?

If so, why not use separate instances of the SpotifyPlus Card and set them up some user presets for their favorite content? You can disable other sections of the card if needed, and only display the player and user presets favorites.

Just throwing it out there.

Hope it helps!