Skip to content

Home Assistant UI Dashboards

Todd Lucas edited this page Sep 23, 2024 · 55 revisions

The following dashboards are useful to me in my environment, so I thought I would post them here in case anyone else finds them useful.

Index

SoundTouchPlus Card

The SoundTouchPlus-Card custom card adds Home Assistant front-end support for the SoundTouchPlus integration.

How it Looks

Features

  • Media Player UI
  • Display / Select SoundTouch Sources
  • Display / Select / Store SoundTouch Device Presets
  • Display / Select SoundTouch User Presets
  • Display / Select SoundTouch Device Recently Played items
  • Display / Select Pandora Stations

Check out the following links for more information:

Mini Media Player

Configuration using the Mini Media Player custom card by kalkih.

Check out the Using the Card page section for details on how to modify the look and feel of the player UI.

How it Looks

Requirements

The following are required in order to use this dashboard:

Lovelace UI Card Definition

Add the following YAML to a dashboard of your choice.

This definition also contains custom shortcuts for the SoundTouch presets (1 thu 6) and various inputs (Spotify, BlueTooth, TuneIn, and Pandora).

You will need to make the following changes to the yaml:

  • change media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID to your SoundTouch device entity_id (e.g. media_player.familyroom_soundbar)
  • change music service shortcuts to match your needs.
    • (optional) change SPOTIFY_USER_ID to your Spotify user id. Note that this is an ID value (e.g. 31l77y2al5lnn7mxfrmd4bpfhqke) and not a URI value (e.g. spotify:user:31l77y2al5lnn7mxfrmd4bpfhqke).
    • (optional) change PANDORA_USER_ID to your Pandora user id (e.g. youremail.com).
type: custom:mini-media-player
entity: media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
artwork: full-cover-fit
artwork_border: true
power_color: true
show_source: true
group: false
source: icon
info: long
hide:
  power: false
  repeat: true
  runtime: false
  shuffle: true
  source: false
  volume: false
shortcuts:
  columns: 6
  buttons:
    - name: 1
      type: service
      id: soundtouchplus.remote_keypress
      data:
        entity_id: media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
        key_id: PRESET_1
        key_state: release
    - name: 2
      type: service
      id: soundtouchplus.remote_keypress
      data:
        entity_id: media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
        key_id: PRESET_2
        key_state: release
    - name: 3
      type: service
      id: soundtouchplus.remote_keypress
      data:
        entity_id: media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
        key_id: PRESET_3
        key_state: release
    - name: 4
      type: service
      id: soundtouchplus.remote_keypress
      data:
        entity_id: media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
        key_id: PRESET_4
        key_state: release
    - name: 5
      type: service
      id: soundtouchplus.remote_keypress
      data:
        entity_id: media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
        key_id: PRESET_5
        key_state: release
    - name: 6
      type: service
      id: soundtouchplus.remote_keypress
      data:
        entity_id: media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
        key_id: PRESET_6
        key_state: release
    - name: Spotify
      type: service
      id: soundtouchplus.play_contentitem
      data:
        entity_id: media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
        source: SPOTIFY
        source_account: SPOTIFY_USER_ID
        location: spotify:playlist:5v5ETK9WFXAnGQ3MRubKuE
        item_type: uri
        is_presetable: true
    - name: Bluetooth
      type: service
      id: media_player.select_source
      data:
        entity_id: media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
        source: Bluetooth
    - name: Tunein
      type: service
      id: media_player.select_source
      data:
        entity_id: media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
        source: Tunein
    - name: Pandora
      type: service
      id: media_player.select_source
      data:
        entity_id: media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
        source: Pandora (PANDORA_USER_ID)

Maxi Media Player

Configuration using the Maxi Media Player custom card by punxaphil.

Check out the Usage section for details on how to modify the look and feel of the player UI.

How it Looks

Requirements

The following are required in order to use this dashboard:

Lovelace UI Card Definition

Add the following YAML to a dashboard of your choice. Note that this configuration uses the card_mod configuration syntax to style aspects of the card. You can remove the card_mod requirement for standard styling if you wish. It also hides the repeat and shuffle player control buttons.

You will need to make the following changes to the yaml:

  • change media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID to your SoundTouch device entity_id (e.g. media_player.familyroom_soundbar)
type: custom:maxi-media-player
sections:
  - player
entities:
  - media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
artworkAsBackground: true
dontSwitchPlayerWhenGrouping: true
playerVolumeOnlyAffectsMainPlayer: true
showVolumeUpAndDownButtons: false
hidePlayerControlPowerButton: false
hidePlayerControlShuffleButton: true
hidePlayerControlRepeatButton: true
card_mod:
  debug: false
  style:
    .: ''
    mxmp-player$: |
      mxmp-player-header {
        background-color: rgba(var(--rgb-card-background-color), 0.8) !important;
      }
      mxmp-player-controls {
        background-color: rgba(var(--rgb-card-background-color), 0.8) !important;
      }
    mxmp-player$ mxmp-player-controls$: |
      .icons * {
        --mdc-icon-button-size: 2.5rem !important;
        --mdc-icon-size: 1.5rem !important;
      }   
    mxmp-player$ mxmp-player-controls$ mxmp-volume$: |
      ha-control-slider {
        height: 14px !important;
      } 
      ha-icon-button {
        --mdc-icon-button-size: 2rem !important;
        --mdc-icon-size: 1.5rem !important;
      }   
      mxmp-ha-player {
        --mdc-icon-button-size: 2rem !important;
        --mdc-icon-size: 1.5rem !important;
      }

Preset List

NOTE - Due to HA template trigger sensor storage limitations (16K), it is recommended that you utilize the SoundTouchPlus Card for display and selection of Preset content instead of the following solution.

Displays the current SoundTouch preset list for a given device.

This will allow you to select a preset item for play on the device by tapping on a preset image.

It will also allow you to SET a preset slot to the currently playing content item by tapping and holding on a preset image. If the slot is empty, then it will be filled. If the slot is not empty, then it will be overwritten. Your SoundTouch device will also beep, indicating that a preset was stored.

How it Looks

How it Works

A template trigger is defined (via configuration.yaml) that will fire when the integration updates its soundtouchplus_presets_lastupdated attribute (e.g. an epoch datetime value). The integration updates this attribute whenever the preset_list service is called directly, or when a presetsupdated websocket event is received from the SoundTouch device. The websocket event can occur from a variety of ways: by the SoundTouch App when a preset is updated; by the 'press and hold' of a preset button on the phsyical device; or by the Python 3 BoseSoundTouchApi methods (StorePreset, RemovePreset).

The template trigger action calls the integrations' preset_list service to retrieve the current list of defined presets on the device. The preset list is returned as service response data, which gets stored to a variable named service_response.

The template trigger sensor step updates the sensor.soundtouchplus_list_presets template sensor state to the same value as the soundtouchplus_presets_lastupdated attribute. It also sets the sensor.soundtouchplus_list_presets template sensor serviceResponse attribute with the preset list data.

The template sensor can then be referenced in Lovelace UI cards that support templates.

Requirements

The following are required in order to use this dashboard:

  • HASS-Browser_Mod 2 Custom Card is used to display the list. Install it via HACS using the Install Instructions page.
  • soundtouchplus_no_image.png image to show for items that do not contain cover artwork.
  • configuration.yaml trigger definitions (see below).
  • input_boolean.always_enabled_helper must be defined as an 'always on' toggle switch. This is defined in the HA Configuration Helpers page as a toggle switch named always_enabled_helper. Once it is defined set it to On and leave it on.

configuration.yaml Changes

The following must be added to your configuration.yaml (or equivalent template definitions file). It is a trigger that detects when the preset list changes on the device, and updates a template sensor attribute with the updated list. The HASS-Browser_Mod Custom Card detects the change, and updates the dashboard.

You will need to make the following changes to the yaml:

  • change media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID to your SoundTouch device entity_id (e.g. media_player.familyroom_soundbar)
# SoundTouchPlus Preset List Update Template Sensor.
# Triggered when the 'soundtouchplus_presets_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_presets_lastupdated
      - platform: homeassistant
        event: start
    action:
      - service: system_log.write
        data:
          level: info
          logger: my_templates_automation
          message: "Automation triggered: SoundTouchPlus Preset List Update Trigger"
      - service: soundtouchplus.preset_list
        data:
          entity_id: media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
          include_empty_slots: true
        response_variable: service_response
    sensor:
      - name: soundtouchplus_list_presets
        unique_id: soundtouchplus_list_presets
        state: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}"
        attributes:
          serviceResponse: "{{ service_response }}"

Lovelace UI Card Definition

Add the following YAML to a dashboard of your choice.

I chose a View Type of Masonry (default) for my preset dashboard, so it is centered in the viewport.

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.

You will need to make the following changes to the yaml:

  • change media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID to your SoundTouch device entity_id (e.g. media_player.familyroom_soundbar)
type: vertical-stack
cards:
  - type: markdown
    content: |-
      # Bose SoundTouch Preset List
      Tap an item to play the content.
      Tap and hold an item to store now playing media as preset.
      Last refreshed on: {{ states('sensor.soundtouchplus_list_presets') }}
  - type: custom:auto-entities
    card:
      type: grid
      columns: 3
    card_param: cards
    filter:
      template: >-

        {% set serviceResponse = None -%} 

        {%- set itmMediaPlayerEntityId = 'media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID' -%}

        {%- if has_value('sensor.soundtouchplus_list_presets') -%}

        {%-   set serviceResponse = state_attr('sensor.soundtouchplus_list_presets','serviceResponse') -%}

        {%- endif -%}

        {%- if serviceResponse != None -%}

          {%- for preset in serviceResponse['presets']['preset'] -%}
          
            {%- set itmId = preset['@id'] | default(0) -%}
            {%- set itmSourceTitle = preset['@SourceTitle'] | default('') -%}
            {%- set itmContainerArt = preset['ContentItem']['containerArt'] | default('/local/images/soundtouchplus_no_image.png') -%}
            {%- set itmItemName = preset['ContentItem']['itemName'] | default('') -%}
            {%- set itmSource = preset['ContentItem']['@source'] | default('') -%}
            {%- set itmSourceAccount = preset['ContentItem']['@sourceAccount'] | default('') -%}
            {%- set itmItemType = preset['ContentItem']['@type'] | default('') -%}
            {%- set itmLocation = preset['ContentItem']['@location'] | default('') -%}
            {%- set itmIsPresetable = preset['ContentItem']['@isPresetable'] | default('false') -%}
            {%- if itmItemName != 'empty preset' -%}
            {{
              {
        '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
                    }
                  } 
                },
        'hold_action': {
          'action': 'fire-dom-event',
          'browser_mod': {
            'browser_id': 'THIS',
            'service': 'soundtouchplus.remote_keypress', 
            'data': { 
              'entity_id': itmMediaPlayerEntityId,
              'key_id': 'PRESET_' + itmId,
              'key_state': 'press'
                    }
                  } 
                }
              }
            }},
            {%- else -%}
            {{
              {
        'type': 'picture-entity',    
        'entity': 'input_boolean.always_enabled_helper',  
        'image': '/local/images/soundtouchplus_no_image.png',    
        'show_state': false,  
        'show_name': true,    
        'name': itmItemName,    
        'tap_action': {
          'action': 'fire-dom-event',
          'browser_mod': {
            'browser_id': 'THIS',
            'service': 'soundtouchplus.remote_keypress', 
            'data': { 
              'entity_id': itmMediaPlayerEntityId,
              'key_id': 'PRESET_' + itmId,
              'key_state': 'press'
                    }
                  } 
                }
              }
            }},
            {%- endif -%}
          {%- endfor -%}
        {%- endif -%}

No Image File

Save the following to the \config\www\images\soundtouchplus_no_image.png location. This image will be displayed for grid items that do not have cover art assigned or are an empty preset slot.

Music Service - Pandora List

NOTE - Due to HA template trigger sensor storage limitations (16K), it is recommended that you utilize the SoundTouchPlus Card for display and selection of Pandora Station content instead of the following solution.

Displays your collection of Pandora Music Service station favorites.

This will allow you to select a station item for play on the device by tapping on an item image.

How it Looks

How it Works

A template trigger is defined (via configuration.yaml) that will fire every 2 hours to update the list.

The template trigger action calls the integrations' musicservice_station_list service to retrieve the current list of stations. The list is returned as service response data, which gets stored to a variable named service_response.

The template trigger sensor step updates the sensor.soundtouchplus_list_musicservice_pandora template sensor state to the current datetime. It also sets the sensor.soundtouchplus_list_musicservice_pandora template sensor serviceResponse attribute with the list data.

The template sensor can then be referenced in Lovelace UI cards that support templates.

Requirements

The following are required in order to use this dashboard:

  • HASS-Browser_Mod 2 Custom Card is used to display the list. Install it via HACS using the Install Instructions page.
  • soundtouchplus_no_image.png image to show for items that do not contain cover artwork.
  • configuration.yaml trigger definitions (see below).
  • input_boolean.always_enabled_helper must be defined as an 'always on' toggle switch. This is defined in the HA Configuration Helpers page as a toggle switch named always_enabled_helper. Once it is defined set it to On and leave it on.

Limitations

The returned list of items will be truncated if the size of the list exceeds 16k in length, which it normally does for Pandora Stations and Recently Played items. 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.

Use the SoundTouchPlus Card instead to get around this limitation.

configuration.yaml Changes

The following must be added to your configuration.yaml (or equivalent template definitions file). It is a trigger that fires every 2 hours to update a template sensor with the music service list. The HASS-Browser_Mod Custom Card detects the change, and updates the dashboard.

You will need to make the following changes to the yaml:

  • change media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID to your SoundTouch device entity_id (e.g. media_player.familyroom_soundbar)
  • change YOUR_PANDORA_USERID to your Pandora source account id; this is usually the email address that is used to login to Pandora.
# SoundTouchPlus Music Service Pandora Station List Update Trigger.
# Triggered every 4 hours (or when HA starts) to refresh Pandora Music Service station favorites.
# IMPORTANT - Always set the sensor name and unique_id to match in the sensor step.
  - trigger:
      - platform: time_pattern
        hours: "/4"
      - platform: homeassistant
        event: start
    action:
      - service: system_log.write
        data:
          level: info
          logger: my_templates_automation
          message: "Automation triggered: SoundTouchPlus Music Service Pandora Station List Update Trigger"
      - service: soundtouchplus.musicservice_station_list
        data:
          entity_id: media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID
          source: PANDORA
          source_account: YOUR_PANDORA_USERID
          sort_type: dateCreated
        response_variable: service_response
    sensor:
      - name: soundtouchplus_list_musicservice_pandora
        unique_id: soundtouchplus_list_musicservice_pandora
        state: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}"
        attributes:
          serviceResponse: "{{ service_response }}"

Lovelace UI Card Definition

Add the following YAML to a dashboard of your choice. I chose a View Type of Panel (1 card) for my dashboard, so it covers the entire width of the viewport.

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.

You will need to make the following changes to the yaml:

  • change media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID to your SoundTouch device entity_id (e.g. media_player.familyroom_soundbar)
type: vertical-stack
cards:
  - type: markdown
    content: |-
      # Bose SoundTouch Pandora Stations
      Tap an item to play the content.
      Last refreshed on: {{ states('sensor.soundtouchplus_list_musicservice_pandora') }}
  - 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_musicservice_pandora') -%}
    
        {%-   set serviceResponse = state_attr('sensor.soundtouchplus_list_musicservice_pandora','serviceResponse') -%}
    
        {%- endif -%}
    
        {%- if serviceResponse != None -%}
    
          {%- for item in serviceResponse['items']['item'] -%}

            {%- set itmSourceTitle = item['@SourceTitle'] | default('') -%}
            {%- set itmContainerArt = item['ContentItem']['containerArt'] | default('/local/images/soundtouchplus_no_image.png') -%}
            {%- set itmItemName = item['ContentItem']['itemName'] | default('') -%}
            {%- set itmSource = item['ContentItem']['@source'] | default('') -%}
            {%- set itmSourceAccount = item['ContentItem']['@sourceAccount'] | default('') -%}
            {%- set itmLocation = item['ContentItem']['@location'] | default('') -%}
            {%- set itmIsPresetable = item['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,
              'location': itmLocation,
              'container_art': itmContainerArt,
              'is_presetable': itmIsPresetable
                    }
                  } 
                }
              }
            }},
          {%- endfor -%}
        {%- endif -%}

No Image File

Save the following to the \config\www\images\soundtouchplus_no_image.png location. This image will be displayed for grid items that do not have cover art assigned.

Recently Played List

NOTE - Due to HA template trigger sensor storage limitations (16K), it is recommended that you utilize the SoundTouchPlus Card for display and selection of Recently Played content instead of the following solution.

Displays the recently played content list for a given device.

This will allow you to select a preset item for play on the device by tapping on a preset image.

How it Looks

How it Works

A template trigger is defined (via configuration.yaml) that will fire when the integration updates its soundtouchplus_recents_lastupdated attribute (e.g. an epoch datetime value). The integration updates this attribute whenever the recent_list service is called directly, or when a recentsupdated websocket event is received from the SoundTouch device. The websocket event can occur from a variety of ways: by the SoundTouch App when new content is played; by the press of a preset button on the phsyical device; or by the Python 3 BoseSoundTouchApi play content methods (PlayContentItem, SelectPreset, etc).

The template trigger action calls the integrations' recent_list service to retrieve the current list of recently played content on the device. The recent list is returned as service response data, which gets stored to a variable named service_response.

The template trigger sensor step updates the sensor.soundtouchplus_list_recents template sensor state to the same value as the soundtouchplus_recents_lastupdated attribute. It also sets the sensor.soundtouchplus_list_recents template sensor serviceResponse attribute with the recent list data.

The template sensor can then be referenced in Lovelace UI cards that support templates.

Requirements

The following are required in order to use this dashboard:

  • HASS-Browser_Mod 2 Custom Card is used to display the list. Install it via HACS using the Install Instructions page.
  • soundtouchplus_no_image.png image to show for items that do not contain cover artwork.
  • configuration.yaml trigger definitions (see below).
  • input_boolean.always_enabled_helper must be defined as an 'always on' toggle switch. This is defined in the HA Configuration Helpers page as a toggle switch named always_enabled_helper. Once it is defined set it to On and leave it on.

Limitations

The returned list of items will be truncated if the size of the list exceeds 16k in length, which it normally does for Pandora Stations and Recently Played items. 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.

Use the SoundTouchPlus Card instead to get around this limitation.

configuration.yaml Changes

The following must be added to your configuration.yaml (or equivalent template definitions file). It is a trigger that detects when the recent list changes on the device, and updates a template sensor with the updated list. The HASS-Browser_Mod Custom Card detects the change, and updates the dashboard.

You will need to make the following changes to the yaml:

  • change media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID to your SoundTouch device entity_id (e.g. media_player.familyroom_soundbar)
# 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: system_log.write
        data:
          level: info
          logger: my_templates_automation
          message: "Automation triggered: SoundTouchPlus Recent List Update Trigger"
      - 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

Add the following YAML to a dashboard of your choice. I chose a View Type of Panel (1 card) for my recently played dashboard, so it covers the entire width of the viewport.

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.

You will need to make the following changes to the yaml:

  • change media_player.YOUR_SOUNDTOUCH_DEVICE_ENTITY_ID to your SoundTouch device entity_id (e.g. media_player.familyroom_soundbar)
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 -%}

Or if you prefer a button type of look without cover art images, replace the picture-entity base variables with the following (thanks @jasebob for the tip):

...
        'type': 'button',
        'entity': 'input_boolean.always_enabled_helper',
        'show_state': false, 
        'show_icon': false,
        'show_name': true,
        'name': itmItemName,
...        

No Image File

Save the following to the \config\www\images\soundtouchplus_no_image.png location. This image will be displayed for grid items that do not have cover art assigned.