Sonos is UPnP Compatible…What’s That?
Universal Plug and Play (UPnP) is a set of network protocols whose goal is allowing devices to seamlessly discover and connect to a network and thereafter be monitored and controlled. The UPnP protocols simplify your life as a user because routers, printers, phones, and other devices can be plugged in and ready to go without much intervention by you. (Well, that’s the idea and it usually works.)
How Can I See What UPnP Devices I Have?
So you have devices that are UPnP, but how do you see them if you are running say Windows 7? Well you can use the Univeral Plug-and-Play Tester from noeld.com which is where we first started or you can use the Device Spy tool that was once part of Intel’s Tools for UPnP Technologies, but is now open-sourced and can be found here: http://opentools.homeip.net/dev-tools-for-upnp. The Device Spy tool is a bit easier to work with because its two panes make it easier to see what’s going on and overall it's more user-friendly. Here is an example of what you get when you run it each of the tools.
Left: UPnP Tester: Right: Device Spy
CONNECT:AMP. Expanding any item, we see there is a lot more going on. To understand what's being shown you need to know that there are two generic objects of interest: a device and service. A device is a container for other devices and services. A service exposes actions and models its state with state variables. So, in the expanded screenshot of a PLAY:5 you can see an example of devices and services:
Device (e.g. ZPS5) (device XML http://192.168.2.10:1400/xml/zone_player.xml)
--Service: ZoneGroup Topology
----Device: Media Renderer
------Service: Connection Manager
------Service: GroupRenderingControl (device XML http://192.168.2.225:1400/xml/AVTransport1.xml)
----Device: Media Server
We only show two device/service XML URLs above. Once you use the Device Spy tool, you can easily get the other XML URLs and they follow the same pattern as shown above. The service XML is useful because it tells you what actions you can take with the service. So for the AVTransport service you probably can guess there are actions of some sort to start and stop the music. The device/service topology presented by the Device Spy is (probably) built from looking at device and service XML files. The tool doesn't know anything about the devices and services and so has to discover them. To be exact, the Device Spy discovers what’s on the network, then it looks at the device XML which refers to all the sub-devices and services and their XML files and so on. From all the device and service XML, the topology can be rendered.
You can see from the screenshot that we are dealing with a zone called “Office”.
Can I Control My Sonos From Here?
Yes, with the Device Spy tool (or similar) you can control Sonos devices. It’s not convenient for lots of actions so people write programs to abstract the process, naturally. But, using this tool you can get an idea of what’s available and help you understand the system.
Expand the AVTransport service, right click the GetTransportInfo action, and select Invoke Action which brings you to the window shown. When you click the Invoke button it queries the zone player and returns information. You see in this example that the zone is PLAYING. You can see possible values for the TransportState by navigating to the State Variables folder icon, expanding and clicking on TransportState.
To stop the current zone player go the Stop action, right click and select Invoke Action (or just double-click Stop), and click the Invoke button.
Can I Figure Out What’s Playing Using Device Spy?
Yes, but it’s a bit tricky. Because zone players can be grouped into zone groups, there is the concept of a group coordinator. The group coordinator is what you have to “ask” for the metadata on what’s playing. So, to continue with this example, we are looking at the “Office” zone player. Going to the GetPositionInfo action and invoking it you see that the TrackURI value has “x-rincon” in it and that TrackMetaData has NOT_IMPLEMENTED. Cutting to the chase, this means that this zone is a slave to the master or group coordinator with the given id RINCON_xxxxxxxxx.
If you go to the group coordinator specified in the slave zone's TrackURI field and invoke the GetPositionInfo action for that group coordinator zone player then you will get metadata for what's playing.
In this example, a track is being played from a local server so the TrackMetaData gives us information to this effect: the artist, the album, the track, and a link to the album art imagery.
<DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"> <item id="-1" parentID="-1" restricted="true"> <res protocolInfo="x-file-cifs:*:audio/flac:*" duration="0:06:40">x-file-cifs://mediamarx/music/Master/Beth%20Orton/Daybreaker/Beth%20Orton%20-%2010%20-%20Thinking%20About%20Tomorrow.flac</res> <r:streamContent></r:streamContent> <upnp:albumArtURI>/getaa?u=x-file-cifs%3a%2f%2fmediamarx%2fmusic%2fMaster%2fBeth%2520Orton%2fDaybreaker%2fBeth%2520Orton%2520-%252010%2520-%2520Thinking%2520About%2520Tomorrow.flac&v=353</upnp:albumArtURI> <dc:title>Thinking About Tomorrow</dc:title> <upnp:class>object.item.audioItem.musicTrack</upnp:class> <dc:creator>Beth Orton</dc:creator> <upnp:album>Daybreaker</upnp:album> <upnp:originalTrackNumber>10</upnp:originalTrackNumber> <r:albumArtist>Beth Orton</r:albumArtist> </item> </DIDL-Lite>
Okay, So How Would I Control the Sonos via UPnP Without Device Spy?
So far we know that the UPnP Sonos device has certain properties that can be viewed via HTTP, like http://192.168.2.225:1400/xml/AVTransport1.xml, so it looks like we are going to talk using HTTP. To that end, we will use the Fiddler Tool to construct simple HTTP requests to start with. Let’s see if we can duplicate the GetTransportInfo action that we performed with Device Spy above. To piece together what’s needed:
1) View the device_description.xml (right click on zone player and select Get Device XML) for any zone player and look for AVTransport service.
You should find something like this in the devcie_description.xml:
<serviceType>urn:schemas-upnp-org:service:AVTransport:1</serviceType> <serviceId>urn:upnp-org:serviceId:AVTransport</serviceId> <controlURL>/MediaRenderer/AVTransport/Control</controlURL> <eventSubURL>/MediaRenderer/AVTransport/Event</eventSubURL> <SCPDURL>/xml/AVTransport1.xml</SCPDURL>
2) Refer back to the reference on UPnP given at the start of this article and see that we are going to be sending some kind of SOAP message to the device.
3) Run the Device Validator (Device Validator.exe in the download from http://opentools.homeip.net/dev-tools-for-upnp) run some Control tests against the PLAY:5 device to get a sense of what kind of actions we can take.
Here's an information about an example test. It's a POST to the device with a SOAP action.
POST /MediaRenderer/AVTransport/Control HTTP/1.1 HOST: 192.168.2.225:1400 SOAPACTION: "urn:schemas-upnp-org:service:AVTransport:1#GetTransportInfo" CONTENT-TYPE: text/xml; charset="utf-8" Content-Length: 353
The body of the request will look something like this:
<?xml version="1.0" encoding="utf-8"?> <s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body> <u:ACTION xmlns:u="serviceType"> <!-- input arguments here --> </u:ACTION> </s:Body> </s:Envelope>
Let's take a step back for a second and review HTTP requests. HTTP requests have three parts: a method like POST or GET, headers, and a body. The body in our work here will contain the SOAP envelope with an ACTION. ACTION in the example above is GetTransportInfo, and in general, is any other applicable action for the device. serviceType is the type from the zone_player.xml file, urn:schemas-upnp-org:service:AVTransport:1 in this example.. Putting it all together, we can construct an HTTP request. The two screen shots below are from Fiddler, but it will be similar in any tool you use
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:GetTransportInfoResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"> <CurrentTransportState>PLAYING</CurrentTransportState> <CurrentTransportStatus>OK</CurrentTransportStatus> <CurrentSpeed>1</CurrentSpeed> </u:GetTransportInfoResponse> </s:Body> </s:Envelope>
Can I Search The Sonos Music Index?
Yes, you can browse the Sonos index using a SOAP request over HTTP to the zone player. You can construct a Fiddler HTTP request with the following components:
METHOD: POST http://192.168.2.6:1400/MediaServer/ContentDirectory/Control
HEADER: SOAPACTION: "urn:schemas-upnp-org:service:ContentDirectory:1#Browse"
<?xml version="1.0" encoding="utf-8"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1"> <ObjectID>A:ARTIST</ObjectID> <BrowseFlag>BrowseDirectChildren</BrowseFlag> <Filter>*</Filter> <StartingIndex>0</StartingIndex> <RequestedCount>10</RequestedCount> <SortCriteria>*</SortCriteria> </u:Browse> </s:Body> </s:Envelope>
This gets all Artists (since we are using * for a filter) and shows the first 10 results. The ObjectID can be strings like A:ALBUM (to search for albums), A:TRACKS (to search for tracks), or A:PLAYLISTS (to search playlists). The range of ObjectID values can be found from one of the other actions in the Media Server/ContentDirectory service.
Create a web page that issues HTTP / SOAP requests to your devices. We have something running now, but need to work out the kinks and distill out the basics before showing it. Stay tuned. Here’s a screenshot for now of the prototype:
Update: 01/16/2011. Be sure to check out the followup post on queries here: http://travelmarx.blogspot.com/2011/01/extracting-sonos-playlist-simple-sonos.html.
Update: 06/18/2014. Review instructions. Update with new version of DeviceSpy (downloadable from new location). Try steps in Fiddler on Windows 8.