[Nearing Release] Sonos Advanced Controller

Hi @daniel.winks,

I've run into a bit of a roadblock with 'Get Favorites' and 'Load a Favorite' – they don't seem to be functioning for me at the moment. Additionally, I've noticed that the "currentFavorite" isn't appearing in the Current States of any of my devices. I've already updated to the latest version and followed the steps of opening the Virtual Players, selecting 'next,' hitting 'done' in the Cloud Sonos App, and in each device, I've gone through the motions of 'Configure,' 'Refresh,' and 'Subscribe to events.'

Is there something else on the checklist that I might be missing? Any guidance would be highly appreciated. Thanks! :blush:

New bundle on GitHub.

Fixes a few things related to favorites, namely for favorites that don't have "resource" data associated with them (nothing I can control, that's just how some favorites come in from Sonos). These favorites will still display on the UI when clicking "getFavorites" and you can put in their favoriteId and they'll play, but without 'resource' info from Sonos, there's no way to match them up with the data from "currently playing" to know that these particular favorites are currently playing. Any favorite that Sonos provides 'resource' info on from their API should be able to be matched up and displayed as "currently playing favorite".

I also added a "loadFavoriteFull" command, which gives all of the available options for loading a favorite, such as how it is loaded into the queue (append, replace, insert, etc), whether it starts playing automatically, what repeat mode it is added with, and whether it has crossfade on. "loadFavorite()" works as it did before. When I first added "loadFavorite()" it was to suit my personal needs, and it has hardcoded values for "replace" queue, "repeat one", and "crossfade on", and "autoplay", since I only use it for starting a bedtime sleep sound track.

Since others may want to have it "append", not start auto playing, or have different repeat modes set, I've added a new command that allows for the selection of all the available options.

1 Like

Quick tutorial on running "loadFavoriteFull()" from Rule Machine, since it's got quite a few parameters.

I've added overloads for the method, allowing for the passing of only as many needed parameters as necessary. This means when you select "Run Custom Action" you don't have to specify ALL of the parameter available, just the ones you need. However, Rule Machine doesn't allow passing "named parameters", so you must specify them in the order they appear in the UI. This means if you want to specify "queueMode", you must first specify a "repeatMode".

First select "Run Custom Action":

Next you need to specify the parameters you want, in the order specified in the driver. You can view the order of the parameters by looking at the command button on the device driver:
image

So you can specify them like this in Rule Machine. First you specify the "favoriteId":

If you now specify no other parameters, it'll run this action with "repeat all", "replace", "off", "true", and "on" specified for all the other parameters (as show on the device driver UI, screenshot above).

As stated before, if you wanted to load favorite 14, and have it "append", you must first specify the "repeat mode" as that is the next parameter on the command. So to "load favorite 14 and have it append to queue", you'd need to specify 2 parameters, the repeatMode and the queueMode:

I've placed these parameters in what I think is the most logical order, based on what would likely be the most commonly desired parameters to control. I figure most people would want crossfade on, and would want to specify control over it least often, it's ordered last. Same for "autoPlay". It defaults to "autoPlay = true" since it avoids needing to tell the player to start playing. As such, it defaults to "on", and is placed second to last in the parameter list.

To specify all parameter available, add more parameters in Rule Machine like this:

Again, they must be in the order of "String favoriteId, String repeatMode, String queueMode, String shuffleMode, String autoPlay, String crossfadeMode". You can optionally omit them, but you may not skip any. So to specify "queueMode", you have to first specify "repeatMode", and you may omit anything following queueMode and it'll use the defaults.

When specifying parameters in Rule Machine, they are all "string" values, and the exact string needed can be viewed in any of the drop downs from the Device Driver UI:
image

1 Like

Daniel,

A question about 'favorites'. These appear to be whats known in the Sonos Ui as "My Sonos Stations". In the Cloud Players, if I do a Get Favorites, returned data displayed in the Player UI is 3, 5, & 6. Channel 0, and 4 are never shown. 1 & 2, don't appear to exist. I expect I added some to My Sonos Stations in the past, and subsequently deleted them.

Anyway, is this expected behavior?

S.

I think so. It doesn't seem like Sonos reuses the numbers from deleted stations/favorites. I've got a bunch of "gaps" in my numbers as well.

1 Like

Over the years I've added and deleted any number of stations and playlists to and from my favorites. Currently, any new favorites will have ID numbers over 600. With a hard limit of 70 favorites, I of course have gaps all over the place.

I've been following this closely and it looks to be a great addition.
I've been holding back on taking the plunge hoping it will be integrated into HPM.
This will make life easier for any updates etc. that may happen.
Are you considering integrating with HPM?
If not, I'll download and have a play.

Many thanks and keep up the great work. :+1:

I looked into HPM, and it doesn't work with libraries. There's some hack to put them inside a bundle, then add the bundle... but that doesn't work since the HPM developer utility doesn't allow adding bundles... So I probably will, but not until I have the app finished. It's just not worth trying to deal with the hassles of HPM until then.

I'm hopefully having a major revamp coming out this weekend anyway... with everything moved to LOCAL methods. I'm renaming it to Sonos Advanced Controller since it'll no longer actually be "Cloud". I've got about half of the commands moved over to local control. The "Add Player" code has all been re-written to use SSDP, too, so it works locally. Also working on putting @CompileStatic on everything I can so it runs faster.

5 Likes

Thanks for the swift reply.
I'll hold off for a few days.
It's no big issue not having it in HPM it just makes life easier for a lazy git like me.... :wink:

You are doing an awesome job with this. Do you sleep at all? :wink:

Keep up the stirling work. :+1:

Hey @Daniel.winks

I just wanted to share my enthusiasm for HPM; it's been a game-changer for me. The ease of installing, repairing, and uninstalling is a real time saver, not to mention those handy notifications for updates. :star2:

I get that libraries can be a bit tricky when used with HPM, but here's a suggestion: why not reach out to @tomw, who built Broadlink IR/RF remote integration? I believe this app uses HPM and libraries. Maybe there is some lesson learned to be shared. Hope this helps you in some way!

Looking forward to Sonos Advanced Controller!

Yeah, I noted that the ESPHome app also uses libraries in HPM via Bundles.

I'm sure I can get it figured out, and I'll toss it all into a GitHub action too, so I don't have to manually do anything. Right now my bundles are built that way.

There's no point in putting "Sonos Cloud Controller" on HPM at this point since I'm doing a near complete re-write and rebranding it "Sonos Advanced Controller". I've got around 80% of everything using local control at this point. Just working on the grouping/ungrouping stuff and it'll be ready to beta. Not much point in it being named something with "Cloud" in it when there's no longer any Cloud utilized.

Some other big improvements are that it will use far less persisted state and instead query things as needed, which should resolve some issues with the grouping/ungrouping. Also adding controls for bass, treble, and loudness, among a few other additions.

I've also found a ton of bugs that all seem to stem from people using some but not all of their speakers in the app. My current code would assume that every member in a group could be resolved to a device in Hubitat, which isn't the case if someone doesn't have a particular speaker added to the HE app. In these cases, it would get a null value and cause a ton of errors.

I've only ever used this personally with all of my speakers added in HE, but I recently picked up a Sonos Roam, and it wasn't added in HE, and I noted a bunch of null exceptions and tracked down the cause. So the new code will instead query the coordinator itself for its group members and use that instead, which works even if the group members aren't all added to HE as 'Sonos Advanced Player' devices.

1 Like

So I have a Roam now, and I noted this too. There's two options in the System menu for the Roam, for "Battery Saver" and "WiFi Power Save", which are enabled by default. Turning those both off seems to have the Roam act like any other Sonos in terms of grouping etc. With them on, I'd add it to a group and it'd show in the group on the official Sonos app and it would just not actually play anything, among other oddities. Turning those options off resolved all that, for what it's worth.

Just wish the Roam was a bit bigger. It's nice and portable, but I don't want to spend $450 on a Move. Maybe Ikea can come out with a $150 approx battery Sonos that's got a bit bigger drivers and battery.

Still, for a "working in the basement/yard" speaker, the Roam will work nicely. Broke the screen protector on my iPhone last summer using it in the yard with a cheapie BlueTooth speaker... with voice control on the Roam I can just drag it around and not need my phone. Lucked out that it was just the protector and not the screen too, since it fell on a rock.

1 Like

Hey Daniel.Winks,

Absolutely on board with the decision to wait for the local transition to be completed before the migration HPM, especially given the upcoming changes. I'd even go so far as to recommend waiting for Sonos Advanced Controller to hit public beta before making the move to HPM; I'm sure there'll be a few hurdles to navigate.

It's fascinating to follow your journey into the realm of local control, and I can't wait for the day when we have a seamlessly functioning Sonos system under local command (except for those Stream Radio station connections, of course).

This Sunday might just free up a bit for me to delve into some testing, and Monday is looking promising too. Given the challenges we've both faced in our setups, it seems like the perfect testing ground. Count me in if you need an extra pair of hands for some advance release testing!

Super pumped about integrating the app into my home production environment full-time. :star2:

Happy Local recoding!

4 Likes

Hi @daniel.winks
I thought I'd give this a go. Here is where I'm at'
I've created a developer account OK and got my Client Key and Client Secret.
I've downloaded 3 files into the library.
I've downloaded the Apps code and OAuth'd it.
I've downloaded 2 driver codes.
I then installed the app and went through the set up by connecting up to my user account and it says my account is connected.
Next I discovered my devices OK (2 of them).
At this point should it define these devices in my device list. I'm not seeing anything new defined.
I do already have them defined using the inbuilt Sonos Integration.
When I click on 'Sonos Virtual Group Devices' I receive this error.

[app:12645](http://192.168.0.24/logs#)2024-01-06 18:40:46.546[error](http://192.168.0.24/logs#)org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '[]' with class 'java.util.ArrayList' to class 'java.util.Map' due to: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: java.util.Map() on line 409 (method groupPage)

I'm obviously doing something wrong so I was wondering if you could point me in the right direction.
Many Thanks, Bob.

Hey, all new version should be out soon... it doesn't use ANY of that cloud stuff, so there's no need for client key, secret, OAuth, and of that.

Also has a lot of improvements to the player creation and group creation pages.

Give me a bit here and I'll get it posted.

2 Likes

OK thanks.
I'll hold fire until you release your updates.
I'm in no hurry as I have Sonos working up to a point but it is very basic.
I'll go back to my beer and the football (soccer to some). :wink:

Alright everyone, big new release.

First, ALL cloud-related stuff is removed, as everything works locally now. I'm renaming this to "Sonos Advanced" as there's no longer anything "Cloud" about it.

Second, Group Devices have been improved with "switch" capability, and accurately reflect whether the group is "on" or not. I'm working on an improvement to how "Group Players" works, too. Presently, it creates an all new group, with no stream playing. I'll leave this in place as-is. "Join Players To Coordinator" does just that, joins them without interrupting any stream on the coordinator. Also leaving that as-is. But I'm working on a new button, name TBD, that will group all the players together into a new group, and if and only if there's a single stream playing on any one of the players, bring that stream into the new group. If there's 2 or more of the "follower" devices playing, then there's no real way to know which stream to pull in, so in those cases I'll just have it not pull one in.

So if you have "bedroom" and "living room" as a Sonos Group device, with living room as coordinator, and the living room speaker is idle, but the bedroom speaker has a stream playing, there will be a command that will pull them into a group with living room as coordinator still, but rather than being an all-new group with no stream, or having the (non-existent) stream from living room, it'll snag the bedroom stream and move it to the living room when it becomes coordinator.

Similarly, I'll be adding a "Split Group" button that takes whatever stream is playing and starts it playing on each of the members of the group, but with them being a stand-alone coordinator of their one-device "group".

Well, at least I'll add these if functionally it's possible. I'm like 95% sure it is, but I haven't actually dug into it. But it's the next thing I have planned.

I've set up everything on my end for HPM integration, just waiting on my pull request to be approved and merge my repository into the official repository list. In the meanwhile, you can manually add it as a custom repository using this link.

I've also added support for setting bass, treble, and loudness. Looking into being able to set some of the Arc/Beam specific stuff too, as they have a few extra config settings for home theater related stuff. Namely, I want to automate turning "Night Sound" and "Speech Enhancement" on and off. I haven't found where the UPnP control for this exists, if at all, so it'll take some investigation.

I have zero idea whether or not you can in-place upgrade the code... I've got 2 Hubitats, and on my main one, I've only ever had iterative updates as I program things, and on my "testing" hub, I've only tested the all-new all-local version from a "fresh" install via HPM. That said, the way the app works in regard to child devices and their DNIs hasn't changed since I added "current state" a long while back, so it'll probably be OK to update the app/driver code from the old "Sonos Cloud" stuff to the new "Sonos Advanced" ones. But if it doesn't work, then the only thing I can really suggest is just adding "Sonos Advanced" side-by-side to the old app and moving any Rules and stuff over to the new child devices.

This new version uses all-new drivers, and a new app. The old "Sonos Cloud" ones are left in place on GitHub, so if you want to manually upgrade, you'll want to copy/paste in the code from the new drivers and app into your current app and driver code and overwrite it.

Or install the new one side-by-side and move things over... that's probably safer.

Edit: Also forgot, "current state" also now includes "currently playing" album art. Yippie.

5 Likes

So "bundles" are easy to remove. Just click on "Bundles" on the left side of HE, click on the bundle, and at the bottom is a "Delete" button. I don't think deleting a bundle removes any of the libraries, apps, or drivers the bundle installed. So you'll want to go through each of those one by one and remove them, too.

Ok thanks for the headups!

Perhaps a stupid question, but can this work well side by side with the built in app?
Want to make sure playing with this doesn't disrupt my current automations using the built-in version.