Sonos plugin

@anker,
Did you get TortoiseSVN (or similar) installed onto your end, per this discussion:
http://forum.micasaverde.com/index.php/topic,8544.0.html

Looking forward to seeing what you come up with!

IMHO being able to play a specific file from the music library on a specific player is one of the key requirements for home automation.

I’m using this feature to announce the name of callers and to get information about the states of my home appliances (dryer, …).

[tt]http://forum.micasaverde.com/index.php?topic=6952.0[/tt]
[tt]http://forum.micasaverde.com/index.php/topic,6658.msg41925.html#msg41925[/tt]
[tt]http://forum.micasaverde.com/index.php/topic,8291.0.html[/tt]

@guessed:

Testing your code and looking at SOAPAction definitions I changed the SOAP headers line in your code to:

headers = {"SOAPAction = " … servicetype … “#” … action},

Now I get a UPNP respons giving UPNPError 401 - Invalid action. I assume this means that it now has established connection to my Sonos? Maybe this could help in figuring out the problem with the http request.

Could it be a missing “content-length” (taken from the luasocket definitions):

•source: simple LTN12 source to provide the request body. If there is a body, you need to provide an appropriate “content-length” request header field, or the function will attempt to send the body as “chunked” (something few servers support). Defaults to the empty source;

I am not familiar with WireShark, so maybe you can figure it out without me guessing :slight_smile:

/anker

Yes 401 just means it can reject the request faster as it’s [effectively] malformed. I spent a little time yesterday and turned the code into a library, so that I can test it without Vera in the picture.
I’m going to see if someone at the office has a Sonos, so I can wireshark it there, as it’s working locally against my Onkyo (albeit, it’s just going through the Request-Response Motions, as the “data” doesn’t have correct values)

The Content-Length head is definitely an option. I’m so used to dealing with Servers that can handle Chunked-Encoding that I overlooked that. I will add that tonight and check it in alongside the other mods that I’ve made while I’m trying to sort this bit out. The Content-Length just needs to be set to the length of the string fed to the LTN12 as the postBody, so it’ll be easy to add.

PS: WireShark is a GUI, so it definitely makes it easy to see Network data going by, albeit hard to filter through, and interpret, the results sometimes :wink:

Guessed I have wireshark loaded up at home if you need someone to test it on a Sonos.


I am here: http://maps.google.com/maps?ll=33.639932,-84.436000

@anker, @wseverino,
I’ve pushed a new version of [tt]I_Sonos1.xml[/tt] to the trunk directory.

This link will give you a whole new ZIP file:
http://code.mios.com/trac/mios_sonos-wireless-music-systems/changeset/6/trunk?old_path=%2F&format=zip

and this link will give you just the changed file:
http://code.mios.com/trac/mios_sonos-wireless-music-systems/browser/trunk/I_Sonos1.xml?rev=6

and this shows the extra headers I added:
http://code.mios.com/trac/mios_sonos-wireless-music-systems/changeset/6

I think @anker was spot on with the [tt]Content-Length[/tt] needing to be explicitly added for the Sonos. Give it a whirl and let me know what you see.

The changes I have pipelined next are to turn the guts of the code into a .lua library, and to make all the parameters into native Lua parameters so the library code can better transition to calling “other” UPnP Services (including URL-flattening, and XML-Escaping for the POST body)

@anker,
I noticed that you put comma (",") characters between the XML elements like this (de-escaped for clarity):

[tt] l_arguments = ‘0,Master,’ … l_DesiredMute … ‘’[/tt]

Did you find something indicating that the Sonos needs these? It’s a little non-standard for XML, but I’m converting these over to be more like:

[tt] l_arguments = {InstanceID=“0”, Channel=“Master”, DesiredMute=l_DesiredMute}
[/tt]

and then having the Backend convert these into the corresponding XML strings prior to pushing them to the Sonos, but my current impl only emits them in standard XML format, and I want to make sure that won’t break anything.

My new code emits them as something without the comma’s, like:

[tt] 0Master0’[/tt]

[quote=“guessed, post:27, topic:169644”]@anker,
I noticed that you put comma (",") characters between the XML elements like this (de-escaped for clarity):

[tt] l_arguments = ‘0,Master,’ … l_DesiredMute … ‘’[/tt]

Did you find something indicating that the Sonos needs these? It’s a little non-standard for XML, but I’m converting these over to be more like:

[tt] l_arguments = {InstanceID=“0”, Channel=“Master”, DesiredMute=l_DesiredMute}
[/tt][/quote]

I will check if Sonos accepts SOAP XML requests without comma later this evening.

Furthermore I will check the http.request changes you made.

/anker

@guessed:

The XLM works without the comma.

/anker

@anker, @wseverino,
If you want to manually test the code, you can run a URL like:
http://192.168.1.50:49451/data_request?id=lu_action&DeviceNum=295&serviceId=urn:micasaverde-com:serviceId:Volume1&action=Mute

just change the “[tt]295[/tt]” to your deviceId. This will run a Mute toggle on the Sonos device under control.

Thanks Guessed. I will check this out tomorrow night when I get home and restore my vera. She crashed and burned this week, The joys of being on the road for living and hearing the DW say your box crashed again. :;

@guessed

I tried your http.request version and it seems strange. The “Play” action works, but the rest doesnt…

Mute (toggle), Pause and stop answers back okay, but has no effect on the sonos.

Skipup and SkipDown comes out with an UPnPError 711…

How do we trouble shoot this?

/anker

Here’s a summation of the stuff I sent @anker in a PM, in case anyone is following along and would like to know (or try):

a) I need a copy of the [tt]/var/log/cmh/LuaUPnP.log[/tt] file for the snippet of time when the functions were exercised.
b) Vera needs to be in Verbose mode at the time.
c) It’s interesting that Play works, but Mute or the other simple ones don’t. Play/Pause/Stop are the same bits of calling code
d) We need to validate if another operation, other than Play, if run first (after a Lua restart/save) will work or not.
e) If (e) pans out, then I can add a [tt]Connection: Close[/tt] request header to shutdown the HTTP connection between requests.

Unfortunately these calls are working against my Onkyo, so it must be just part of the variance people talk about when dealing with UPnP servers.

@anker,
Upon reading the [tt]UPnP-av-AVTransport1-v1-Service-1[/tt] spec a little more, the following codes:
[tt]Stop, Pause, Previous, Next[/tt]

should only have the [tt]InstanceID[/tt] parameter, and not the [tt]Speed[/tt] parameter. It’s possible this is contributing to why the Sonos is silently failing in those situations.

ie. it’s receiving a parameter that it’s not expecting.

@anker, @wseverino,
I’ve pushed a new version of I_Sonos1.xml to the trunk directory. It contains:

a) Addition of a Connection: close HTTP Header, to force the connection to close between requests
b) Splitting the PLAY action from the STOP, PAUSE, NEXT, PREVIOUS
c) Removal of the Comma between the XML elements of the Parameter list (just in case)

This link will give you a whole new ZIP file:
http://code.mios.com/trac/mios_sonos-wireless-music-systems/changeset/7/trunk?old_path=%2F&format=zip

and this link will give you just the changed file:
http://code.mios.com/trac/mios_sonos-wireless-music-systems/export/7/trunk/I_Sonos1.xml

and this shows the extra header I added, the segmentation of PLAY, and the removal of the Commas:
http://code.mios.com/trac/mios_sonos-wireless-music-systems/changeset/7

Give it a try. If this doesn’t work, I may just need to get myself a Sonos ZP90 :wink:

@Guessed - I can confirm that the actions are working. I tested them with a ZP90, ZP120, ZP100, S5, and a Play:3.

FYI - Here is some good info on the Sonos. See http://travelmarx.blogspot.com/search/label/sonos

Cool, thanks for the validation, definitely glad to hear there communications problems are out of the way.

I have another version of it waiting for checkin that turns the UPnP parts into a library, and modularizes it a bit better. will probably check that in tomorrow, or maybe Monday night, as I have update my plugins for UI5 today.

@guessed - I can confirm too that the actions are working. I tested them with a ZP90 and ZP120. Thanks for your effort even though you do not have a sonos :slight_smile:

Great, thanks for the validation also.

I checked in a new version this morning, and it’s in trunk in code.mios.com.

This version moves to using a library ([tt]L_Sonos1.lua[/tt]) to contain all the generic UPnP bits, and moves to using structured Lua Tables for the named function/action parameters to the UPnP calls… Internally it converts them to the necessary XML to send over the wire.

Sending data is handled, but I’m not post-processing the receipt yet, as I’m still working out how I want the results to look (as a Lua Table structure).

You should go ahead and get yourself setup with a Windows SVN client install (like http://tortoisesvn.net/, no affiliation etc) so you can make localized tweaks as needed.

Things that are UPnP-generic will go into the [tt]L_Sonos1.lua[/tt], and the rest (calls, etc) go into [tt]I_Sonos1.xml[/tt]

I have some fairly large improvements to make to the calling model, after the XML response stuff is sorted out, but these might have to wait until CY12.

Thankyou, you saved me from having to go out and buy a Sonos (I’ve been following a bunch of them on eBay)

Just wanted to say: Thanks a lot for the Sonos plugin! I can now add the ‘stop’ command to my ‘go to bed scene’s’ etc and issue the play command at 7:15h so I don’t have to find my remote control anymore when I am still half asleep.

Brilliant work!