Skip to main content
Headliner II
March 5, 2013

Sonos with node.js, my attempt!

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.

    391 replies

    Avid Contributor I
    October 23, 2014
    Thank you so much for this! Working great on my raspberry p for integration in a smart house system, and set up a cheapo RF remote to use for basic operating in the bathroom. (I.e. no tears if I drop it in the tub.)

    There is one thing I can't figure out, though. How do you use the generated state.json? Do I have to use it as part of a preset.json? All I want to do is resume whatever was happening on one of my players before it was interrupted be the say command. I am trying to write a bash script that
    1. Generates a state-file. (Succes)
    2. Uses say for an announcement. (Succes)
    3. Feeds the state.json back to resume whatever was happening before (No succes)

    Any input?

    (P.S. This a large thread, I've flicked through it but couldn't find anything on this subject. I'm sorry if I've overlooked it.)
    jishiAuthor
    Headliner II
    October 24, 2014
    Thank you so much for this! Working great on my raspberry p for integration in a smart house system, and set up a cheapo RF remote to use for basic operating in the bathroom. (I.e. no tears if I drop it in the tub.)

    There is one thing I can't figure out, though. How do you use the generated state.json? Do I have to use it as part of a preset.json? All I want to do is resume whatever was happening on one of my players before it was interrupted be the say command. I am trying to write a bash script that
    1. Generates a state-file. (Succes)
    2. Uses say for an announcement. (Succes)
    3. Feeds the state.json back to resume whatever was happening before (No succes)

    Any input?

    (P.S. This a large thread, I've flicked through it but couldn't find anything on this subject. I'm sorry if I've overlooked it.)


    Hi, the state json was merely a feature for integration purposes, to "display" the current state of your players. It is not related to the preset function at all.

    What you are talking about, "saving" the current status as a preset is another feature that hasn't been built yet (in conjunction with a preset builder). That was supposed to be part of a sandbox function for the API, but haven't had time to work on that.
    Avid Contributor I
    October 24, 2014
    I, see, jishi, thanks for letting me know, and for the great API.
    Lyricist III
    November 25, 2014
    Can anyone tell me how to get the 'mobile' version to work? I have everything set up and working great {the 'desktop' version}, but when i access it from my phone, its cumbersome to try and change the volume. I assume the 'mobile' version will help with this issue. But my directory structure doesn't have a '/m'. I appreciate any and all assistance.
    jishiAuthor
    Headliner II
    November 25, 2014
    Can anyone tell me how to get the 'mobile' version to work? I have everything set up and working great {the 'desktop' version}, but when i access it from my phone, its cumbersome to try and change the volume. I assume the 'mobile' version will help with this issue. But my directory structure doesn't have a '/m'. I appreciate any and all assistance.

    You need to checkout branch "mobile"

    If you used git, just invoke "git checkout mobile". If you downloaded the zip from github, you need to view the mobile branch and then the zip file will hopefully reflect the correct version.

    Do note that the mobile is far from finished. You can't for instance switch zone so you are stuck with whichever it chooses on load.
    Contributor I
    November 28, 2014
    Absolutely awesome library! Let's talk, I'm building a new Sonos Controller.

    https://github.com/michaelmcmillan/Zone
    Avid Contributor I
    December 4, 2014
    Is there a way to determine whether a given zone is grouped or not? The output from 'state' does not seem to contain any information on this. Alternatively, is this available somewhere in the sonos service (IP:1400) pages? I can't seem to find it.

    Also, the new version including pauseall/resumeall seems very useful, but I can't install it. I am obviously missing something. With this version, do I need to install sonos-discover and the api as two different node services? And then start both services? Sorry if I'm dense.
    jishiAuthor
    Headliner II
    December 4, 2014
    Is there a way to determine whether a given zone is grouped or not? The output from 'state' does not seem to contain any information on this. Alternatively, is this available somewhere in the sonos service (IP:1400) pages? I can't seem to find it.

    Also, the new version including pauseall/resumeall seems very useful, but I can't install it. I am obviously missing something. With this version, do I need to install sonos-discover and the api as two different node services? And then start both services? Sorry if I'm dense.


    Not at the moment, no. This is fairly simple to implement though. What is your use case?

    If you want to upgrade, use git to get the latest version or unzip the files over the old one. Then delete the node_modules folder and run npm install again, to get the latest dependencies. Let me know it that works.
    Avid Contributor I
    December 5, 2014
    Thanks for answering!

    My use case is as follows:
    My home automation system (raspberry pi running domoticz and the sonos http api, communcating with a fibaro home center lite) makes a pause request to the sonos api if the motion sensor has not detected movement in the room for 15 minutes. However, I do not want the pause request to be sent if the zone is grouped, so I was trying to implement some sort of check for grouping to decide whether or not to pause. But as I said, I could not find this info anywhere in the 'state' output or anywhere on the IP:1400 pages.

    I'm not at home at the moment, but I'll follow your update instructions and report back how I get on.

    Thanks!
    jishiAuthor
    Headliner II
    December 5, 2014
    Thanks for answering!

    My use case is as follows:
    My home automation system (raspberry pi running domoticz and the sonos http api, communcating with a fibaro home center lite) makes a pause request to the sonos api if the motion sensor has not detected movement in the room for 15 minutes. However, I do not want the pause request to be sent if the zone is grouped, so I was trying to implement some sort of check for grouping to decide whether or not to pause. But as I said, I could not find this info anywhere in the 'state' output or anywhere on the IP:1400 pages.

    I'm not at home at the moment, but I'll follow your update instructions and report back how I get on.

    Thanks!


    It wasn't as trivial as I first anticipated, but since the rewrite it's easier to extend the functionality with custom actions. Put this in a file called grouped.js or similar, and add it to the lib/actions folder:

    code:

    function checkGrouped(player, values, callback) {
    var zones = player.discovery.zones;
    var result = loopAndCheckIfPlayerIsGrouped(zones, player);
    callback({grouped: result});
    }

    function loopAndCheckIfPlayerIsGrouped(zones, player) {
    for (var i = 0; i < zones.length; i++) {
    if (zones[i].coordinator.uuid == player.uuid && zones[i].members.length == 1) {
    return false;
    }
    }
    return true;
    }

    module.exports = function (api) {
    api.registerAction('grouped', checkGrouped);
    }


    Now you can invoke:

    /Office/grouped

    and you will receive {"grouped":true} if the player is grouped with others. Would that work? The optimal solution would be that it would be tracked depending on the zone events, but this would be a temporary workaround until I have the time to look at it.