Calling Sonos users

General HouseBot discussion. Any issues that don't fit into any of the other topics belong here.
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: Calling Sonos users

Post by Osler »

As an update, I have been using Sonos via HouseBot for several days since moving to version 3.2.

Remember, issues with network topology are usually uncovered after a Sonos update. I uncovered a bad network cable on one of my ZonePlayers after a prior update. There may be an issue with a switch or a network cable somewhere that could be causing your problems.

Osler
vcruz777
Member
Posts: 70
Joined: Sun Jul 08, 2007 9:39 pm

Re: Calling Sonos users

Post by vcruz777 »

Now is working fine although I am still having issues getting the album art and queue size. I included in the script a workaround for them. For the album art I included some logic to look for the album art in the server HD (the files used when browsing the library) and it works OK. After some troubleshooting I finally found two viruses in the server that were causing some of the problems reported before, like the high CPU usage with the Services.exe process. So it looks OK. Thanks a lot for your responses.

Saludos,

Victor
dkarthur
Member
Posts: 2
Joined: Fri Aug 13, 2010 10:01 pm

Re: Calling Sonos users

Post by dkarthur »

Hi Osler,

Over the last week or so I have been reading this thread and a similar one at the Sonos forum regarding your wsc library. You've done an excellent job with the housebot automation - and it looks like you are truly the guru of Sonos uPNP! Congratulations!

I have been messing around with some of the functionality you have surfaced in this using Delphi [with a view of creating a neater controller program for myself - I really don't like the Sonos provided one] and I am in desperate need of a bit of a heads up on how one of the particular interfaces work. I have looked at your example vbs script to try and figure some things out but with no joy. I have also tried to review the "Sorority" source but again with no singificant joy.

Basically my query revolves around the "browse" interface. I understand how this works if you just want to download all albums or all artists or all tracks but I don't quite understand how this works for a restricted type browse. For instance if I want all the albums for a particular artist - or all the tracks for a particular album. I think there are two possibilities in that either somehow the container parameter is manipulated (like a directory path) or the filter parameter is manipulated with an expression. I am guessing it's the first but I can't quite see how it works... Similarly I am wondering how browse is used to search - for instance to return all artists/tracks/albums that contain a particular string ...

If you could give me a heads up with some basic code examples or point me in the right direction of some doco it would be much appreciated ..

Cheers

Dave A
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: Calling Sonos users

Post by Osler »

dkarthur:

It has been a while since I coded the browse function, so there may be some mistakes in what I am telling you; however, we can work through it.

The main container for all of the indexed tracks on a ZP is A: (structure is similar to a directory as you suspected). If you browse the DirectChildren of A:, what should return is the following:

A:ALBUM
A:ARTIST
A:ALBUMARTIST (I think)
A:GENRE
A:COMPOSER
(there may be more, but I think these are the ones)

Now, if you browse the DirectChildren of A:ALBUM, a list of all available albums should be returned. Go one deeper and all the tracks for the album should return (i.e., browse A:ALBUMS/License to Ill will return all the tracks for this truly wonderful album from the Beastie Boys). Likewise, browsing A:ARTIST should return a list of all artists. Go one deeper and all of the albums for the artist will be returned. One deeper still and the tracks for that artist's chosen album will be returned (A:ARTIST/Beastie Boys/License to Ill). These browse terms need to be properly escaped as well in order to browse or pass it to the ZP to play it (i.e., A:ARTIST/Beastie%20Boys/License%20to%20Ill). Also, there may be a limit as to the number of items that can be returned at a time. I think I hit a barrier at 121 items so you may need to keep track of where you are in the browse list and use the index feature of the browse function to scroll through all of the items available.

If you browse S:, I believe this returns all of the tracks that are available in alphabetical order. Browsing R: gives what remains of the internet radio functionality that is stored locally on the ZP (outside of what they now do with RadioTime).

I have implemented the powerscroll feature, but not the search functionality. I can help with the former when you get the above accomplished.

I distinctly remember coding my browse subroutine and it was a definate pain to get working correctly, FYI.

Osler
dkarthur
Member
Posts: 2
Joined: Fri Aug 13, 2010 10:01 pm

Re: Calling Sonos users

Post by dkarthur »

Hi Osler,

Thanks for your really prompt reply - much appreciated.... I just need some time now to mess with it (send the wife and daughter out shopping for a few hours!)...

I'll let you know if I have any issues with that .. but it looks very straightforward .. I should have just tried it .. but I didn't see any bits of source do a straight browse of A: - all the examples all seemed to start at A:ARTISTS or similar .. so I didn't really twig that A: was the root of a simple hierarchy. Bit embarassing really .. oh well ..

Anyway - when I work through that I'll make contact again re the search function... Thanks for your offer.

Cheers + Many Thanks again!


Dave A
supermangesthlm
Member
Posts: 7
Joined: Tue Aug 31, 2010 5:48 pm

Re: Calling Sonos users

Post by supermangesthlm »

Olster,

Let me first say THANK YOU MAN, YOU ROCK! The stuff here is GOLD!

I’m a long time lurker (feb/mars) coming from the sonos-forum and i finally got things working earlier tonight. (Having overcome the “register error” on my 32bit win7 - If anyone is interested i can write a step-by-step). I’m not a hard core coder and i don’t think that i want to get HB running.. but this is what i want to do:

I want to spread inexpensive RF-remotes around the flat, (Basic 4-way light switches – “nexa” in Sweden - https://www.m.nu/images/gt-216.jpg) have them talk to my eventghost setup via a receiver I have and then control the zones that way.. (IE I know what zone I’m in as I can “hardcode” each switch to a zone). (Guessing the Potato dude is probably gonna try to convert me to xAP and convince me that that is the ultimate swiss-army-knife of HA.. but I like things simple and wife compatible..

PROBLEM: I seldom listen to music in the bathroom as I usually forget to bring a sonos remote.. now if I had a (hidden) RF-switch, the flick of a few buttons would allow me to shave to my fav pl or radio station..

This is all I want to do, I don’t need album art displayed somewhere.. I don’t need to search my MP3 tracks etc. (I can use sonos software to build PL etc).

The new proposed “ToggleSource” feature:
1. Say I dumped all current Sonos-Playlists and all current favorite Radio stations a similar way that you dump the zones
2. Say that you could have ZPCMD start playing one of those (on the next toggle cmd play the next etc)

Q: So, is there any way for you to find it in your heart to add some features to ZPCMD to allow:
ZPCMD /uuid:_.._
"/TogglePause"
Get the state of the Zone, and change it.
"/ToggleMute"
Get the state of the Zone, and change it.
"/Vol+n"
Get the volume of the Zone, and increase volume n “units”
"/Vol-n"
Get the volume of the Zone, and decrease volume n “units”
"/ToggleSource" | "/ToggleSource:DaddysPlaylist;MomysPlaylist;FavoriteRadiostation1;FavoriteRadiostation1"

(also ToggleSonosLED/TogglePlaymode not as important but still (and naturaly only one of mute/pause is)

EDIT:
"/PlaySource:DaddysPlaylist"
could also be usful..
(or "/PlayTrack:'Brass Monkey'")
((or "/PlayTrack:'doorbell.mp3'"))
but i dont want to ask for to much.. :)

Guessing that i can come close to 75% of theese featurs with enviorment vars in my .bat-files.. except source.. but that would not be the same as state can change without EG knowing..)

Keeping fingers crossed..

//Mange
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: Calling Sonos users

Post by Osler »

You can do all the things you are asking with simple scripting. Simply write the script and the pass the script as a command line parameter to cmd.exe. This would be much more flexible for you to do than have me change ZPCMD.exe (the location of the source code for which is uncertain at this time due to a recent HD failure).

Please see this post as it provides some very good examples for nearly precisely what you are asking:

http://forums.sonos.com/showthread.php?t=7733

Also, see this post. The code for connection needs to be changed in these older scripts to comply with the (relatively) newly implemented asynchronous find function:

http://forums.sonos.com/showthread.php?t=17334

If you have any questions or need any help working through the scripts, let me know and I'd be happy to help.

Osler

EDIT:
Yes, any tips and tricks you can provide for Win7 would be greately appreciated by the community.

EDIT2:
The only reason I responded to you was because you wanted to have 'Brass Monkey' available at the touch of a button in the loo..... :D
supermangesthlm
Member
Posts: 7
Joined: Tue Aug 31, 2010 5:48 pm

Re: Calling Sonos users

Post by supermangesthlm »

Im looking in to it right now, will follow up with questions.. defenetly.. having looked at ZonePlayerController.wsc a bit closer im guessing the i should look at: GetMuteState, SetMuteState, GetVolumeLevel, SetVolumeLevel.. however, how do i start a sonos playlist? or a fav radiostation...

Steps that worked for me to get ZPC working:
1. DL stuff from pg 1
2. unzip to where ever you want it
3. start elevated cmd.exe (right-click run as administrator)
4. cd your way to wherever you have ZonePlayerController.wsc
5. type: "C:\Windows\System32\Regsrv32.exe ZonePlayerController.wsc"
6. cd your way to wherever you have ZonePlayerFinder.wsc
7. type: "C:\Windows\System32\Regsrv32.exe ZonePlayerFinder.wsc"
8. Done & Done!
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: Calling Sonos users

Post by Osler »

Starting a specific song, radio station, or non Sonos playlist will be a bit more complex. Work through the more basic things like mute and incremental volume increase and I will help you with the ability to toggle through "sources". Playing a Sonos playlist should be as simple as this:

Code: Select all

ZonePlayer.PlaySongNow("SQ:1","")
The above code should play the first saved queue. Individual tracks or external playlist will be a bit more complex to get the URI that needs to be passed, but will still use the above code.

Post your scripts!!

Osler
supermangesthlm
Member
Posts: 7
Joined: Tue Aug 31, 2010 5:48 pm

Re: Calling Sonos users

Post by supermangesthlm »

EDIT, new code... hehe..

Code: Select all

'MR Clean:
Option Explicit
Dim ZonePlayer
Dim objArgs
Dim strArg 

Set ZonePlayer = CreateObject("ZonePlayer.Controller")
ZonePlayer.Connect("RINCON_000nnnnnnn00")
Do Until ZonePlayer.Online = True
	WScript.Sleep 20
Loop

Set objArgs = WScript.Arguments
For Each strArg in objArgs
	if UCASE(strArg) = "MUTE" then CALL ZonePlayer.SetMuteState("Master", True)
	if UCASE(strArg) = "UNMUTE" then CALL ZonePlayer.SetMuteState("Master", False)
Next 

'CALL ZonePlayer.PlaySongNow("SQ:1","") 'This still dont work thou...
ZonePlayer.Disconnect
Set ZonePlayer = Nothing
So, how do i receive stuff from "GetMuteState" - set a string?
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: Calling Sonos users

Post by Osler »

Try this:

Code: Select all

'MR Clean:
Option Explicit
Dim ZonePlayer
Dim MuteStatus

Set ZonePlayer = CreateObject("ZonePlayer.Controller")

ZonePlayer.Connect("RINCON_000nnnnnnn00")

Do Until ZonePlayer.Online = True
   WScript.Sleep 20
Loop

'the following code will create a mute toggle effect depending on the current zoneplayer state

MuteStatus = CStr(ZonePlayer.GetMuteState("Master"))
If MuteStatus = "True" Then
     Call ZonePlayer.SetMuteState("Master", False)
ElseIf MuteStatus = "False" Then
     Call ZonePlayer.SetMuteState("Master", True)
End If

ZonePlayer.Disconnect
Set ZonePlayer = Nothing
I need to look at passing URIs as I haven't written code for this in quite a while. The SQ:1 may need to be preceded by "x-rincon:", "x-file-cifs:", or something similar. I can't answer that at the moment as I am working off of memory.

Osler
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: Calling Sonos users

Post by Osler »

Ok, my fault with the SQ: business. That is only for browsing the saved playlists. The following code should get a saved playlist going for you:

Code: Select all

Option Explicit
Dim ZonePlayer
Dim PlaylistPath
Dim PlaylistNumber

Set ZonePlayer = CreateObject("ZonePlayer.Controller")

ZonePlayer.Connect("RINCON_000nnnnnnn00")

Do Until ZonePlayer.Online = True
   WScript.Sleep 20
Loop

Call ZonePlayer.ClearQueue()

PlaylistPath = "file:///jffs/settings/savedqueues.rsq#"
PlaylistNumber = "1"

Call ZonePlayer.AddSongToQueue(PlaylistPath & PlaylistNumber, "")

Call ZonePlayer.SetTransportState("Play")                   

ZonePlayer.Disconnect
Set ZonePlayer = Nothing
Sorry for the misinformation.

Osler
supermangesthlm
Member
Posts: 7
Joined: Tue Aug 31, 2010 5:48 pm

Re: Calling Sonos users

Post by supermangesthlm »

Code: Select all

'MR Clean:
Option Explicit
Dim ZonePlayer
Dim objArgs
Dim strArg 
Dim connectiontimer
Dim MuteStatus

Set ZonePlayer = CreateObject("ZonePlayer.Controller")
ZonePlayer.Connect("RINCON_000[WHY_IS_THIS_NUMBER_SO_SECRET]00")
connectiontimer = now()
Do Until ZonePlayer.Online = True
	WScript.Sleep 20
	'WScript.echo "."
Loop
connectiontimer = connectiontimer & chr(13) & now()

Set objArgs = WScript.Arguments
'Main loop..
For Each strArg in objArgs
	SELECT CASE UCASE(strArg)
	CASE "MUTE":
		CALL ZonePlayer.SetMuteState("Master", True)
	CASE "UNMUTE":
		CALL ZonePlayer.SetMuteState("Master", False)
	CASE "TOGGLEMUTE":
		MuteStatus = ZonePlayer.GetMuteState("Master")
		If MuteStatus = -1 Then
		     Call ZonePlayer.SetMuteState("Master", False)
		ElseIf MuteStatus = 0 Then
		     Call ZonePlayer.SetMuteState("Master", True)
		End If
	CASE "STARTPLAYLIST":
		Call ZonePlayer.AddSongToQueue("file:///jffs/settings/savedqueues.rsq#1", "", "", True)
		Call ZonePlayer.SetTransportState("Play")

	END SELECT
Next 

CALL ZonePlayer.PlaySongNow("SQ:1","")
ZonePlayer.Disconnect
Set ZonePlayer = Nothing

'WScript.echo connectiontimer
I got somethings running now... will code more during the day...problems so far:
  • 1. Connection time... aboute 10 secs... that dont feel like realtime.. anything we can do aboute that? (i have no problem w/ network trafic..) can I have the connection open for like longer... or does it die w/ the object... ?
  • [DONE]2. Need to clear the que before doing "STARTPLAYLIST"... otherwise it just builds...
  • [DONE]3. cstr returned False in my local language so it seems that it returns 0 or -1..
  • [DONE]4. had to add 2 inputargs to AddSongToQueue
  • 5. Need to find more time to code...
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: Calling Sonos users

Post by Osler »

Code: Select all


'MR Clean:
Option Explicit
Dim ZonePlayer
Dim UDN
Dim objArgs
Dim strArg 
Dim connectiontimer
Dim MuteStatus

Set ZonePlayer = CreateObject("ZonePlayer.Controller")
UDN = "RINCON_000[WHY_IS_THIS_NUMBER_SO_SECRET]00"
ZonePlayer.Connect(UDN)       'the UDN is used for linking so put it into a strvar so you can manipulate it later
connectiontimer = now()
Do Until ZonePlayer.Online = True
   WScript.Sleep 20
   'WScript.echo "."
Loop
connectiontimer = connectiontimer & chr(13) & now()

Set objArgs = WScript.Arguments
'Main loop..
For Each strArg in objArgs
   SELECT CASE UCASE(strArg)
   CASE "MUTE":
      CALL ZonePlayer.SetMuteState("Master", True)
   CASE "UNMUTE":
      CALL ZonePlayer.SetMuteState("Master", False)
   CASE "TOGGLEMUTE":
      MuteStatus = ZonePlayer.GetMuteState("Master")
      If MuteStatus = 0 Then
           Call ZonePlayer.SetMuteState("Master", True)
      Else
           Call ZonePlayer.SetMuteState("Master", False)
      End If
   CASE "STARTPLAYLIST":
      Call ZonePlayer.ClearQueue()
      WScript.Sleep 250
      Call ZonePlayer.AddSongToQueue("file:///jffs/settings/savedqueues.rsq#1", "", 0, True)
      WScript.Sleep 250
      Call ZonePlayer.SetTransportState("Play")

   END SELECT
Next 

ZonePlayer.Disconnect
Set ZonePlayer = Nothing

'WScript.echo connectiontimer

Not sure about your connection times, but when I execute using scripts it is nearly instant. All of my ZPs are wired, though.

Make sure to change the parameter in AddSongToQueue from an empty string to an integer (0 in this case...see above).

I added some pauses between back-to-back commands (250 ms), as I have found this helpful in the past.

Osler
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: Calling Sonos users

Post by Osler »

Since you are not concerned about reconnecting a ZonePlayer to the script if it goes offline (i.e., your script isn't persistent), I have added back the original synchronous connection function for you to use. The function is "ConnectSynchronusly" and takes the UDN as an argument.

Code: Select all

Dim ZonePlayer
Dim UDN
Dim objArgs
Dim strArg 
Dim connectiontimer
Dim MuteStatus

UDN = "<insert UDN>"

Set ZonePlayer = CreateObject("ZonePlayer.Controller")

connectiontimer = now()

If ZonePlayer.ConnectSynchronously(UDN) = "OK" Then
     connectiontimer = connectiontimer & chr(13) & now()
     Set objArgs = WScript.Arguments
     For Each strArg in objArgs
          SELECT CASE UCASE(strArg)
               CASE "MUTE":
                    CALL ZonePlayer.SetMuteState("Master", True)
               CASE "UNMUTE":
                    CALL ZonePlayer.SetMuteState("Master", False)
               CASE "TOGGLEMUTE":
                    MuteStatus = ZonePlayer.GetMuteState("Master")
                    If MuteStatus = 0 Then
                         Call ZonePlayer.SetMuteState("Master", True)
                    Else
                         Call ZonePlayer.SetMuteState("Master", False)
                    End If
               CASE "STARTPLAYLIST":
                         Call ZonePlayer.ClearQueue()
                         WScript.Sleep 250
                         Call ZonePlayer.AddSongToQueue("file:///jffs/settings/savedqueues.rsq#1", "", 0, True)
                         WScript.Sleep 250
                         Call ZonePlayer.SetTransportState("Play")
          END SELECT
     Next
Else
     WScript.echo "Connection Failed"
End If

ZonePlayer.DisconnectSynchronously
Set ZonePlayer = Nothing

WScript.echo connectiontimer
"ConnectSynchronously" uses FindByUDN in upnp.lib and is generally the fasted way to connect to a upnp device.

The caveat is that I have cut and pasted my old code into the current .wsc file and renamed the function. I have not tested using this function with the current .wsc, but it should work. If there is a problem with it, I won't be able to debug until this evening.

See new .wsc file attached.

Osler
Attachments
ZonePlayerController.zip
(15.2 KiB) Downloaded 686 times
Post Reply