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 2
Pandora some thing does not clear and trying to reboot sometimes clears it but i need to crash the server and restart ....some times it takes a few try to start the server as it crashes upon start up


AVT Play Log:

currently: PAUSED_PLAYBACK pndrradio:6500497454822409
951777329.841: track = pndrradio-http://audio-sjl-t1-2.pandora.com/access/2903629055255764799?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777329.782: track = pndrradio-http://audio-sjl-t1-2.pandora.com/access/2903629055255764799?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777329.673: track = pndrradio-http://audio-sjl-t1-2.pandora.com/access/2903629055255764799?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777329.547: track = pndrradio-http://audio-sjl-t1-2.pandora.com/access/2903629055255764799?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777329.462: track = pndrradio-http://audio-sjl-t1-2.pandora.com/access/2903629055255764799?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777329.414: track = pndrradio-http://audio-sjl-t1-2.pandora.com/access/2903629055255764799?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777329.290: track = pndrradio-http://audio-sjl-t1-2.pandora.com/access/2903629055255764799?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777328.498: track = pndrradio-http://audio-sjl-t1-2.pandora.com/access/2903629055255764799?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777328.448: track = pndrradio-http://audio-sjl-t1-2.pandora.com/access/2903629055255764799?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777328.356: track = pndrradio-http://audio-sjl-t1-2.pandora.com/access/2903629055255764799?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777327.909: track = pndrradio-http://audio-sjl-t1-2.pandora.com/access/2903629055255764799?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777323.619: track = pndrradio-http://audio-sjl-t1-2.pandora.com/access/2903629055255764799?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777323.619: state = PAUSED_PLAYBACK
951777311.436: track = pndrradio-http://audio-sjl-t1-2.pandora.com/access/2903629055255764799?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777284.070: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777283.380: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777212.870: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777211.907: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777206.406: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777181.910: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777181.780: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777138.142: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777138.095: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777137.946: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777137.877: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777137.755: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777126.659: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951777125.610: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951776991.706: track = pndrradio-http://audio-ch1-t2-1.pandora.com/access/3649818379862672283?version=4&lid=27816969&token=xT2%2FYnsGXGkdspL74
951776961.236: track = pndrradio-http://t1-1.p-cdn.com/access/?version=4&lid=27816969&token=Aff%2FCvCfN3JUclKArvkGYS1poXotTYU1sxeDjla74nwqbsvH
NodeRX Blocks:

Time avail full old dup oob nack
951777427: 0 0 0 0 0 0
951777303: 786 0 0 0 0 0
951777273: 724 0 0 0 0 0
951777243: 724 0 0 0 0 0
951777213: 724 0 0 0 0 0
951777182: 724 0 0 0 0 0
951777152: 724 0 0 0 0 0
951777122: 724 0 0 0 0 0
951777092: 723 0 0 0 0 0
951777062: 724 0 0 0 0 0
951777032: 724 0 0 0 0 0
951777002: 724 0 0 0 0 0
951776972: 1011 0 0 0 0 0
951776942: 724 0 0 0 0 0
951776912: 724 0 0 0 0 0
951776882: 724 0 0 0 0 0
951776852: 724 0 0 0 0 0
951776822: 723 0 0 0 0 0
951776792: 724 0 0 0 0 0
951776762: 724 0 0 0 0 0
CHSNK Fill Level:

Time =0 ^0 ^20 ^40 ^60 ^80 =100
951777427: 0 0 0 0 0 0 0
951777302: 4 424 452 456 456 2630 711
951777272: 0 0 0 0 0 3466 1130
951777242: 0 0 0 0 0 3459 1137
951777212: 0 0 0 0 0 3466 1130
951777181: 0 0 0 0 0 3462 1134
951777151: 0 0 0 0 0 3461 1131
951777121: 0 0 0 0 0 3465 1131
951777091: 0 0 0 0 0 3460 1136
951777061: 0 0 0 0 0 3467 1129
951777031: 0 0 0 0 0 3457 1139
951777001: 0 0 0 0 0 3462 1134
951776971: 1 428 448 456 452 3602 1032
951776941: 0 0 0 0 0 3462 1134
951776911: 0 0 0 0 0 3464 1132
951776881: 0 0 0 0 0 3455 1137
951776851: 0 0 0 0 0 3463 1133
951776821: 0 0 0 0 0 3460 1136
951776791: 0 0 0 0 0 3460 1136
951776761: 0 0 0 0 0 3462 1134
CHSRC Fill Level:

Time cnt t.ms avg.ftf max.ftf
951777427: 0 0 0 0
951777306: 1128 29328 15 61
951777276: 1148 29847 25 2412
951777246: 1150 29900 25 61
951777215: 1149 29874 25 60
951777185: 1150 29900 25 61
951777155: 1149 29874 25 65
951777125: 1148 29848 25 61
951777095: 1150 29900 25 61
951777065: 1149 29874 25 61
951777035: 1150 29900 25 61
951777005: 1149 29874 25 61
951776975: 1605 41730 18 80
951776945: 1149 29873 25 198
951776915: 1148 29848 25 61
951776885: 1150 29900 25 61
951776855: 1148 29848 25 61
951776825: 1149 29874 25 63
951776795: 1148 29848 25 61
951776765: 1150 29900 25 69
Userlevel 4
Badge +14
Which version of node.sj are you running? It seems like a really odd error. Also, make sure that you are running the latest version of both the http-api and sonos-discovery so the line-references will be correct.

I have added a simple dashboard example as well, for you to look at. just surf into http:/localhost:8080/dashboard/ or whatever IP you are using.
Userlevel 2
Will do as soon as i get home thanks maybe it is because i am running in windows but will update everything and try to recreate the error....
Userlevel 4
Badge +14
Will do as soon as i get home thanks maybe it is because i am running in windows but will update everything and try to recreate the error....

No, that can't be it, I'm running windows as well without any issues. The error seems to be caused by a JSON.parse call which receives a javascript object instead of a string, but I can't find any code related to it...
Userlevel 2
Ok will check i am running node v0.10.22 x64 ...

windows 7 .....I loaded the dash board and black screen how do i select zone to view ?

I have all the right updates will test later on ......
Hey J,

Updated both tonight.... will play around.

Also.... Just something to consider... I did a git pull for the http-api, and it complained about the fact that I have changed my presets.json.... So I just renamed the file, and put it back....

code:

remote: Counting objects: 3, done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 2 (delta 1), reused 2 (delta 1)
Unpacking objects: 100% (2/2), done.
From https://github.com/jishi/node-sonos-http-api
1c2dbbc..8502f14 master -> origin/master
Updating 1c2dbbc..8502f14
error: Your local changes to the following files would be overwritten by merge:
presets.json
Please, commit your changes or stash them before you can merge.
Aborting


With yours as master.... do you think you should rename it in the branch so it doesn't conflict with a user version? Or should I just rename it first?

Coolness.... 47megs on the web, and 37 megs on the http, after running for 3 or 4 days.....
Userlevel 2
steelrat how did you get it working when i go to ip/dashboard i get blank just black
Userlevel 4
Badge +14
The dashboard just makes an estimate and selects the biggest zone. My real version uses the highres versions from Spotify so that one is nice and pretty. I added it more as a reference example, it isn't really meant to be a working dashboard and should be adjusted depending on screen resolution and music services used.

If you have updated to the latest commit, it should never complain about presets.json again. If it does, you might need to run:

git rm --cached presets.json

That would tell it to stop tracking that file.
Userlevel 2
Sorry no matter what i do nothing comes up in the dash info where in the code can o force a zone name or id ....I don't understand biggest zone I am sorry.....
steelrat how did you get it working when i go to ip/dashboard i get blank just black

Well, I don't really have an answer.... other than, I wonder if it's because of how the pandora on your side is doing the stream. It's a logical assumption that slacker or rdio are acting closer to how the spotify is functioning that J's using....

Can you try any other sources than pandora? Even say the freeby version of slacker, which I have working here?
Sorry no matter what i do nothing comes up in the dash info where in the code can o force a zone name or id ....I don't understand biggest zone I am sorry.....

If I'm understanding the logic.... it's the device group with the most players....

Lets say you have 10 devices total....

Groups 5 players, 3 players, and a few singles....

It would pick the 5 player group.
Userlevel 2
Yes it does work with groups only not a single player is there a way that i could force the player id in the script so it will work for a single player I am just learning here and so please excuse my lack of understanding I appreciate your patience ......Robert
Userlevel 2
I have a single player in my setup (play5) and the dashboard is operating as expected in firefox. It would be nice to have the basic controls like volume, next, previous and play/pause along the bottom. Nothing fancy, just a nice layout for listening and viewing the album art
Userlevel 2
I do not dispute single player working it is when you have many players in your system the first player only will display if none are in a group I believe he did this to help me get a handle on the code am just trying to work out how to make it work a specific zone
Userlevel 4
Badge +14
As I said, it was never meant to be a controllable GUI, I only made it for my personal use in the Office.

If you want to control which player you will use, you will need to modify the "topology-change" event, line 43 in index.html to make another selection based on some input parameter (#uuid or ?uuid), something like this:

/dashboard/#RINCON_0058000000

code:

socket.on('topology-change', function (data) {

var players = {};

// make a hashtable of all players
data.forEach(function (i) {
players[i.uuid] = i;
});

// find which player you are interested in
var desiredPlayer = players[location.hash.substring(1)];

// now, we want the coordinator instead
currentZone = players[desiredPlayer.coordinator];

renderInfo();
});


It would probably be possible to rewrite it using roomName instead, but that requires some more thinking which I'm not capable of at the moment. If someone wants to create an enhanced version of this dashboard you are welcome to fork and send a pull request to me, but I will try and focus on some other alternative controller views.
Userlevel 2
No problem and many thanks........ for the guidance it really helps...
Userlevel 4
Badge +14
Been silent the last week, been trying to reclaim some sleep.

However, got some news for you. The web controller now has a working master mute. I also re-made the content of all buttons in SVG which means that it will scale nicely when making the interface bigger. Also added some css effects for a better feeling.

I also tried to make a fix when having multiple interfaces in your computer. Now it will search for Sonos players on all networks, and use then one which find a player first. Probably not of concern for most of you, but might help some of you with more advanced setups.

Enjoy!
Userlevel 2
A gift for the holiday thank you ....:D
Userlevel 4
Badge +14
I'm sorry but I broke compatibility with node 0.8 in my last changes. This is fixed now. This is mostly for rasberry Pi-users, since it's a pain upgrading from source on it.

EDIT: Actually, you can download pre-compiled version here:
http://nodejs.org/dist/v0.10.22/node-v0.10.22-linux-arm-pi.tar.gz
Userlevel 2
A bit off topic but how does one run your code as a server on a raspberry as a service every time i redirect node server.js > robert.txt i do not return to the bash so i can run the other script .....thanks

It does run though so the install is correct.....But have no clue what I am doing yet but learning....

Thanks
Userlevel 2
you can use the screen command to launch individual sessions on linux. Attach and detach from sessions at will
Userlevel 2
tried the new version works well in puppy linux but not so well in FreeBSD where it worked previously. Now the IP detection for the controler no longer functions. I get the following:
- binding SSDP to port 2509
- relevant IPs {}
- info - socket.io started
- http server listening on port 8000
notification server listening on port 3500

looks like it does not detect the network interface and then scan for sonos. This worked in previous versions. Any advice??
Userlevel 4
Badge +14
tried the new version works well in puppy linux but not so well in FreeBSD where it worked previously. Now the IP detection for the controler no longer functions. I get the following:
- binding SSDP to port 2509
- relevant IPs {}
- info - socket.io started
- http server listening on port 8000
notification server listening on port 3500

looks like it does not detect the network interface and then scan for sonos. This worked in previous versions. Any advice??


Which version of node are you running? Apparently the interfaces aren't detected on freebsd for some reason, probably an incompatibility in node.
Userlevel 2
Thanks for the quick reply. I am running FreeBSD 9.1p5 and Node-Devel-0.9.3 the latest port that I am aware of.
Userlevel 4
Badge +14
Thanks for the quick reply. I am running FreeBSD 9.1p5 and Node-Devel-0.9.3 the latest port that I am aware of.

The dev build and the stable build are different packages, could you try it with the stable build, which should be 0.8.x something?

I'm not sure how the package system on freebsd works, but there seems to exist ports for 0.10 as well, but maybe not for your version?http://www.freshports.org/www/node