Simplified HTTP API (node.js)


Userlevel 4
Badge +14
Hi, I'm starting a new thread regarding this (old one here https://en.community.sonos.com/advanced-setups-229000/sonos-with-nodejs-my-attempt-33834) since that one grew out of hand.

I have made some major improvements to the simple HTTP API that I've built, and it now also comes with a pre-composed raspberry pi image that runs from a RAM-drive (based on AlpineLinux) for even simpler installation.

This software is useful for simple integration with home automation in mind, or for small hobby projects.

For more information, see http://jishi.github.io/node-sonos-http-api/

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

Have fun!

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.

43 replies

Great to see you made some improvements. Can't wait to try out the new api.
Thanks for all your hard work! Hopefully someone will integrate the Echo interface right into your Pi build, which would greatly simplify Echo voice control of Sonos.
Badge
Nice done. Installed this on raspberryPi Linux and works well. REST API is pretty nice and easy to use.
Userlevel 4
Badge +14
I have made improvements to the Raspberry Pi image and added an auto-update feature. It will now install the latest stable release automatically without intervention.

The preset functionality is also improved significantly, and has now a presets-folder that will auto reload as soon as content changes. Since the whole /flash folder is exposed via samba, means that you can edit the files from your PC via regular filesharing. You can reach it via \\sonos or \\[IP of raspberry]
Badge
In case anyone is interested, here is a new open-source offering built using jishi's node-sonos-discovery (which underlies node-sonos-http-api) and also available using a modified version of his pre-composed node-sonos-http-api raspberry pi image. Jishi, you enabled me to solve a major problem in my house!

"SonosAmpJuicePi"- solution for automatically powering on/off amps
https://en.community.sonos.com/advanced-setups-229000/sonosampjuicepi-solution-for-automatically-powering-onoff-amps-6756435
Badge
In a previous version, I was able to "move" any music from one player to an other by grouping then after a few seconds ungrouping the first player (through sending appropiate presets). This used to work for all kinds of playlists, radio, even casting. (I had a handy button on my harmony remote, that triggered this action with a single click. Neat !)

However I can't get this to work anymore in the current version (using 1.1.5 ; but sorry, can't say exactly from which version onwards it broke). Grouping the two players still works, but when ungrouping I can't get the 'destination' player to keep playing what was originally on the 'source' player. It returns to its original content. (I guess something has changed about applyPreset of SonosDiscovery, but understanding the code is beyond my humble capacities...)

Jimmy can you bring the old behaviour back, pls ? (Or even better : include such a 'move' function in the API ?) Thanks !
Userlevel 4
Badge +14
In a previous version, I was able to "move" any music from one player to an other by grouping then after a few seconds ungrouping the first player (through sending appropiate presets). This used to work for all kinds of playlists, radio, even casting. (I had a handy button on my harmony remote, that triggered this action with a single click. Neat !)

However I can't get this to work anymore in the current version (using 1.1.5 ; but sorry, can't say exactly from which version onwards it broke). Grouping the two players still works, but when ungrouping I can't get the 'destination' player to keep playing what was originally on the 'source' player. It returns to its original content. (I guess something has changed about applyPreset of SonosDiscovery, but understanding the code is beyond my humble capacities...)

Jimmy can you bring the old behaviour back, pls ? (Or even better : include such a 'move' function in the API ?) Thanks !


This might be related to a change I made to fix another issue where "leave" didn't really do what one would expect. If you could file an issue on github regarding this, and also explain in detail what you actually want to achieve, I can take a look at it.

This was probably the change that broke your expected behavior: https://github.com/jishi/node-sonos-http-api/issues/245
Badge
Thank you I will !
Userlevel 4
Badge +14
Some of the latest addition include support for more TTS services. It now includes support for Microsoft Cognitive Services (Bing Speeh API), and the new AWS Polly service which has super natural sound in many supported languages. Seems like speech simulation has taken huge steps in the last few years.
Thanks so much for providing this API! It is really cool! I'm working on creating a node.js app with a scheduler to turn on my music automatically. I've noticed that occasionally when I give pause and resume commands to my sonos using my computer it will not do anything. If I try to hit the URL and do /zones or anything it will just return a blank array [] . Then, if I hit the play button on the actual sonos it will start working again and will receive commands. Is this a known issue or do you think something could be wrong with my sonos? My whole idea is based around my node server being able to wake up the sonos and start playing a specific playlist, so I would hope it would be possible.
Userlevel 4
Badge +14
Thanks so much for providing this API! It is really cool! I'm working on creating a node.js app with a scheduler to turn on my music automatically. I've noticed that occasionally when I give pause and resume commands to my sonos using my computer it will not do anything. If I try to hit the URL and do /zones or anything it will just return a blank array [] . Then, if I hit the play button on the actual sonos it will start working again and will receive commands. Is this a known issue or do you think something could be wrong with my sonos? My whole idea is based around my node server being able to wake up the sonos and start playing a specific playlist, so I would hope it would be possible.

That sounds really odd. If the zones return an empty array, that means the system hasn't been discovered. Are you sure the application isn't constantly restarting for some reason? Try to get the output from stdout when running it, and file an issue at github for it, and I'll take a look.
Thanks so much for providing this API! It is really cool! I'm working on creating a node.js app with a scheduler to turn on my music automatically. I've noticed that occasionally when I give pause and resume commands to my sonos using my computer it will not do anything. If I try to hit the URL and do /zones or anything it will just return a blank array [] . Then, if I hit the play button on the actual sonos it will start working again and will receive commands. Is this a known issue or do you think something could be wrong with my sonos? My whole idea is based around my node server being able to wake up the sonos and start playing a specific playlist, so I would hope it would be possible.

That sounds really odd. If the zones return an empty array, that means the system hasn't been discovered. Are you sure the application isn't constantly restarting for some reason? Try to get the output from stdout when running it, and file an issue at github for it, and I'll take a look.


I looked a little further and it looks like it does return zones. But, if I try pauseall or resumeall using the URL in chrome it doesn't do anything and returns the [] that I mentioned. The app output shows 'resuming all players' each time I make the http request, but nothing happens. If I go over and hit the pause button on the sonos it will resume playing just fine. By output from stdout do you mean a logging file or simply the command line output that is generated?
Userlevel 4
Badge +14
With stdout I mean the command line output from the server console. For the raspberry image, this is redirected to a log file, but if you are running it manually, it would print out directly to the console.
Hi,
really great job - I got your api working on my RaspberryPi.

But there are a few things open which I couldn't find out. Maybe I'm blind :-)

I get an event every time the current track changes. That works fine. I can save the json element of the state. Now I like to play a track again. But how can I start a specific track? My tracks are from my music library, from spotify and from apple music. Those tracks aren't saved in any playlist or favorite list.

What I'm doing wrong? Can someone post an example for me?

Regards
Badge
Some really great work you've done here!
Yesterday I installed it on a Raspberry PI running Windows IoT Core and it worked without any changes at all!
Userlevel 4
Badge +14
Hi,
really great job - I got your api working on my RaspberryPi.

But there are a few things open which I couldn't find out. Maybe I'm blind :-)

I get an event every time the current track changes. That works fine. I can save the json element of the state. Now I like to play a track again. But how can I start a specific track? My tracks are from my music library, from spotify and from apple music. Those tracks aren't saved in any playlist or favorite list.

What I'm doing wrong? Can someone post an example for me?

Regards


I'm not really following your question. You need to provide more details for me to be able to help you. "Event every time", are you using the webhook?

Tracks are usually part of the queue, So you usually just do a trackSeek to the correct trackNo if you want to jump back and forth between sources, but I'm guessing that is not what you are asking. Again, if you could be more specific and paint the scenario, I might be able to give you an answer.
Userlevel 4
Badge +14
Some really great work you've done here!
Yesterday I installed it on a Raspberry PI running Windows IoT Core and it worked without any changes at all!


Are you saying that this works without any issues with the Chakra engine version of node.js? That's good to know!
Badge
Some really great work you've done here!
Yesterday I installed it on a Raspberry PI running Windows IoT Core and it worked without any changes at all!


Are you saying that this works without any issues with the Chakra engine version of node.js? That's good to know!


Yepp 🙂 I installed the Node.js addition to Visual Studio from here: https://github.com/ms-iot/ntvsiot. Then I created a new project of the type "Basic Node.js Web Server (UWP)", copied all the files from your project and deployed to the PI with Windows IoT Core.



It just worked!
Badge
Hi jishi!
Is there a way to know when the dicoveryprocess i done? Maybe a webhook?
Userlevel 4
Badge +14
Hi jishi!
Is there a way to know when the dicoveryprocess i done? Maybe a webhook?


You will receive a topology-change webhook as soon as it has discovered your system, if you have defined a webhook. So yes, there is.
Hi,
really great job - I got your api working on my RaspberryPi.

But there are a few things open which I couldn't find out. Maybe I'm blind :-)

I get an event every time the current track changes. That works fine. I can save the json element of the state. Now I like to play a track again. But how can I start a specific track? My tracks are from my music library, from spotify and from apple music. Those tracks aren't saved in any playlist or favorite list.

What I'm doing wrong? Can someone post an example for me?

Regards


I'm not really following your question. You need to provide more details for me to be able to help you. "Event every time", are you using the webhook?

Tracks are usually part of the queue, So you usually just do a trackSeek to the correct trackNo if you want to jump back and forth between sources, but I'm guessing that is not what you are asking. Again, if you could be more specific and paint the scenario, I might be able to give you an answer.


Hi jishi,
thanks for your response.

Let me try to explain better what I like to do. Sorry for my late response and my bad english.

I've installed your http-api on a RaspberryPI and I'm using the webhook.
So I get a call every time a new song gets played at one of my players. This works very fine. I'm saving the message data (ok, not the whole message) to a database (mongdb). I've written an Android app which displays all saved entries from that database.

Now I like to play one of those songs. My tracks are coming from AppleMusic, a local library and maybe Spotify in the future. I know from where a song originally comes from.

Since my last post here I've found some solutions:

For songs from AppleMusic I found the following command
code:
/RoomName/applemusic/{now,next,queue}/song:{songID}

With this command I'm able to play a song from AppleMusic.

For songs from Spotiy, there must be the following command. I couldn't test it since now, because I currently have no Spotify account:
code:
/RoomName/spotify/now/spotify:track:4LI1ykYGFCcXPWkrpcU7hn


And finally for my local library I've found the following commands.
code:
/Playroom/musicsearch/library/song/red+hot+chili+peppers+dark+necessities

This command is a "search" command. It is searching for a song that matches the criteria. The command is working, but it is not that what I want. So I'm looking for a better way to select and play a specific song from my local library.


I would be very happy if you can support me with some hints.

Many thanks
Regards
Userlevel 4
Badge +14

And finally for my local library I've found the following commands.
code:
/Playroom/musicsearch/library/song/red+hot+chili+peppers+dark+necessities

This command is a "search" command. It is searching for a song that matches the criteria. The command is working, but it is not that what I want. So I'm looking for a better way to select and play a specific song from my local library.


I would be very happy if you can support me with some hints.

Many thanks
Regards


There is no convenient way to "queue and play" form local library today. It would make sense to support that in the same manner as the music services, I just haven't looked at it. I'll create an issue for it in github and look at it when I get the time. It's a good suggestion.

There is no convenient way to "queue and play" form local library today. It would make sense to support that in the same manner as the music services, I just haven't looked at it. I'll create an issue for it in github and look at it when I get the time. It's a good suggestion.

that would be great.

Many thanks to you. You did a really great job.
Badge
Hi @jishi,

Thanks for the library. I have working with it for a while, trying to understand the code. I am experimenting to build an Angular2 service out of it - with Observables (first experiments on https://github.com/Tommertom/ng2sonos).

I am struggling to understand how you get to all the data from the Sonos system. For example, the AlbumArtUri for a Radio stream. I have put some trackers on the soap.invoke method to see if that returns values, but it doesn't. Where do you get that data from? And how many soap calls are needed to build the Sonossystem data tree (volume, position, etc.)?

Anyway, hope you can indicate where I can find this in the code.

Regards,

Tom
Userlevel 4
Badge +14
Hi @jishi,

Thanks for the library. I have working with it for a while, trying to understand the code. I am experimenting to build an Angular2 service out of it - with Observables (first experiments on https://github.com/Tommertom/ng2sonos).

I am struggling to understand how you get to all the data from the Sonos system. For example, the AlbumArtUri for a Radio stream. I have put some trackers on the soap.invoke method to see if that returns values, but it doesn't. Where do you get that data from? And how many soap calls are needed to build the Sonossystem data tree (volume, position, etc.)?

Anyway, hope you can indicate where I can find this in the code.

Regards,

Tom


Hi Tom.

Most of the data is actually "evented" from the players, meaning that they do HTTP POST requests to my software with state changes. That's why you don't see them on the soap.invoke calls, because those are mostly explicit calls for action from the user (play, pause, skip change track etc). The only exception to that is the GetPositionInfo call which is used periodically to "sync" the current state, in case it has gotten out of sync. The code that is responsible for handling these requests are the NotificationListener, which emits it and then each player handles their own data to update their state.

You also need to subscribe to the events, in order to make the Sonos players send these requests. This is handled in the Subscriber class.

Hope that helps!