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
Thought there would be more interest in something like this.

However, following up myself:

I bought a raspberry pi primarily to test this out, and it was even easier than expected, to get this running. Installed a precompiled version of Node 0.8.16 on the default raspbian image and everything works as expected.

Also implemented the following:

+/-volume support
seek
next/previous

I'm guessing it would be possible to utilize some sort of button board to get physical buttons to control your Sonos (I'm thinking presets), but even some sort of wireless keyboard could be useful.
Userlevel 2
A lot of us will definitely be interested in your progressions on this project, but (like me) they are probably just waiting to see what happens.

Maybe if you release/reveal the code you allready have, and some quick instructions of how to use it, you will probably get more response.

Don't know if this is part of your plans, but what I would like to see is a good looking web based controller that can run on an IIS server. (An alternative to the old perl-based controller)

Good luck with this project and keep up the good work!
Userlevel 4
Badge +14

Don't know if this is part of your plans, but what I would like to see is a good looking web based controller that can run on an IIS server. (An alternative to the old perl-based controller)

Good luck with this project and keep up the good work!


Thank you for your reply, it helps knowing that there is a demand to keep the spirit up :)

Yes, the next step is to try and reproduce a simple html5 controller based on websockets (with socket.io) to get a more native look and feel. I have never seen the perl-based controller though. Since node doesn't interact with IIS as far as I know, this will not be hosted on IIS. However, node has built-in support for http, so there is no need for this, and this would be platform agnostic.

The tough nut to crack as I see it is the music and queue management. I have no insight on how the music browsing works, since I exlusively rely on spotify myself.

I will add my progress so far to my github as soon as I figure out the smartest way to handle topology events and how to structure the npm, hopefully this weekend.
Badge


Yes, the next step is to try and reproduce a simple html5 controller based on websockets (with socket.io) to get a more native look and feel. I have never seen the perl-based controller though.

The tough nut to crack as I see it is the music and queue management. I have no insight on how the music browsing works, since I exlusively rely on spotify myself.



Sonospy has an optional HTML GUI front end (using jQuery and Javascript) that supports browsing - you ought to be able to work out how browsing works from that.
Userlevel 4
Badge +14
Sonospy has an optional HTML GUI front end (using jQuery and Javascript) that supports browsing - you ought to be able to work out how browsing works from that.

Good tip. However, the main problem for me is that I have no indexed music om my system, so I have no way of inspecting the actual traffic.
jishi,

SONOS allows up to 16 shares, you could create a small share on the computer for testing purposes. I keep a few small folders for such purposes. And, there is a large folder that can be expanded if I ever need to test beyond the 65000 limit. The metadata is distinct even though the track contents might not be distinct.
Userlevel 4
Badge +14
Okay, here is the first draft.

https://github.com/jishi/node-sonos-http-api

if you don't want to muck around with git, I have a zip-file which you can use:

http://upload.grabbarna.se/files/sonos-http-api.zip

unzip it to a folder, then just invoke from a command prompt or powershell or bash or whatever while standing in the folder:

code:

node server.js


I don't handle topology yet, had some issues with timing and haven't had time to look into it.

I have only tested it in node 0.8.16, should work fine in 0.8.x but unsure about earlier versions. It works on a raspberry pi, and should be okay on any nodejs supported platform.

Feedback is welcome, forking and patches as well.

Have fun!
Userlevel 4
Badge +14
Here is an update.

I have managed to implement the topology stuff now as well, which basically means that you are able to send commands to any player, and it will control the coordinator instead.

This means that if:

Kitchen and Office is grouped, command to either player will control them both (except for volume). This is probably much more handy.

Posted a pre-zipped package here:

http://upload.grabbarna.se/files/sonos-http-api-v2.zip

And also pushed the latest version to github.
Userlevel 4
Badge +14
For those interested in the progress:

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

Man, does it takes forever to replicate the GUI in HTML...
Userlevel 4
Badge +14
Finally pushed the web controller to a public repository:

https://github.com/jishi/node-sonos-web-controller

Nothing is actually working (except for zone discovery), but if you want to try it out to get a feeling on how it will behave in the browser, please feel free to do so. You will also be able to follow my commit logs :)

If you want to help out, give me a shout. The main reason for me doing this, is because I want to expose a working controller for all my co-workers. Being behind firewalls and on different nets, it would simplify it a lot if I could just expose a web-based controller for everyone to use. It could also be useful for controlling a system remotely.
Userlevel 2
Looking really good.....will try it out thnak you for sharing..

Regards

Robert
Userlevel 4
Badge +14
I managed to map one of my airmouse volume buttons to control a specific player with my raspberry pi without any problems.

It read out the events on /dev/input/event0 (the keyboard) and maps the appropriate keycode to invoke the setVolume() method, this was with approx 20 lines of js.

It works if run as a daemon as well, I started node.js from a ssh session and controlled it with a USB attached keyboard. Main problem is that the Airmouse operates in the 2.4 GHz span so it seems to drop about 5% of the keystrokes... it's a crappy china-keyboard as well, so that might explain it.
Userlevel 2
Thanks and keep up the good work. I would love to see a quick how to of how to get this working with a RasPI.
Userlevel 4
Badge +14
Thanks and keep up the good work. I would love to see a quick how to of how to get this working with a RasPI.

I'll try and write something up. Is it node.js installation and how to start a node app that you are interested in?
Userlevel 4
Badge +14
Glad it worked out for you. It's strange that you would need to npm install all libs separately. The package.json file is supposed to keep track of the dependencies for you, making a "npm install" invoke from the same folder to trigger a dependency-check and download stuff that is missing globally. That was my experience when I tested it out, will have to check it out again.

Haven't had much time to work on it, but another guy has forked the project and is pushing minor improvements to it.

Regarding running it as a service, it is doable but requires some manual setup. It's easier on linux afaik, but it's possible on Windows as well.
Userlevel 4
Badge +14
Okay, finally got some time to work in this and I got around to implement support for presets.

A preset in this sense is a group of players with a predefined volume. This means that you can, by supplying a valid js object, send a signal to the players to group themselves, set the preferred volume and start playing whats in the queue.

A preset looks like this:

code:

{
"players": [
{ "roomName": "room1", "volume": 15},
{"roomName": "room2", "volume": 25}
]
}


The first player in the group will be assigned to coordinator role.

Next step will be to implement some playback options, like random, gapless, a favorite queue etc. It would also be of interest to keep track of which track it was actually playing last time, in order to resume where it left of.

Check it out here: https://github.com/jishi/node-sonos-http-api
Userlevel 4
Badge +14
I made some improvements to the preset signals, previously it did spam a lot which confused the players and failed to add everyone to the group. I also identify if the coordinator already is a coordinator, and skips the BecomeCoordinatorOfStandaloneGroup call.

It also support predefined presets, which you can store in a file, which gives you the ability to define something like an "all" preset, that you can apply by invoking:

code:
http://localhost:5005/preset/all
Userlevel 4
Badge +14
And today I read about this thing: http://tessel.io/
Userlevel 4
Badge +14
If anybody is interested, I did add support for replacing queue with one of your favorites.

example:

code:
http://localhost:5005/TV Room/favorite/MyAwesomePlaylist


Would replace the queue for the current group that TV Room is part of, with the favorite "MyAwesomePlaylist"

I will eventually add support for this in the presets as well, which means that you can resume a specific grouping, with pre-defined volume set and a predefined favorite list.

I will probably use this my self instead of the built in alarm, using the crontab daemon on the raspberry pi and do a 2-step wake-up call 🙂 slow music in the bedroom first 30 minutes, then all players in my apartment with some more up beat playlist.
And today I read about this thing: http://tessel.io/

I'm well aware that clock speed is only part of the story, but at 180MHz I wonder if it is fast enough for large JavaScript programs.
Userlevel 4
Badge +14
I'm well aware that clock speed is only part of the story, but at 180MHz I wonder if it is fast enough for large JavaScript programs.


Yes, that part worries me too. The raspberry at 700 works pretty good but it can still choke when it has a lot to deal with.

However, it is running a full blown Debian setup, and could probably be stripped down quite a bit. Would be interesting to see how well it would behave.
Userlevel 4
Badge +14
Now, as part of the 4.2 upgrade, the players now remember their queue and queue position it had prior to being grouped with other players.

This is a good thing, since that gives you the possibility to use different coordinators for different presets, and that way, you will be able to switch presets and keep the old queue, if each preset has a unique coordinator.
Userlevel 2
Yes, you are running 0.6 of node.js, they changed it in 0.7 from "path" to "fs". I haven't run it under 0.6 in a long time, and I focused on 0.8 when I started. It might work, you can try and change this row (however, you might get other problems down the line):

code:
var fs = require('fs');


to

code:
var fs = require('path');


I assume you installed it using apt-get under debian/ubuntu, correct? If you don't want to compile and install it yourself, you can check this out: http://ypcs.fi/howto/2013/03/23/nodejs-debian/


Thanks! I updated to a newer nodejs, and now it works!

Looking forward to experimenting with this :)

Andreas
Userlevel 4
Badge +14
Thank you for your pointers, some bugs that was introduced in my last commits.

I have fixed them and pushed to github now. Enjoy!
Userlevel 2
Muting is working, thanks!
A longer message is awaiting approval...