Sonos with node.js, my attempt!


Userlevel 4
Badge +14
INFO

Source code here: https://github.com/jishi/node-sonos-http-api
Sonos Web Controller draft (work in progress!): https://github.com/jishi/node-sonos-web-controller
Sonos IR control (requires lircd and IR reciever): https://github.com/jishi/node-sonos-remote-control

==============================================================


I know that there already is an attempt at this by this guy: http://forums.sonos.com/showthread.php?t=32643, but I found it to be a bit lacking in functionality so I decided to write up my own.

I have created a simple web-based API using what I have, which could be useful for integrating stuff with other applications. This web based API is inspired by other RESTful APIs, however I don't think it follows the correct guidelines to be called a REST API.

IT supports most basic features like:

play, pause, seek, next, prev, volume, mute, setAVTransportURI

It also supports these advanced fatures:

State of player as JSON, zone info as JSON, Play favorite item, presets (grouping, volume, avTransportURI)

You can read more in the README for each project.

To run it as a service under linux, I suggest using pm2 (https://github.com/Unitech/pm2). You need to run it in forked mode (-x)!

For Windows, you might try Winser http://jfromaniello.github.io/winser/

Cheers!

This topic has been closed for further comments. You can use the search bar to find a similar topic, or create a new one by clicking Create Topic at the top of the page.

397 replies

Userlevel 4
Badge +14
Seems like radio favorites needed to be handled differently than queue favorites. I added simple fix for it, but it might not work for custom radios (TuneIn should be fine though).

I also identified a few bugs in the preset system that I introduced in a rewrite, should work correctly now again.

"npm install" doesn't seem to update dependencies from git repos, so it's usually best to remove the node_modules folder and invoke "npm install" in order to get the latest version of sonos-discovery module.

Let me know if you have any more problems and I will try and sort it out.
Userlevel 4
Badge +14
For those who are interested, I pushed a new repository with a proof of concept for IR remote controlling your Sonos using a raspberry pi and a simple IR receiver.

https://github.com/jishi/node-sonos-remote-control

I use this myself with a left over IR remote, that controls the volume for my living room, and I've mapped the number keys to different presets and the media keys for play/pause/prev/next. Very neat.
Userlevel 4
Badge +14

adding player to coordinator Bathroom with streamurl x-rincon:RINCON_00000000000000000


I added some entity encoding stuff to support the favorites, I guess there are some scenarios where this will pass null that I need to take into account.

However, that streamurl points to a device with no MAC-adress, which is kind of odd? It should never be all zeros like that.
Userlevel 4
Badge +14

On my wish list:
- Queue management, add/remove/clear spotify tracks and/or playlists.
- Control shuffle/repeat/crossfade
- No autoplay when changing presets

My goal is to have a simple mobile GUI with some presets buttons;
Morning - Group all players, set volumes, start radio.
Evening - Group some players, set volumes, set shuffle, set repeat, set crossfade, replace queue with spotify playlist.
Party - Same as above but different playlist and maybe moving items in queue to play select item as next song.
Mute - Muting or changing volume in selected rooms.
Stop all - Stop all players with a single click (useful when leaving the home).

I've tried some of the unsupported APIs and this is the best so far, keep up the good job!


Control shuffle/repeat etc is next on my todo.
You can disable Auto-play on the preset by adding the following to your preset:

code:

{ "state": "stopped",
players:
[ { roomName: 'Bathroom', volume: 11 },
{ roomName: 'Kitchen', volume: 11 },
{ roomName: 'Master Bedroom', volume: 11 },
{ roomName: 'Living Room', volume: 10 } ] }


It's not part of my example, but should be.
Party mode is also an idea I've had for a long time. I started a .NET based app for it, but I never finished it. I will probably do a web-based version instead based on this API, that handles multiple clients (think, smartphone control).

You might want to check out the web controller-project that I started in your case, since the http-api is just a wrapper around sonos-discovery. If you plan on hosting a web client, you should probably skip that layer. https://github.com/jishi/node-sonos-web-controller

The web controller isn't working, but you might get the idea on how you can create and host the web client within node completely.

Oh, and finally, I did a commit to fix the null-check as well, but I'm not sure that it will resolve your issue completely. Let me know what kind of error you receive. Oh, I just struck me that you probably anonymized the streamurl, DOH! 🙂
Userlevel 2
Thanks, yes I removed my real Mac-address... ;)

Will continue my testing tonight. The Web-controller looks very cool but I think it might be a bit heavy weight for me. Just want to have a few predefined buttons that should trigger some custom actions like your new IR remote project.

Looks like I can get Morning, Mute and Stop All buttons running quite easily now.
Userlevel 4
Badge +14
So, I spent the evening with coming up with a rather unique feature (haven't seen it yet anywhere else, enlighten me if I'm wrong!).

I call it "volume enforcement", which basically means that you can "lock" the volume for all your players, both up and down. This might be useful at a party, in an office environment, or just when you are going to sleep (if another family member decides to have a party in your house or something).

How it works? When you tell it to lock volumes, it will register the current volume for all players, and every time the volume changes, it will just send another volume adjustment to reset it back to whatever it was. This will of course not be rock solid, but might be useful never the less.

This is part of the http-api, since it needs some sort of trigger to function.

I might change it to only lock for increasing volume, since this effectively makes it impossible to mute a player with the buttons. If you have any feedback regarding that, please let me know.
Userlevel 2
Thanks for the new preset options - perfect!

But some problems with grouping speakers. If I have 3 speakers grouped (Bathroom, Kitchen, Master Bedroom) and would like to regroup two of them.

Sending the following
code:
{"players":[{"roomName":"Bathroom","volume":15},{"roomName":"MasterBedroom","volume":25}],"state":"stopped","uri":"x-sonosapi-stream:s47341?sid=254&flags=32"}


Server output
code:
{ action: 'preset',
value: '%7B%22players%22:[%7B%22roomName%22:%22Bathroom%22,%22volume%22:15%7D,%7B%22roomName%22:%22Master%20Bedroom%22,%22volume%22:25%7D],%22state%22:%22stopped%22,%22uri%22:%22x-sonosapi-stream:s47341?sid=254&flags=32%22}' }
applying preset { players:
[ { roomName: 'Bathroom', volume: 15 },
{ roomName: 'Master Bedroom', volume: 25 } ],
state: 'stopped',
uri: 'x-sonosapi-stream:s47341?sid=254&flags=32' }
applying preset { players:
[ { roomName: 'Bathroom', volume: 15 },
{ roomName: 'Master Bedroom', volume: 25 } ],
state: 'stopped',
uri: 'x-sonosapi-stream:s47341?sid=254&flags=32' }
skipping breakout because already coordinator
current volume 15
setting volume 15
current volume 25
setting volume 25
callback
STATUS: 200
volume success? true
Volume
STATUS: 200
Volume
STATUS: 500


The group still contains 3 speakers. However if ungrouping all speakers first and then send the command it works ok. It doesn't load the Radio from the URI command either.
Userlevel 4
Badge +14

The group still contains 3 speakers. However if ungrouping all speakers first and then send the command it works ok. It doesn't load the Radio from the URI command either.


Yeah, that's a glitch. If the first player already is a coordinator, I need to check which group members it has and detach the ones that shouldn't be part of it. Right now it just works with the players listed. It worked in an earlier version where I always detached the coordinator, but that became kind of choppy if you reapplied the same preset twice. I will fix it in the coming days.

uri is only useful for line-ins and hardcoded http-streaming urls. The x-sonosapi-stream urls require the DIDL metadata in order to be applicable. Next on the todo is to support favorites in presets as well, that should be a no brainer to solve.
Userlevel 2
Yeah, that's a glitch. If the first player already is a coordinator, I need to check which group members it has and detach the ones that shouldn't be part of it. Right now it just works with the players listed. It worked in an earlier version where I always detached the coordinator, but that became kind of choppy if you reapplied the same preset twice. I will fix it in the coming days.

uri is only useful for line-ins and hardcoded http-streaming urls. The x-sonosapi-stream urls require the DIDL metadata in order to be applicable. Next on the todo is to support favorites in presets as well, that should be a no brainer to solve.


Looking forward to play with the upcoming fixes!
Userlevel 4
Badge +14
So, now it's possible to use favorites in your presets. It will replace the queue if it's a queue. If it's a radio, it will just start playing it and leave the queue intact.
Userlevel 4
Badge +14
Looking forward to play with the upcoming fixes!

Just pushed a commit where the issue with players not leaving the group is fixed. Enjoy.
Userlevel 4
Badge +14
Seems like I had a bad fallback. I pushed a fix for it to sonos-discovery. Remove your node_modules folder and run npm install again.
Userlevel 2
Seems like I had a bad fallback. I pushed a fix for it to sonos-discovery. Remove your node_modules folder and run npm install again.

Much better, thanks!
Userlevel 4
Badge +14
I have added support for:

groupVolume
groupMute
mute (single player)
repeat
shuffle

I rewrote the previous groupmute/volume implementation and because of that, the calls for volume and mute are now different (this doesn't concern the http-api, only sonos-discovery).

enjoy.
Userlevel 4
Badge +14
It now also supports playMode in presets.

Example:

code:

{
"players": [
{ "roomName": "room1", "volume": 15},
{"roomName": "room2", "volume": 25}
],
"state": "stopped",
"favorite": "my favorite name",
"playMode": "SHUFFLE"
}


Valid values are: NORMAL, REPEAT_ALL, SHUFFLE_NOREPEAT, SHUFFLE

The most confusing part of it is that "SHUFFLE" is with implicit repeat on. I might change the format to something like:

code:

"playMode": {"repeat": "on", "shuffle": "off"}


Maybe that would be easier to comprehend.
Userlevel 2
It now also supports playMode in presets.

Example:

code:

{
"players": [
{ "roomName": "room1", "volume": 15},
{"roomName": "room2", "volume": 25}
],
"state": "stopped",
"favorite": "my favorite name",
"playMode": "SHUFFLE"
}


Valid values are: NORMAL, REPEAT_ALL, SHUFFLE_NOREPEAT, SHUFFLE

The most confusing part of it is that "SHUFFLE" is with implicit repeat on. I might change the format to something like:

code:

"playMode": {"repeat": "on", "shuffle": "off"}


Maybe that would be easier to comprehend.



Great updates!
I think that the second option would be better, especially if you will implement the Crossfade option as well.
Userlevel 4
Badge +14
Yeah, you are probably right. People probably think that crossfade should go in there as well.

I have added a new feature, pauseall and resumeall. This will pause the currently playing zones, and remember for subsequent resumeall calls, which will resume the players that was playing when you paused them.

Useful for home automation, when someone rings the doorbell or when you receive a phone call perhaps.
Userlevel 4
Badge +14
Just wanted to share that my previous on{x} script became a whole lot easier when having a raspberry pi in the background keeping track of the players.

http://forums.sonos.com/showthread.php?t=30387&highlight=on%7Bx%7D

new code:

code:

// Pauses the queue in the Sonos when a call starts
device.telephony.on('busy', function () {
device.ajax({
url: 'http://192.168.1.112:5005/pauseall',
type: 'GET'
}, function () {});
var notification = device.notifications.createNotification('Pausing players, click to resume');
notification.on('click', function() {
console.log('Resuming players from notification');
device.ajax({
url: 'http://192.168.1.112:5005/resumeall',
type: 'GET'
}, function () {});
});
notification.show();
});

// Pauses the queue in the Sonos when a call starts
device.telephony.on('idle', function () {
// resuming players now
device.ajax({
url: 'http://192.168.1.112:5005/resumeall',
type: 'GET'
}, function () {});
});
Userlevel 4
Badge +14
From the idea shared here: http://forums.sonos.com/showthread.php?t=16130

I added the simple feature to have an optional timeout with "pauseall", which can easily be used as a sleep function.
Userlevel 4
Badge +14
I have taken some time to revive the web controller project I was working on. I have now managed to get the top buttons working (prev, play, next) as well as the position bar (only status, no seek functionality), and the track info.

This updates, instantly, if you control sonos from any other controller, like one would expect.

http://upload.grabbarna.se/files/sonos-web-controller.png

Might not be considered a huge leap in functionality, bit I spent most of the time rewriting stuff that wasn't well thought of. If I finish it, would you use it?
jishi,

I have negative free time at the moment, but your projects, especially with the raspberry pi, are causing me to develop an "itch" to join the fun.
Userlevel 4
Badge +14
Hi buzz. Nice to hear that there actually is an interest, so my work isn't completely in vain :)

I'll start a new thread for the web controller when I feel like the basic functions are fully functional, maybe that'll get more attention.
Userlevel 2
Jishi,
Fiddled around with the web controller using puppy linux and it is starting to look quite promising. Performance is excellent. Eventually I would like to host this server app on my Nas4Free box based on freebsd. I had the purple controller working a while back but its functionality is quite dated. My "clients" would be linux desktops, blackberry phones, android and apple "guest" devices and windows stations as well.

Keep up the good work.
Userlevel 4
Badge +14
Jishi,
Fiddled around with the web controller using puppy linux and it is starting to look quite promising. Performance is excellent. Eventually I would like to host this server app on my Nas4Free box based on freebsd. I had the purple controller working a while back but its functionality is quite dated. My "clients" would be linux desktops, blackberry phones, android and apple "guest" devices and windows stations as well.

Keep up the good work.


Nice to hear. supporting mobile devices will be the next step, and I will probably allow for a different layout for these devices (meaning, /m url would have a different template set). However, I think that Blackberry phones can be tricky to support.
Userlevel 2
Nice to hear. supporting mobile devices will be the next step, and I will probably allow for a different layout for these devices (meaning, /m url would have a different template set). However, I think that Blackberry phones can be tricky to support.

I will take a peek at how it looks / works on the BB Z10 and let you know.