Bose soundtouch create_zone

Hi Todd
This is really nice documentation and certainly answered my question about how to access the service to get the list from within a card. I think HA generally misses this kind of documentation - “How to use” with some nice examples. I think some in the community get hung up on the flexibility and not wanting to “tell people” how to use something. But templates are indeed tricky! So starting with something that works and modifying it really is the best way for people to enjoy what you have done.

Hi Todd

Ahh right. This is a better solution to use the base class’ functions. I did not realize these were even there, being locked into SoundTouch API all this time.
OK I am off to rewrite some cards and automations!..
This is looking awesome by the way, and with my new Wifi providing such a better experience with the Bose system I have a new enthusiasm for it! I cant believe the difference given the ASUS routers ran everything else I have perfectly well.

BTW I have 2xST20, 2xST10 (as a stereo pair), SA-5 amp, 2x Wireless Link Controllers feeding older (not smart) Bose speakers. I haven’t got to trying the TTS or snapshot functions but I think my devices are all first generation and may not support it.

@jasebob Very cool, thank you for the kind words.

Per the SoundTouch WebServices API reference: audio notifications (e.g. TTS) are only available for SoundTouch 10, SoundTouch 20 Series III, and SoundTouch 30 Series III. Attempting to send an Audio Notification to an incompatible device will return a 403 Forbidden error.

I would be curious to know if it works on an older generation ST-10.

I will try.
Do any of the API functions return hardware version information?

I get the 403 Forbidden message for the ST20, SA-5 Amp and Wireless Link Controllers - as expected.
The ST10 attempts to play, music stops and after several seconds I get this API error. Then the music resumes.

SoundTouchError: "BST1002E - 'Master Bedroom': SoundTouch Web-services API returned an error status: 'media referenced by url is not supported by speaker'", code="415", name="HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE", severity="Unknown"

@jasebob Are you referring to the integration services? or the underlying bosesoundtouchapi library?

The library definitely has all of that information. I wrote / maintain the bosesoundtouchapi library as well.

The soundtouchplus integration does not currently return that information, but a service could be added to return it.

What information (specifically) are you looking for? The SoundTouch WebServices API (my wiki docs) can return a LOT of information types. Here are some off the top of my head that contain hardware related information:

  • /info service returns basic information that is common to all SoundTouch devices.The response contains such details as device name, device type, what software components are installed and their versions, region codes, and other valuable information.
  • /networkInfo service returns the current network information configuration of the device.
  • /performWirelessSiteSurvey service gets a list of wireless networks that can be detected by the device.

… and many more.

I was just thinking that you could use the hardware version to populate the supported_features

@jasebob Ahhh, understood. I already have checks in the integration code for device-specific features. Each SoundTouch device will return /supportedURLs, which basically indicates what the device is (and is not) capable of.

For example, the ST-10 does not support audio mode capabilities, tone controls, level controls, etc, while the ST-300 does. The ST-300 /supportedURLs will return extra information, which indicates it supports these features. Like so:

  <URL location="/audiodspcontrols" />
  <URL location="/audioproductlevelcontrols" />
  <URL location="/audioproducttonecontrols" />
  <URL location="/audiospeakerattributeandsetting" />
  <URL location="/productcechdmicontrol" />
  <URL location="/producthdmiassignmentcontrols" />

The SoundTouchPlus integration retrieves and caches this list of features when it is initialized, so it’s just a matter of querying the supported url’s cache to check if a feature is enabled or not for a device. Here’s the code for the select_sound_mode processing to give you an example (ST-10 does not support this, ST-300 does):

  _logsi.LogVerbose(STAppMessages.MSG_PLAYER_COMMAND + " - SoundMode='%s'", "Select Sound Mode", self.name, self.entity_id, sound_mode)

  # does device support audio dsp controls?
  if SoundTouchNodes.audiodspcontrols.Path in self._client.ConfigurationCache:
      
      # is sound_mode an audio mode name?  if so, then we need the value.
      audioDspAudioMode:str = AudioDspAudioModes.GetValueByName(sound_mode)
      if audioDspAudioMode is not None:
          sound_mode = audioDspAudioMode

      # does sound mode list contain the specified sound_mode?
      # if so, then change the sound mode; otherwise log an error message.
      config:AudioDspControls = self._client.ConfigurationCache[SoundTouchNodes.audiodspcontrols.Path]
      if sound_mode in config.SupportedAudioModes:
          cfgUpdate:AudioDspControls = AudioDspControls(audioMode=sound_mode)
          self._client.SetAudioDspControls(cfgUpdate)
      else:
          _logsi.LogError("'%s': Specified sound_mode value '%s' is not a supported audio mode; check the sound_mode_list state value for valid audio modes" % (self.name, sound_mode))
  else:
      _logsi.LogWarning("'%s': Device does not support AudioDspControls; cannot change the sound mode" % (self.name))

In summary, I don’t have to have specific checks for device types in my code - the device itself tells me if it supports a feature or not based on the /supportedURLs response.

If a device does not support a feature, then I will issue a warning log message so the user can see something in the HA logs that indicate the feature is not supported. I also try to document which devices support what features in the wiki, but it’s tough to do since I only have the ST-10 and ST-300 device types.

I really wish Bose would have published more detailed information about their API’s and such, but they closed the vault and threw away the key when they shut down their developer program in 2021-ish. Unfortunately for me, I was not a member of the program so I never got to see their docs back in the day.

Anyway, hope that helps you understand more of how things work under the covers so to speak.

I think that may be due to your ST-10 being a first generation device. I believe all of my ST-10’s are of the latest generation (not sure though, as it’s just a serial number), and they can play https url’s and TTS messages just fine. I thought I read somewhere in a forum that there is a time limit on earlier generation devices that limit the time (or size maybe) of the url being played.

btw, play_info is used to play TTS messages, as they are simply a call to the google translate service, which returns a response of the MP3 file that is generated for the text message.

Hi Todd

For the toggle function, I have a script solution for now which is working well. See below.

soundtouch_toggle_join:
  alias: SoundTouch Toggle Join
  fields:
    master:
      description: Master of the group
      example: media_player.soundtouch_kitchen
    slave:
      description: Slave device to be joined to the Master group
      example: media_player.soundtouch_dining
  sequence:
    - if:
        - condition: state
          entity_id: "{{ slave }}"
          state: "off"
      then:
        - service: media_player.join
          target:
            entity_id: "{{ master }}"
          data:
            group_members:
              - "{{ slave }}"
      else:
        - service: media_player.unjoin
          target:
            entity_id: "{{ slave }}"
          data: {}
  mode: single

@jasebob I added the Toggle Zone Member service that you suggested with release v1.0.25; I just pushed it out a couple of minutes ago.

The service toggles the given zone member to or from the master device’s zone. A new zone will be created automatically if needed.

Note that you have to issue the call to the media_player that is the MASTER of the zone.

Example - The following will toggle the bose_st10_2 zone member in the master zone controlled by bose_st10_1:

service: soundtouchplus.zone_toggle_member
data:
  entity_id_master: media_player.bose_st10_1
  entity_id_member: media_player.bose_st10_2

Let me know how it works for you.

OK Cool and thank you.
I’ve gone away for a couple of days, so I will try it over the weekend.

Perhaps this should really be a media_player function, calling join / unjoin. I wonder what would happen if you built a pull request to the base class? :slight_smile:

Hi Todd

I’ve upgraded to 1.0.26 and confirmed ZoneMemberToggle works well. Thanks!

I mostly have the preset and recent list stuff working too. All except for the recent list. The recent list service call is not returning the album art as a containerArt attribute. Its just missing in the retuned data. This does appear in the dictionary for Get Preset List and works well.

Here are the first two items I get back from Get Recent List.

recents:
  recent:
    - "@deviceID": F45EAB5367D7
      "@id": "2453655922"
      "@createdOn": "1703974731"
      "@SourceTitle": Spotify (**********@gmail.com)
      ContentItem:
        "@source": SPOTIFY
        "@type": tracklisturl
        "@location": >-
          /playback/container/c3BvdGlmeTpwbGF5bGlzdDozN2k5ZFFaRjFFMzdNY1JyaTNjMWQy
        "@sourceAccount": *****************************
        "@isPresetable": "true"
        itemName: Daily Mix 1
    - "@deviceID": F45EAB5367D7
      "@id": "2481184716"
      "@createdOn": "1703974711"
      "@SourceTitle": Spotify (*****************@gmail.com)
      ContentItem:
        "@source": SPOTIFY
        "@type": tracklisturl
        "@location": >-
          /playback/container/c3BvdGlmeTphcnRpc3Q6NmVVS1pYYUtrY3ZpSDBLdTl3Mm4zVg==
        "@sourceAccount": ********************************
        "@isPresetable": "true"
        itemName: Ed Sheeran

Do you use your ST10s as a stereo pair? How do you integrate them?
At the moment I only added one device to soundtouchplus and that seems to work just fine - except for the reboot service call. This only re-boots one of the two units.
I am wondering if you should automatically reboot the stereo pair, or tell people to add both devices?

@jasebob - I have not been able to test with Spotify, as I only have a free account; you have to have the premium level in order to add the Spotify music service to the device. With that said, forgive my 20 questions …

  1. Are all of the recent items that do not contain the cover art from the SPOTIFY source?
  2. Can you issue the following two commands from a desktop browser - make sure you are playing a track from the Spotify source on your device when you do. Change the IP address to your SoundTouch device IP address:
    http://192.168.1.131:8090/nowPlaying
    http://192.168.1.131:8090/recents
    Can you send me the output of those in a private message? I’m looking for anything in the results that looks like a url to a cover art image. All of the sources I have been able to test with return the artwork url in the containerArt node of the contentItem parent node of the recent list. That may not be the case for Spotify, but I am not sure as I have never been able to test with it.

I have used my ST-10’s as a stereo pair, but have them both added to HA as separate devices. If memory serves, the first device controls both devices though when SoundTouch WebService API calls are issued. Note that will not apply to the reboot function though, as the reboot is performed via a call to the SSH service on the device (not SoundTouch WebServices API). You would need to manually issue a call to the reboot service for the second device in order to reboot both devices.

I know when I have mine as a stereo pair, it automatically changes the device name that initiated the pair request (e.g. the main device) to something like ST-10-1 + ST-10-2, instead of keeping the ST-10-1 name. The main device seems to send commands to the paired device to keep them in sync after that, but again only SoundTouch WebService API commands (not SSH server commands).

Hi Todd

Yes, everything is Spotify for me and I have a premium family account. My preset selections are also all Spotify and they are working.

So
/nowPlaying returns a containerArt tag as part of the ContentItem and it has a nice URL.
/presets does the same, with a containerArt returned in the XML
/recents does not. The contentItem only has a itemName tag. The XML is actually quite short and the only thing remotely like a path is the location field of the ContentItem which is the referring to the Spotify path to play the track.

What do you get in the dreaded Bose Phone App?
When I go to recently played in there all the items have a generic Spotify icon.
Whereas when I click on the presets each item has a piece of album art.

Perhaps I can also help you figure out the station list for Spotify. I can’t get this service call to work

@jasebob Ya, same here … in the SoundTouch App, all of my recently played items are set to generic icons for ALL sources (Pandora, TuneIn, etc). I get the same results when I generate the list from the device using the http://192.168.1.131:8090/recents call as well. Presets are still fine though, just like yours.

This tells me that the Bose SoundTouch device is removing the cover art from the recent list items! I have no idea why it does that - maybe to conserve space as some image url’s can be quite long? Maybe it’s due to the fact that most image art url’s are from a CDN source, and are temporary in nature; e.g the device verifies the image url’s before returning them in the recents list, and they may no longer exist since they are on a CDN source? Maybe they remove them due to copyright / digital licensing rights? Not sure on that one.

Here’s my recent list now (it was fully populated with artwork yesterday) - the Zach Williams cover art is due to me playing that Pandora station today.

As it happens, I did receive a free 90-day trial offer from Spotify for a premium account a few days ago. I think I will get signed up for that, and try to figure out the station list navigation at least.

Wish I had better news on the recents list.

I just played something off of Tunein. Bingo! There is the containerArt which missing from a Spotify entry. So its definitely related to Spotify.

<recents>
<recent deviceID="000C8AC06D11" utcTime="1703995767">
<contentItem source="TUNEIN" type="stationurl" location="/v1/playback/station/s34804" sourceAccount="" isPresetable="true">
<itemName>KQED-FM</itemName>
<containerArt>http://cdn-profiles.tunein.com/s34804/images/logog.png?t=637231950230000000</containerArt>
</contentItem>
</recent>

So the really nasty solution is to Cache the ContainerArt and match it to the location string. But that needs non-volatile storage for the integration and would be a lot of work.

I just changed the recent selections from a picture-entity to a button card.
Its not as pretty but is very functional and gives access to all the recently played list.

So, in your example code replace

        'type': 'picture-entity',   
        'entity': 'input_boolean.always_enabled_helper',
        'image': itmContainerArt,   
        'show_state': false,   
        'show_name': true,  
        'name': itmItemName,   

with

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

This could be made prettier with the custom-button card so that the buttons are rectangular and better suited to a line of text.

@jasebob Nice - I added the button example to the wiki.

I was able to sign up for the free 90-day trial of Spotify Premium-level membership, so will keep you posted on what I find.

I updated the Play Content Item service examples with the various Spotify types (album, artist, etc), if you want to have a look at that.

@jasebob Regarding the Bose Developer Portal from back in the day … you didn’t happen to see (or pull) anything from there besides the Bose SoundTouch API Reference.pdf that you posted a few weeks ago did you?

I know it’s a long shot, but I am specifically looking for anything related to navigate or search services. These are the 2 services that I currently use to pull information from other Music Services that I have researched thus far: Pandora, Local Music, and NAS Server Music.

I am hoping that Spotify is accessed the same way, but I cannot figure out the XML request to query Spotify. I am wondering if they scrapped support for those when they started supporting the “Spotify Connect” methodology.

Any thoughts?

Hi Todd

Happy new year!
No, I didn’t grab anything else.
Perhaps this is what you are thinking, but it would be nice to pull down playlists and favorite lists from music services and then arrange them in the same data structures to display them as selection pages.
The Bose phone app has a nasty Spotify interface and it still works today. It can search and find songs / artists / albums. It might be a good app to trap the traffic from.