Digging into UPnP by searching a Sonos API

A discussion about connection possibilities of a Sonos speaker led to an short analysis on how it communicates with other systems. As an exercise I would like to control the volume.

At first I thought Sonos uses a proprietary API because after a quick search on the internet I couldn’t find anything useful. However, after searching for some minutes it turned out that there are open protocols in use.

Search for protocols

nmap found the IP address of my Sonos Play:5 and I searched for open TCP ports on this device:

TCP ports 1400, 1410 and 1443 are open. Using curl it was clear that 1400 and 1443 are the same or similar services with the difference that 1443 uses TLS.

Ok, that’s interesting. The Server string contains UPnP in it what looks like this device has some UPnP capability. Searching the internet I found that UPnP uses SSDP for discovery so I installed the gssdp-device-sniffer on my Linux system. One of the responses which were caught look like this:

Remark: The port 1410 did also respond to a HTTP request with an UPnP Server string but I couldn’t find any description document URI.

Understanding UPnP

At this point we know this device uses UPnP and a special URI was discovered which seems like a step forward. But first I had to learn something about UPnP. On https://openconnectivity.org/developer/specifications/upnp-resources/upnp you can find very helpful specifications. As an introduction http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v2.0.pdf is enough as it explains UPnP basics down to a common protocol layer. Following steps are defined, namely Addressing, Discovery, Description, Control, Eventing, Presentation.

The discovery step we already have above, where I caught the SSDP message. It provided us with an URI which is specified in the description step. Looking at the data from http://192.168.0.24:1400/xml/device_description.xml shows a list of all so called services where the following definition looks interesting:

Going to http://192.168.0.24:1400/xml/RenderingControl.xml it reveals several actions like GetVolume and SetVolume which are described with its parameters like this example shows (stripped relatedStateVariable for readability away):

Now we are in the step/chapter Control. Explanations can be found in the UPnP-av-RenderingControl-v1-Service document.

Sending a request

It’s time to send a request. UPnP-arch-DeviceArchitecture explains on page 78 an Action Invocation which I used as template for the SOAP request to get the actual volume level.

Invoking this command it responds with the volume level 22:

Now my goal is reached, I established some basic communication with the Sonos device and all other controls are straight forward.

Learnings

  • The UPnP specification is easy understandable and the device and service description format is human readable
  • UPnP uses different (well known) protocols and is very powerful as it covers a wide application spectrum
  • The error code 402 (Invalid Args) occurred a few times, always without a pointer to the error. This can be nasty
  • It looks like the Sonos device is more open as many know

Linux, Go, Container, PostgreSQL, Bitcoin, Infosec

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store