Sonos HTTP API - run commands to Sonos via http

Continuing the discussion from Sonos and home automation audio:

@veni

I did this as well. Here are the steps I used. You need to set up a node server on a computer – which is far easier than it sounds.

  1. download node installer from Index of /download/

  2. install node

  3. download the Sonos HTTP API from from GitHub - jishi/node-sonos-http-api: An HTTP API bridge for Sonos easing automation. Hostable on any node.js capable device, like a raspberry pi or similar.

  4. install the sonos discovery code from command line interface (such as in Terminal on OS X), by typing

                        npm install sonos
    
  5. start node server from command line by going into the folder containing the sonos http api code ( such as /Users/[your user name]/node-sonos-http-api/ and typing

                        node server.js
    

At this point, you should see a lot of sones-related information come up within your command line interface. Then, from your browser, enter any of the commands listed (see GitHub - jishi/node-sonos-http-api: An HTTP API bridge for Sonos easing automation. Hostable on any node.js capable device, like a raspberry pi or similar.). When accessing from the computer on which the node server is located, the format is basically http://localhost:5005/[speaker name]/[command]. Here, “http://localhost” sends the http request back to the same computer, “:5005” sends the request to port 5005 (which is the port for the node server), and then the node server receives the command. For example, to play a Sonos favorite playlist called “CurrentFavs” on the Sonos in my kitchen, I enter

                                 http://localhost:5005/kitchen/favorite/CurrentFavs

FYI - This command works on all types of streams and playlists, such as Pandora radio stations or Spotify playlists that you have saved in your Sonos favorites. If you want to invoke the say command, be sure to use %20 in between words instead of a space. For example, if I wanted the kitchen speaker to announce “I am Ultron”, I would enter

                                 http://localhost:5005/kitchen/say/I%20am%20Ultron.

If you want to access the node server from another computer on the same network, then replace “http://localhost” with the network address of that computer, such as 10.0.1.15. This will come in handy if you create a ST SmartApp to send http commands to your node server.

IMO, the coolest function is the ability to send “Presets”, which are predefined groupings of speakers and volumes. An example (from the read me) is:

{
“players”: [
{ “roomName”: “room1”, “volume”: 15},
{“roomName”: “room2”, “volume”: 25}
],
“state”: “stopped”,
“favorite”: “my favorite name”,
“uri”: “x-rincon-stream:RINCON_0000000000001400”,
“playMode”: “SHUFFLE”,
“pauseOthers”: true
}

Hope this helps,
Tony

7 Likes

Much appreciated friend!

How does this integrate ST? I guess what I am asking is how do you send the commands without having to type them into a computer all the time?

You can set up virtual devices (recommend momentary) that in turn call the http commands. Then maybe A smartapp that presses those buttons upon certain time / Motion / other events.

2 Likes

is it possible to send commands directly to Sonos, instead of a server with Nodejs ?

I’d like to write a small ST app just for grouping/ungrouping Sonos players.
would that be possible ?

At this time, I don’t think its possible to group/ungroup “directly” from SmartThings to Sonos.

If you look at the SmartThings music player capabilities, you can see that the functions are limited to basic play/pause, volume level, etc. – No grouping/ungrouping.

I understand that the Smartthings integration does not support it. But it is possible on Sonos API.
So why can’t I send a correct command to Sonos API from a custom smartthings app to group them ?

As far as I know, Sonos doesn’t make its API available over http, which is why the https://github.com/jishi/node-sonos-http-api is critical.

But - if you think you are able to do it in a “small ST app”, great! I’ll be your beta tester.

well, the nodejs implementation seems to be making http call to Sonos. Am I wrong ?

Yup. It’s making a call to the https://github.com/jishi/node-sonos-http-api I mentioned earlier.

no; I mean the connection between nodejs and the Sonos device. Isn’t it HTTP ?

No. If it was, there wouldn’t be much need for the whole node server thing. Read the code and you’ll see.

well it seems that it is possible.
DLNA mediarenderer ST app can do it with following example code:

private mediaRendererAction(String action) {
def result
if(action==“Play”){
result = mediaRendererAction(action, “AVTransport”, getDataValue(“avtcurl”), [InstanceID:0, Speed:1])
}
else if (action==“Mute”){
// result = mediaRendererAction(“SetMute”, “RenderingControl”, getDataValue(“rccurl”), [InstanceID: 0, Channel:“Master”, DesiredMute:1])
result = mediaRendererAction(“SetMute”, “RenderingControl”, “/MediaRenderer/RenderingControl/Control”, [InstanceID: 0, Channel:“Master”, DesiredMute:1])
}
else if (action==“UnMute”){
// result = mediaRendererAction(“SetMute”, “RenderingControl”, getDataValue(“rccurl”), [InstanceID: 0, Channel:“Master”, DesiredMute:0])
result = mediaRendererAction(“SetMute”, “RenderingControl”, “/MediaRenderer/RenderingControl/Control”, [InstanceID: 0, Channel:“Master”, DesiredMute:0])
}
else{
result = mediaRendererAction(action, “AVTransport”, getDataValue(“avtcurl”), [InstanceID:0])
}
result
}

private mediaRendererAction(String action, Map body) {
mediaRendererAction(action, “AVTransport”, getDataValue(“avtcurl”), body)
}

private mediaRendererAction(String action, String service, String path, Map body = [InstanceID:0, Speed:1]) {
def result = new physicalgraph.device.HubSoapAction(
path: path ?: “/MediaRenderer/$service/Control”,
urn: “urn:schemas-upnp-org:service:$service:1”,
action: action,
body: body,
headers: [Host:getHostAddress(), CONNECTION: “close”]
)
result
}

private subscribeAction(path, callbackPath="") {
def address = getCallBackAddress()
def ip = getHostAddress()
def result = new physicalgraph.device.HubAction(
method: “SUBSCRIBE”,
path: path,
headers: [
HOST: ip,
CALLBACK: “http://${address}/notify$callbackPath”,
NT: “upnp:event”,
TIMEOUT: “Second-${state.gapTime ?:300}”])
result
}

private unsubscribeAction(path, sid) {
def ip = getHostAddress()
def result = new physicalgraph.device.HubAction(
method: “UNSUBSCRIBE”,
path: path,
headers: [
HOST: ip,
SID: “uuid:${sid}”])
result
}

No Grouping / ungrouping capability.

But I am not telling you not to try. Like I said, if you end up being able to do it, I - and many others - would be super excited.

well, if only group/ungroup function is missing, I would use play function with multiple Sonos devices selected at the same time.
would that work ?

Really great information here!

In looking through this thread I am wondering if it would be possible to create a smartApp or a Device handler that provides greater control over Sonos by using sendHubCommand to trigger http request to a server running node-sonos-http-api within my wifi network.

The point would be to avoid a publicly accessible server and the associated complexities by having the hub talk to a local server that spoke to Sonos. SendHubCommands would seem to be able to do that.

If it worked you could then link automation to those commands, triggering a bunch of stuff.

Any experience with trying something like that or resources/threads that may help me out?

Apologies if this is the wrong place to ask this question.

That is certainly possible - and is the point of the node server. Check out the related links.

I have done so, but sadly don’t see the example I am looking for, Thanks for pointing them out.

Dude. Check out the links to node server in above posts.

Also check out [Deprecated] Ask Alexa 2.0.7?

Hi,

I am trying to run sonos http api on my Ubuntu 12.04 server.
When I run the server.js I get this error:

node --harmony server.js

/root/node-sonos-http-api/server.js:109
process.on(“unhandledRejection”, (err) => {
^
SyntaxError: Unexpected token >
at Module._compile (module.js:439:25)
at Object.Module._extensions…js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:945:3

~/node-sonos-http-api# npm -v
node -2.15.1
~/node-sonos-http-api# nodejs -v
v0.10.47

What can I do ?