Dashboard: Sonos card

Thank you!
Whenever I try to set this variable it comes changes the background to transparent instead of the set color. This was already the case for me when I tried to set this for the covers in the favorites (earlier posts).
Does this only happen for me?

No idea if this is the best place to post but here we go.
I have spent a few days, with a lot of brain damage to create my sonos player and thought I’d share my learnings. Here’s the punchline (yaml mode):

The top element is a modded custom:mini-media-player. Why? I like it’s compact media friendly style.

The next block is my own grid of custom:button-card’s. Each launches the displayed shortcut. Figuring out how to get the sonos entity to accept all these shortcuts took forever. I’m gonna do a follow up post on that.

The next block is sonos card, stripped of everything except the launch button bar. So I can access favorites, grouping and so on.

Here’s what that looks like (it auto expands):

Finally, we have another mini-media-player, that controls the receiver that the sonos is playing through. My sonos feeds multiple destinations, so I like to be able to control the master sonos volume (first media player) and the specific area I’m in (second media-player).

Here’s the code (excluding the !includes):

# lovelace_gen

{% set sonos_shortcut_data = [
  {"label": "Discover Weekly", "command": "spotify:user:spotify:playlist:37i9dQZEVXcLfFHFjIa3mz", "source_id": "Discover Weekly", "icon": "si:spotify", "color": "rgb(29, 185, 84)"},
  {"label": "Release Radar", "command": "spotify:user:spotify:playlist:37i9dQZF1E37VWUN6PIVn6", "source_id": "Release Radar", "icon": "si:spotify", "color": "rgb(29, 185, 84)"},
  {"label": "The Coffee House-17", "command": "x-sonosapi-hls-static:channel-linear%3a41f8b174-fb06-1707-aaa7-e74e109c2ee9?sid=37&flags=8232&sn=2", "source_id": "CH 17 - The Coffee House", "icon": "fapro:sirius-xm#fullcolor"},
  {"label": "Daily Mix 1", "content_type": "playlist", "command": "spotify:user:spotify:playlist:37i9dQZF1E37VWUN6PIVn6", "icon": "si:spotify", "source_id": "Daily Mix 1", "color": "rgb(29, 185, 84)"},
  {"label": "Indie Folk",  "command": "https://www.deezer.com/en/playlist/1750314842", "source_id": "Firepit Singalong", "icon": "fapro:deezer-2023#fullcolor"},
  {"label": "Firepit Music Classics", "command": "Firepit Music Classics", "icon": "si:sonos",  "content_type": "playlist"},
  {"label": "Feel Good Alt", "command": "x-sonosapi-radio:catalog%2fstations%2fA1GCD4WZPYK96P%2f%23chunk-hoqkntnFRCCXcdBau70Evg?sid=201&flags=8300&sn=7", "icon": "fapro:amazonmusic", "color": "#46C3D0", "size":'44px'},
  {"label": "My 2024 Favs #1","command": "spotify:user:spotify:playlist:63yn3W32lQKYIdzBdpdTpr", "icon": "si:spotify", "color": "rgb(29, 185, 84)"},
  {"label": "AC/DC Back in Black","command": "x-rincon-playlist:RINCON_B8E9379F2D7A01400#A:ALBUMARTIST/AC%2fDC/Back%20in%20Black", "source_id":"Back in Black", "icon": "si:sonos"},
  {"label": "Pure Unplugged", "command": "FV:2/19", "content_type": "favorite_item_id", "source_id": "Pure Unplugged", "icon": "si:sonos"},
] %}

{% set sonos_shortcut_entity = " media_player.basement" %}
{% set sonos_shortcut_service = "media_player.play_media" %}
{% set sonos_shortcut_source_attribute = "media_playlist" %}

title: Sonos
views:
- title: Sonos View
  type: masonry
  cards:
    - type: custom:stack-in-card
      card_mod:
        style: |
          ha-card {
            max-width: 388px;
          }
      cards:
        - type: custom:mini-media-player
          entity: {{sonos_shortcut_entity}}
          group: true
          artwork: cover
          hide:
            jump: false
            power: true
            volume: false
            source: true
          info: short
          source: icon
          card_mod:
            style: |
              div.mmp-player {
              }
              div.mmp-player__adds {
                margin-left: 6px;
                margin-right: 6px;
              }
        - !include
            - includes/components/shortcut_menu_custom_button.yaml
            - shortcut_service: {{sonos_shortcut_service}}
              shortcut_entity: {{sonos_shortcut_entity}}
              shortcut_data: {{sonos_shortcut_data}}
              service_type: "music"
              shortcut_source_attribute: {{sonos_shortcut_source_attribute}} #optional
              shortcut_grid_columns: "160px 160px"
              shortcut_grid_rows: "34px 34px 34px 34px"
              display_mode: "text"
              button_bg: {{button_bg}}                    #optional
              button_hover_bg: {{button_hover_bg}}        #optional
              button_selected_bg: {{button_selected_bg}}  #optional
              button_type: custom:mushroom-template-card  #optional
              max_icon_height: 24px
              icon_size: 24px
              layout_margin: "0px 0 0px 0"
        - entity: media_player.basement
          type: custom:sonos-card
          sections:
            - volumes
            - groups
            - grouping
            - media browser
            - player
          mediaBrowserItemsPerRow: 3
          card_mod:
            style:
              sonos-volumes$:
                .: |
                  .row:first-of-type {
                    margin-top: 1rem;
                  }
                  .row {
                    padding-right: 1.5rem;
                    padding-left: 1.5rem;
                  }
                sonos-volume$:
                  .: |
                    ha-control-slider {
                      --control-slider-thickness: 16px;
                      margin-top: 12px;
                    }
              sonos-player$:
                .: |
                  div.artwork {       
                    
                    }
                  div.container {
                    display: none;
                  }
              sonos-media-browser$:
                .: |
                  sonos-media-browser-header {
                    height: 1.5rem;
                  }
                sonos-media-browser-icons$:
                  .: |
                    div.icons {
                      height: 20rem;
                      overflow-y: auto;
                    }
                sonos-media-browser-header$:
                  .: |
                    .title {
                      font-size: 1.25rem !important;
                      justify-content: left !important;
                      font-weight: 400 !important;
                      }
                    sonos-ha-player {
                      display: flex;
                      align-items: center;
                      justify-content: right;
                      padding-top: 3px;
                    }
                    div.icons {
                      height: 25rem !important;
                    }
              .: |
                ha-card.type-custom-sonos-card {
                  height: 100% !important;
                  margin: auto;
                  border-style: none;
                }
                div.content {
                  background: white;
                  height: auto !important;
                  overflow-y: auto !important;
                }
                sonos-footer {
                  height: 1.5rem !important;
                  padding-top: 0.5rem !important;
                  padding-bottom: 0.5rem !important;
                  display: flex;
                  align-items: center;
                  --mdc-icon-size: 1.5rem !important;
                }
        - entity: media_player.pioneer_receiver
          type: custom:mini-media-player
          name: Pioneer SC-LX704 Receiver
          group: true
          hide:
            play_pause: true
          card_mod:
            style:
              mmp-powerstrip$:
                .: |
                  mmp-source-menu {
                    font-weight: 400 !important!;
                    max-width: 200px !important;
                  }
              .: |
                div.mmp-player {
                  padding: 12px !important;
                }
                div.mmp-player__adds {
                  margin-left: 12px !important;
                  margin-right: 12px !important;
                }
3 Likes

Is there now a function that allows you to start all (e.g. Spotify) playlists in Shuffle? That would be a great function, so you wouldn’t always have to make 2 clicks. :slight_smile:

I know this isn’t specifically an issue with the Sonos card, but certainly must affect a good number of Sonos users here who use Spotify. I (and apparently others) have found the HA media browser is unable to browser and/or play Spotify playlists on a Sonos device.

I am able to use the Spotify app and Spotify Connect to play playlists on the Sonos and HA & this Sonos card displays everything correctly, but cannot browse playlists from within HA and Sonos card using the HA media browser.

I know the HA Spotify integration states: “Although Sonos is a Spotify Connect device, it is not supported by the official Spotify API” but was hoping someone here might know of a magic bullet that slays this dragon.

Describing the problem in more detail - I’m able to browse and play everything else from Spotify (artists, albums, songs, etc) as well as from other sources with the HA Sonos integration using the media browser, except Spotify playlists. When I try to browse playlists I get a “Media Browsing Error - Unknown Error” message. The HA log shows the following:

File “/usr/src/homeassistant/homeassistant/components/websocket_api/decorators.py”, line 26, in _handle_async_response
await func(hass, connection, msg)
File “/usr/src/homeassistant/homeassistant/components/media_player/init.py”, line 1310, in websocket_browse_media
payload = await player.async_browse_media(media_content_type, media_content_id)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/src/homeassistant/homeassistant/components/spotify/media_player.py”, line 472, in async_browse_media
return await async_browse_media_internal(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/src/homeassistant/homeassistant/components/spotify/browse_media.py”, line 225, in async_browse_media_internal
response = await hass.async_add_executor_job(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/local/lib/python3.12/concurrent/futures/thread.py”, line 58, in run
result = self.fn(*self.args, **self.kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/src/homeassistant/homeassistant/components/spotify/browse_media.py”, line 390, in build_item_response
item_payload(item, can_play_artist=can_play_artist)
File “/usr/src/homeassistant/homeassistant/components/spotify/browse_media.py”, line 439, in item_payload
browse_media.thumbnail = fetch_image_url(item)
^^^^^^^^^^^^^^^^^^^^^
File “/usr/src/homeassistant/homeassistant/components/spotify/util.py”, line 24, in fetch_image_url
return item.get(key, )[0].get(“url”)
~~~~~~~~~~~~~~~~~^^^
TypeError: ‘NoneType’ object is not subscriptable

@prgeno
Based on the logs you provided, it appears that one or more of your playlists are missing a cover image; the fetch_image_url method is failing because it assumes there is an images item at the zero index position, and there is not (proven by the TypeError: 'NoneType' object is not subscriptable exception).

Go to the Spotify web site and display your playlists there. Assign an image to any playlist that does not have an image.

The problem is that the fetch_image_url method only traps IndexError exceptions; the exception being raised is a TypeError so it doesn’t catch it, and it bubbles back up the chain of events.

def fetch_image_url(item: dict[str, Any], key="images") -> str | None:
    """Fetch image url."""
    try:
        return item.get(key, [])[0].get("url")     # <- this is the problem
    except IndexError:
        return None

That function should be updated to this:

def fetch_image_url(item: dict[str, Any], key="images") -> str | None:
    """Fetch image url."""
    try:
        return item.get(key, [])[0].get("url")
    except Exception:
        return None

The function change is not something that you can correct though. But adding an image to playlists that don’t have an image should fix your issue.

Hope it helps!

@prgeno
FYI … I just verified that was the issue. I created an empty playlist with no cover image, and the built-in Spotify integration returned the “Unknown Error” dialog and the TypeError: 'NoneType' object is not subscriptable log message.

I wanted to make sure my SpotifyPlus integration could handle it (and it did). :smiley:

Also, you are not the only one with this issue - check out this community thread for more details.

Todd,

Thank you so much for digging into this. I will verify my playlists later today and report back here.

Also, I can’t wait to check out your Spotify Plus integration. I know the HA devs and addon/integration devs like yourself don’t hear it nearly often enough, but HA users like myself are incredibly appreciative for what you folks add to HA for all of our benefit.

So a big thank you for your efforts

1 Like

Could you contribute this fix to the standard Spotify integration?

@PunxsutawneyPhil
Sorry, but I can’t supply the fix as I am not the owner of the original Spotify integration.

With that said, I opened issue #114454 on the HA GitHub page - not sure when it will be taken care of though.

Hope it helps!

Can’t you fork and open a pull request?

Playlists not having an image doesn’t appear to be the problem, at least not in my case. While I never explicitly assigned an image to any of my playlists, I did not find any playlist that didn’t already have an image (usually a cover of a track in the playlist) automatically assigned.

The only playlist that didn’t have an image was the automatically generated “Liked Songs” playlist, which I cleared out to get rid of it. I also took the time to weed out old playlists thinking maybe I had too many.

Unfortunately I’m still getting the same error using the Official Spotify Integration when accessing it through the Sonos Card.

While that is bad news for me, the good news for you is: I added your Spotify Plus integration and it lists my playlists just fine. So whatever the official integration is not doing correctly, you are.

If only your integration also worked with Sonos devices, which it apparently does not, and/or could be made to work with the Sono Card as a replacement for, or an addition to, the HA media browser.

Unfortunately, my situation is no better off than it was. I’ll keep poking around to see if I can find a common thread, but it’s at least nice to know something out there works, and that gives me some hope for the future.

Thanks again

@PunxsutawneyPhil
Per the integration owner …

“This has been fixed in 2024.4, will land next Wednesday”

Too much work and too many hoops to jump thru for a pull request. It’s an easy fix for the owner.

1 Like

@prgeno
Thanks for the info Paul. Unfortunately, I don’t have any Sonos gear to test with. I’m a Bose Soundtouch guy myself.

A question about Sonos if you have a second … can you reply with an example service call (or script, automation) that you use to power on the Sonos device and play a Spotify track / album / playlist?

Just curious if the Sonos has Spotify Connect built in to the speaker? Or does it use Google Cast api maybe? And do you have to use Spotcast to prepare it for play?

I ask, as the SpotifyPlus integration has a turn on script mechanism that can be used to power up the device that plays the Spotify content.

The Bose Sountouch has Spotify Connect support built in, so it handles it natively.

1 Like

@prgeno

Any messages in the System Log for the error? If it says something about ‘fetch_image_url’ then it’s still a missing image issue. I believe that method is used to fetch any type of media image (playlist, album, artist, etc).

And to verify, if you have multiple Spotify accounts, when you are verifying playlist images, you are logged into the online Spotify interface using the same account selected in the HA media browser?

Maybe this conversation should be moved to a different topic? It’s drifting away from the Sonos Card

@PunxsutawneyPhil @prgeno
Apologies Phil, you are correct; this is getting off topic from the Sonos card. Thanks for keeping us on point.

Paul - we can carry on the conversation in a private message if that works for you?

1 Like

@PunxsutawneyPhil

Sorry for bringing this up in this thread. But I only use your Sonos Card for our whole house audio system, and I would guess that this Spotify Playlist issue must be affecting other Sonos Card users as well.

Hopefully the Official Spotify integration update next month will fix the issue. But maybe Sonos Card could use help from Spotify Plus to offer a more robust Spotify media browser from within Sonos Card?

@thlucas I’ll head over to the Spotify Plus thread to try and answer your questions. But as I stated above, I only use Sonos devices and the Sonos Card in my system. Spotify Plus on its own has very limited use in my situation, but I’m happy to try and help in any way I can.

Loving this card, thank you!

I’ve been playing around with some card-mod code to change what the card looks like, but I haven’t been able to find a few options. I’m not great at CSS and I can see what some elements are called, but my mods don’t seem to work.

This is what I have:

image

card_mod:
  style:
    sonos-player$ sonos-player-controls$: |
      .icons * {    
        --mdc-icon-button-size: 3rem !important;
        --mdc-icon-size: 2rem !important;
        color: pink;
      }
    sonos-player$ sonos-player-controls$ sonos-volume$: |
      ha-control-slider {
        height: 10px;
      }
      .volume-level, ha-icon-button {
        display:none !important;
      }

I’m changing the size of the volume bar and hiding the mute button, and setting the icon and button sizes of the controls, plus setting a color.

I found mentions of setting transparency for the overlays, and they need to be in themes, I can look into that later.

Questions.

  • How do I resize the bottom overlay? I’d like it to be probably 60-70% narrower, or even more in line with the top overlay. Since my buttons are small, I don’t need it to be this big
    image
  • How do I hide some of the buttons in the card? I never use repeat or shufflet, I’d like to only keep previous, pause and next.
  • How do I hide the Entity/Group name? I use this card in my Office Dashboard so I don’t need to know what speakers are being used. Would help make it shorter without needing to scroll.

bottom overlay:

card_mod:
  style:
    sonos-player$: |
      .controls {
        margin: 0 3rem !important;
      }

hide buttons: not possible as far as I know

hide entity group name:

    sonos-player$ sonos-player-header$: |
      .entity {
        display: none;
      }
1 Like

I am suddenly getting tons of these errors regarding, i suppose, the sonos card:

2024-04-03 21:24:50.451 ERROR (MainThread) [frontend.js.latest.202403070] Uncaught error from Chrome 123.0.0.0 on Windows 10
ReferenceError: Cannot access ‘e’ before initialization
Object.callback (/hacsfiles/custom-sonos-card/custom-sonos-card.js:358:980)
callback (node_modules/home-assistant-js-websocket/dist/connection.js:23:33)
forEach (node_modules/home-assistant-js-websocket/dist/connection.js:15:25)
2024-04-03 21:30:05.055 ERROR (MainThread) [frontend.js.latest.202403070] Uncaught error from Chrome 123.0.0.0 on Windows 10
ReferenceError: Cannot access ‘e’ before initialization
Object.callback (/hacsfiles/custom-sonos-card/custom-sonos-card.js:358:980)
callback (node_modules/home-assistant-js-websocket/dist/connection.js:23:33)
forEach (node_modules/home-assistant-js-websocket/dist/connection.js:15:25)
2024-04-03 21:31:20.484 ERROR (MainThread) [frontend.js.latest.202403070] Uncaught error from Chrome 123.0.0.0 on Windows 10
ReferenceError: Cannot access ‘e’ before initialization
Object.callback (/hacsfiles/custom-sonos-card/custom-sonos-card.js:358:980)
callback (node_modules/home-assistant-js-websocket/dist/connection.js:23:33)
forEach (node_modules/home-assistant-js-websocket/dist/connection.js:15:25)
2024-04-03 21:31:50.604 ERROR (MainThread) [frontend.js.latest.202403070] Uncaught error from Chrome 123.0.0.0 on Windows 10
ReferenceError: Cannot access ‘e’ before initialization
Object.callback (/hacsfiles/custom-sonos-card/custom-sonos-card.js:358:980)
callback (node_modules/home-assistant-js-websocket/dist/connection.js:23:33)
forEach (node_modules/home-assistant-js-websocket/dist/connection.js:15:25)
2024-04-03 21:35:50.553 ERROR (MainThread) [frontend.js.latest.202403070] Uncaught error from Chrome 123.0.0.0 on Windows 10
ReferenceError: Cannot access ‘e’ before initialization
Object.callback (/hacsfiles/custom-sonos-card/custom-sonos-card.js:358:980)
callback (node_modules/home-assistant-js-websocket/dist/connection.js:23:33)
forEach (node_modules/home-assistant-js-websocket/dist/connection.js:15:25)
2024-04-03 21:43:11.674 ERROR (MainThread) [frontend.js.latest.202403070] Uncaught error from Chrome 123.0.0.0 on Windows 10
ReferenceError: Cannot access ‘e’ before initialization
Object.callback (/hacsfiles/custom-sonos-card/custom-sonos-card.js:358:980)
callback (node_modules/home-assistant-js-websocket/dist/connection.js:23:33)
forEach (node_modules/home-assistant-js-websocket/dist/connection.js:15:25)
2024-04-03 21:43:11.723 ERROR (MainThread) [frontend.js.latest.202403070] Uncaught error from Chrome 123.0.0.0 on Windows 10
ReferenceError: Cannot access ‘e’ before initialization
Object.callback (/hacsfiles/custom-sonos-card/custom-sonos-card.js:358:980)
callback (node_modules/home-assistant-js-websocket/dist/connection.js:23:33)
forEach (node_modules/home-assistant-js-websocket/dist/connection.js:15:25)
2024-04-03 21:49:41.809 ERROR (MainThread) [frontend.js.latest.202403070] Uncaught error from Chrome 123.0.0.0 on Windows 10
ReferenceError: Cannot access ‘e’ before initialization
Object.callback (/hacsfiles/custom-sonos-card/custom-sonos-card.js:358:980)
callback (node_modules/home-assistant-js-websocket/dist/connection.js:23:33)
forEach (node_modules/home-assistant-js-websocket/dist/connection.js:15:25)
2024-04-03 21:49:41.859 ERROR (MainThread) [frontend.js.latest.202403070] Uncaught error from Chrome 123.0.0.0 on Windows 10
ReferenceError: Cannot access ‘e’ before initialization
Object.callback (/hacsfiles/custom-sonos-card/custom-sonos-card.js:358:980)
callback (node_modules/home-assistant-js-websocket/dist/connection.js:23:33)
forEach (node_modules/home-assistant-js-websocket/dist/connection.js:15:25)

From what it depends and how to fix?