Pinterest Stumbleupon Whatsapp
Ads by Google

The dream of any smart home enthusiast is a home you can talk to, but the reality is a long way off from that.

Amazon Echo, for instance, allows you to use any number of voice controlled features, but dialog must be initiated by you with a question – you can’t just have her announce an important message.

You can do this with a Sonos system though, and a bit of DIY Raspberry Pi magic. Today I’ll show you how to set up voice notifications on your Sonos system, introducing a couple of useful IFTTT recipes, OpenHAB integrations, and more, to make use of the notification feature.

Note that there is a native Sonos binding for OpenHAB available, but it’s known to cause memory issues due to a faulty uPnP library. I’d suggest skipping that for now, and using the method in this tutorial instead.

A Raspberry Pi running Raspian linux is ideal for this tutorial, but it should also work on any linux-based home server you have running. In this case, I’m using the same Raspberry Pi that runs OpenHAB, the open source home automation system Getting Started with OpenHAB Home Automation on Raspberry Pi Getting Started with OpenHAB Home Automation on Raspberry Pi OpenHAB is a mature, open source home automation platform that runs on a variety of hardware and is protocol agnostic, meaning it can connect to nearly any home automation hardware on the market today. Read More . The rest of this tutorial assumes you’re also running this on a Raspberry Pi, and either have a local terminal window open on the desktop, or are logged-in remotely using SSH Setting Up Your Raspberry Pi For Headless Use With SSH Setting Up Your Raspberry Pi For Headless Use With SSH The Raspberry Pi can accept SSH commands when connected to a local network (either by Ethernet or Wi-Fi), enabling you to easily set it up. The benefits of SSH go beyond upsetting the daily screening... Read More .

You’ll Need

  • Raspberry Pi 2 (older models should work, but check for specific changes in the instructions)
  • At least one Sonos speaker (other audio systems are not supported, this is a tutorial for Sonos only)
  • Free account at VoiceRSS.org. Register then find your API key, which we’ll need later to generate the voice messages.

Install Node Latest

Check which version of Node you have by typing:

Ads by Google
node -v

Note that version 6 is not supported. If you have Node 6, you’ll to first remove it, then follow the instructions below to install v5.5. 

If you don’t have v5 or if you get a not found error, follow these instructions to install Node. The following command assumes a Raspberry Pi 2; for older models, use armv6l instead of armv7l.

wget https://nodejs.org/download/release/latest-v5.x/node-v5.12.0-linux-armv7l.tar.gz
tar -xvf node-v5.12.0-linux-armv7l.tar.gz
cd node-v5.12.0-linux-armv7l
sudo cp -R * /usr/local

Confirm again by typing:

node -v

And you should see v5.12 (or whatever the latest was that you downloaded).

Next, we have some Node modules to install. We also want the Node Package Manager.

sudo apt-get install npm
sudo npm install -g npm
sudo npm install -g node-gyp

That’s the pre-requisites out of the way, now onto the fun stuff.

Sonos HTTP API

The Sonos HTTP API creates a web server on the local network, which allows us to ping a URL with a message to announce on a Sonos (and to control it remotely if you want, though this tutorial focuses only on the voice notification aspect).

git clone https://github.com/jishi/node-sonos-http-api.git sonos
cd sonos
npm install --production
npm start

If you see a message about such-and-such module not found, just do another npm install and the module name, then try npm start again. If you experience errors relating to “requires a C++11 compiler”, fix with the following commands:

sudo apt-get install gcc-4.8 g++-4.8
sudo update-alternatives --install/usr/bin/gccgcc/usr/bin/gcc-4.6 20
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.6 20
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50

Eventually you should see something like this:

sonos-http-api working

The server is now running, interfacing with Sonos. The format of this API is easy:

http://[SERVER IP]:5005/[ROOM NAME]/[ACTION]

Or as a specific example:

http://192.168.1.99:5005/kitchen/playlist/chillout

The action we’re interested is the “say” command, used as follows:

http://192.168.1.99:5005/kitchen/say/make%20use%20of%20is%20awesome/en-gb

You’ll hear an error message about having to register to an API key at VoiceRSS.org. You should have already done this, so type out the following and paste in your API key as appropirate:

nano settings.json

{

 "voicerss":"YOURAPIKEY"
}

(Hit CTRL-X, Y, to save the file)

Restart the server, and ping the URL again. After a few seconds, you should hear a delightful English voice (though you change the end of the URL to en-us if you’d rather). To make the Sonos HTTP API server start again when the Pi is restarted:

sudo nano /etc/rc.local

Add a line before the exit 0:

sudo node /home/pi/sonos/server.js < /dev/null &

You now have the ability to create a voice message from anywhere on the local network simply by pinging a URL, so the possibilities are wide open at this point. If you’re struggling for ideas though, read on for a few useful notifications I’ve got set up.

OpenHAB Notifications on Events

Let’s take a simple example first: motion detection. This is a common use case for activating lights, but you might want a voice notification too if it’s a motion sensor in a low-traffic area, or perhaps as a forward warning that someone is coming up the garden path.

rule "Garden motion detected"
when
  Item Garden_Motion changed 
then
  var String message = "You have a visitor"
  sendHttpGetRequest("http://localhost:5005/kitchen/say/"+message.encode("UTF-8")+"/en-gb")
end

You should see how you can integrate these simple voice notifications into any of your rules, but let’s try something a little more complex.

Daily Weather Report from IFTTT to OpenHAB to Sonos

In this recipe, we’ll have Sonos announce a daily weather report at your prefered time.

You’ll need the My.OpenHAB binding enabled, since this creates a secure connection between your internal OpenHAB server and the external IFTTT service. Set that up if you haven’t already – you can refer to part 1 of our OpenHAB guide Getting Started with OpenHAB Home Automation on Raspberry Pi Getting Started with OpenHAB Home Automation on Raspberry Pi OpenHAB is a mature, open source home automation platform that runs on a variety of hardware and is protocol agnostic, meaning it can connect to nearly any home automation hardware on the market today. Read More for full instructions, otherwise I’ll assume you’ve already got it setup with persistence enabled for all items.

Next, create a new String item in your OpenHAB install, which will store the daily weather report. Before this is visible in the My.OpenHAB channel, we’ll need to initialize it with some default variable. Ping the following URL (change raspberrypi.local to your OpenHAB server, or just use it’s IP address, and Todays_Weather to whatever you named the String):

http://raspberrypi.local:8080/CMD?Todays_Weather=Sunny  

Log in to My.OpenHAB and check the Items list to ensure the variable has now been exported.

my openhab item export check

Back on IFTTT, create a new recipe, and use the Weather channel as the trigger at your preferred time of day. You’ll need to set your location first if you’ve never used it before.

Select My.OpenHAB as the action, and choose the Todays_Weather as the variable to update.

ifttt weather report

For now, just pick the next half hour slot for testing – you can update the recipe later once you know it’s working.

Sure enough, at the test time (in fact, a little before), I got today’s forecast updated successfully.

2016-02-27 10:28:01.689 [DEBUG] [o.o.i.m.i.MyOpenHABServiceImpl] - Received command Mostly Cloudy today! With a high of 7C and a low of 1C. Repeat. Conditions will be Mostly Cloudy today, with a high of 7C and a low of 1C. for item Todays_Weather
2016-02-27 10:28:01.697 [DEBUG] [o.o.i.m.i.MyOpenHABServiceImpl] - store(Todays_Weather), state = Mostly Cloudy today! With a high of 7C and a low of 1C. Repeat. Conditions will be Mostly Cloudy today, with a high of 7C and a low of 1C.

Next up, we need an OpenHAB rule to send this variable to the Sonos “say” URL. The following should do it:

rule "Announce daily weather report"
when
  Item Todays_Weather received update
then
  sendHttpGetRequest("http://localhost:5005/kitchen/say/"+Todays_Weather.state.toString.encode("UTF-8")+"/en-gb")
end

This is simple enough: whenever the Todays_Weather variable is updated (which it will be, automatically, at 8am every day), ping the URL. We use encode(“UTF-8”) String function to make the sentence from IFTTT suitable for use in a URL. To manually test this part of the system, just use the OpenHAB HTTP API again:

http://raspberrypi.local:8080/CMD?Todays_Weather=Cloudy, with a chance of meatballs.

Connect to IFTTT Without OpenHAB, Using If-This-Then-Node

Finally, let’s look at how to connect from any IFTTT recipe without the OpenHAB intermediary. Instead, we’ll install another web server, and expose that to the open Internet. This is not without risk: any kind of open server is a security risk, but we’re mitigating this by not running a complete server stack, just a small specific service that only accepts certain commands in a safe JSON data packet format (so no SQL injection or authentication attacks will be possible). Once we’re done, you’ll have a public URL to which you can send messages from the IFTTT Maker channel.

Start by setting up one of the many free dynamic DNS services 5 Best Dynamic DNS Providers You Can Lookup for Free Today 5 Best Dynamic DNS Providers You Can Lookup for Free Today DynDNS was always a top mention when free dynamic DNSes were brought up. But now that it's gone, are there any good alternatives? There sure are. Read More out there – I recommend DuckDNS, specifically because it gives a simple set of instructions for Raspberry Pi, enabling it to update your IP adddress automatically. Follow along with these, and remember your URL for the next steps. Your router may also have a dynamic DNS function built-in, so check there first. In my case, I can get a *.mynetgear.com URL for free, so I’ve used that.

Next, find your router’s port forwarding What Is Port Forwarding & How Can It Help Me? [MakeUseOf Explains] What Is Port Forwarding & How Can It Help Me? [MakeUseOf Explains] Do you cry a little inside when someone tells you there’s a port forwarding problem and that’s why your shiny new app won’t work? Your Xbox won’t let you play games, your torrent downloads refuse... Read More configuration page; this is where we’ll tell it what to do with incoming requests. Forward all HTTP requests (port 80) to port 1337 on your Raspberry Pi server. I’m assuming you’ve got a IP address reserved already for your Raspberry Pi – if you haven’t, check your router’s config page for reserved IPs while you’re in there, as you don’t it to change next week and for the server to suddenly stop working.

router config port forwarding

Now to install the last bit of server software.

https://github.com/sebauer/if-this-then-node.git
cd if-this-then-node/
npm install
node server.js

You should see the following.

if this then node default values error

That’s ok, that just means we need to update our details. Open up config.js in Nano and edit those details to anything other than the default, then save. When you run the server again, you should see this:

if this then node server running

Great. Test your machine is accessible from the outside world by typing in your dynamic DNS hostname, and append /ifttn/ to the end of the URL. If everything works, the message “IFTTN – if-this-then-node Version 2.0.1 is up and running!” will be displayed in you browser. Again, to make this script run on start-up, edit the /etc/rc.local file and add:

sudo node /home/pi/if-this-then-node/server.js < /dev/null &

If-This-Then-Node works through plugins – there’s a few default ones supplied, but there aren’t of interest to us. Instead, download this custom plugin that I’ve written for you with the following commands.

cd plugins
wget https://gist.githubusercontent.com/jamesabruce/4af8db24ba3452b94877/raw/d11c1cff3aa44dbb6a738eeb15202f3db461de75/sonos.js 

You’ll also need to install the request module.

npm install request

Then restart the server. The plugin is quite simple, but a little different to the URL we’re used so far. In this case, I’ve used the special “sayall” action, which sends the message to every Sonos device.

request('http://localhost:5005/sayall/'+params.message+'/en-gb', function (error, response, body)

If you’d rather be able to target specific devices, replace that line with:

request('http://localhost:5005/'+params.device+'/say/'+params.message+'/en-gb', function (error, response, body)

Add another line parameter called device to the JSON request below in which to specify the Sonos device name.

To test this out, I’m using the IFTTT “Do” button app. Create a new recipe, browse to channels, and select the Maker channel.

do button

Create a new recipe. Enter in the URL you configured earlier from a free dynamic DNS provider (including /ifttn/ at the end of the URL. Don’t forget those slashes). Select POST request, application/json content, and the body of the message as follows, replacing all variables as needed with those you previously configured:

{ 
"action":"sonos", 
"user":"YOURUSER", 
"pw":"YOURPASSWORD", 
"message":"Incoming message for everyone: Dinner is ready! Repeat. Dinner is ready. Get your asses upstairs now." 
}

Now I have a readily accessible button that will announce the message on every Sonos device in the house. You can of course pair this with any IFTTT channel you want to make a custom message using variables from that channel. You should even be able to replicate the weather report from above without using OpenHAB now, though it did take the extra effort of installing another server.

Note: hackers will automatically scan you. This happens all the time, but if you’re viewing logs, it can seem alarming. Below you can see someone systematically tried to ascertain if any of the standard PHPMyAdmin interfaces were accessible. Which they weren’t. Don’t be alarmed if you see something similar. It’s the internet equivalent of cold calling random phone numbers to see if anyone’s there.

web server hack attempts

What Will You Announce?

You should now have the tools and kwowledge to constantly bathe your entire house in voice notifications about everything you could possibly think of. Who needs music? Your only limit is 350 daily requests from VoiceRSS.org – but that’s about one every 4 minutes, so you should be alright.

So what will you do with this? Share your ideas or IFTTT recipe in the comments!

Image Credits:coffee and woman by S_Photo via Shutterstock

  1. jishi
    September 15, 2016 at 1:47 pm

    The guide is completely wrong in regards to npm install procedure. Invoking npm install without any packet names, will install all dependencies listed in package.json, so replace this:

    npm install production
    npm install basic-auth sonos-discovery require-fu request-promise node-static async

    with only this:

    npm install --production

    And everything should work correctly. The dependencies changes over time, so this guide has become obsolete because of that.

    • James Bruce
      September 15, 2016 at 2:43 pm

      Thanks Jishi, for your awesome software, and for that correction. I'll update the guide now!

    • jishi
      September 15, 2016 at 3:03 pm

      You're welcome!

      You could also mention that there now is a pre-built SD-card image for all raspberry models available at http://jishi.github.io/node-sonos-http-api/ for much easier install if you can spare a dedicated raspberry pi.

  2. phate
    September 12, 2016 at 3:52 pm

    Hi,

    many thanks for the great tutorial!
    I've tried everything you suggested on a ubuntu server machine, but starting the api fails with the following output:

    phate@prometheus:~/sonos$ sudo npm start

    > sonos-http-api@1.0.0-beta.22 start /home/phate/sonos
    > node server.js

    no settings file found, will only use default settings
    module.js:341
    throw err;
    ^

    Error: Cannot find module 'fuse.js'
    at Function.Module._resolveFilename (module.js:339:15)
    at Function.Module._load (module.js:290:25)
    at Module.require (module.js:367:17)
    at require (internal/module.js:20:19)
    at Object. (/home/phate/sonos/lib/music_services/libraryDef.js:2:14)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:20:19)
    at Object. (/home/phate/sonos/lib/actions/musicSearch.js:9:20)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)

    npm ERR! Linux 4.4.0-36-generic
    npm ERR! argv "/usr/bin/nodejs" "/usr/bin/npm" "start"
    npm ERR! node v5.12.0
    npm ERR! npm v3.10.7
    npm ERR! code ELIFECYCLE
    npm ERR! sonos-http-api@1.0.0-beta.22 start: `node server.js`
    npm ERR! Exit status 1
    npm ERR!
    npm ERR! Failed at the sonos-http-api@1.0.0-beta.22 start script 'node server.js'.
    npm ERR! Make sure you have the latest version of node.js and npm installed.
    npm ERR! If you do, this is most likely a problem with the sonos-http-api package,
    npm ERR! not with npm itself.
    npm ERR! Tell the author that this fails on your system:
    npm ERR! node server.js
    npm ERR! You can get information on how to open an issue for this project with:
    npm ERR! npm bugs sonos-http-api
    npm ERR! Or if that isn't available, you can get their info via:
    npm ERR! npm owner ls sonos-http-api
    npm ERR! There is likely additional logging output above.

    npm ERR! Please include the following file with any support request:
    npm ERR! /home/phate/sonos/npm-debug.log

    When checking, the js is actually there:

    phate@prometheus:~/sonos$ cd node_modules/fuse/bin/
    phate@prometheus:~/sonos/node_modules/fuse/bin$ ls -al
    insgesamt 20
    drwxrwxr-x 2 phate phate 4096 Dez 10 2013 .
    drwxrwxr-x 6 phate phate 4096 Sep 12 17:27 ..
    -rwxrwxrwx 1 phate phate 2467 Dez 10 2013 fuse.js

    I tried around a lot, including (re-)installing fuse again via npm install -g fuse and this only brings up some warning about minimatch - no error or anything.

    phate@prometheus:~/sonos$ sudo npm install -g fuse
    npm WARN deprecated minimatch@0.0.5: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
    /usr/bin/fuse -> /usr/lib/node_modules/fuse/bin/fuse.js
    /usr/lib
    ??? fuse@0.4.0

    Do you happen to have an idea what might be the root of all evil?
    npm is version 3.10.7 and node-v reveals v5.12.0 (just as in your tutorial).

    I tried a lot in order to solve this problem, but did not yet have any success. It would be really great if someone had an idea. Many thanks in advance!

  3. Jonathan Mutnick
    August 16, 2016 at 3:14 pm

    Will this work on a ZonePlayer 80?

    • James Bruce
      August 16, 2016 at 3:34 pm

      From what I can tell, it *should*.

  4. Fabian
    August 10, 2016 at 7:03 pm
    • James Bruce
      August 16, 2016 at 3:34 pm

      Thanks Fabian, will update now

  5. Juergen Baginski
    April 26, 2016 at 6:41 pm

    Works cool, thanks.
    Since I had the Sonos-Binding in use at the start it didn't work. After unistalling that, it did.

  6. Eric Williams
    March 23, 2016 at 6:02 pm

    Pretty sweet write up... There's also a company working on an app that does this without the need of raspberry pi and a bunch of technical configuration. Check it out at Sonofy.co... They have a private beta going on right now

    • James Bruce
      March 24, 2016 at 9:34 am

      Looks cool, but worth noting that without a hub or Raspberry Pi, this will require your phone to be on (generating the notifications from an app), and for you to be at home, which is quite limiting compared to this method.

      • Eric Williams
        May 3, 2016 at 1:17 am

        True...worth noting. However, it's a better option for non-hackers that have an extra android phone laying around that they could leave at the house for home notifications.

Leave a Reply

Your email address will not be published. Required fields are marked *