Yesterday we showed you how to create a DIY Wi-Fi light that could be controlled with Siri; today we're going to build on that knowledge to make Siri to work with a Sonos sound system too, then put it all together in a romantic scene.

Check out the end result:

The video above was not faked, or staged -- everything is possible using Siri, and the guide below. No jailbreak is required, though there is some programming, for which I've provided the code.

Things You'll Need:

  • Raspberry Pi
  • iOS device
  • Siri-compatible coloured lighting, such as Philips Hue with a 2nd generation hub, or our DIY Wi-fi Light
  • Sonos (or other playback device with an HTTP API)
  • (Optional) NodeMCU/ESP8266, relay, and power sockets; or a commercial HomeKit power socket accessory

Why is This So Complicated?

HomeKit, and controlling your devices through voice control is really neat. Unfortunately, the closed ecosystem that Apple is, HomeKit is restricted to a handful of devices. Sonos is not one of them. However, all is not lost. Thanks to some hardworking hackers, the HomeKit protocol was recently reverse engineered, and as demonstrated in our last project, you can now create your own fake HomeKit devices. We'll be taking advantage of that.

Start by following our DIY Wi-Fi light tutorial, because that's going to form the basis of everything else. In fact, if you don't already have a Philips Hue lighting system, you can go ahead and actually build the Wi-Fi light described in that tutorial.

Even if you do have a Hue system, go ahead and follow the tutorial because you'll need to create fake HomeKit accessories for everything else (code provided below). By continuing with this guide, I'm going to assume you've got the HAP-NodeJS server running already, and have successfully added a fake light and tested out the server, even if it isn't connected to an actual bit of DIY hardware.

Make a Playlist

Go ahead and create a new Sonos Playlist named "Romantic". It doesn't need to be exactly the same name, but you'll have to adjust the accessory scripts later if you do change it. I've added some Marvin Gaye and Sade tracks to mine. Smooth.

Next, over on the Raspberry Pi that's running HAB-NodeJS (if you don't know what I'm talking about, you didn't read the Wi-Fi light tutorial. Do that first), navigate to your home directory and type the following to install the HTTP API for Sonos. This is going to give us a web URL that we can ping to trigger certain actions on the Sonos.

        git clone https://github.com/jishi/node-sonos-http-api.git sonos
cd sonos
npm install production
npm install basic-auth sonos-discovery require-fu request-promise node-static async
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. It's possible I already had some modules installed globally from other projects, and you may need to install more. Hopefully you'll see something like this:

sonos-http-api working

Congratulations, you now have a simple HTTP API you can use to trigger your Sonos. Read up on the documentation for the full list of commands, but the format we're most interested in is:

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

or as a specific example:

http://192.168.1.99:5005/master%20bedroom/playlist/romantic

Case doesn't appear to matter. The %20 is a URL encoding of a space character, but you should be able to type an actual space too, and your browser will automatically convert it. The command above simply triggers the Romantic playlist to the Master Bedroom device. Use the pause command to stop it:

http://192.168.1.99:5005/master%20bedroom/pause

Aside, the API also gives us a function that will come in really handy for other projects: the ability to say a specific statement, like a notification, then continue playing the current queue. Try:

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

The first time you do this, you'll get an message about having to register to an API key at VoiceRSS.org [No Longer Available] (up too 350 requests per day are free). When you're done with that, type:

        nano settings.json
    

and paste in your key to the following example:

        {
 "voicerss":"YOURAPIKEY"
}

Restart the server, and ping the URL again. After a few seconds, you should hear a delightful English voice. You can change the end of the URL to en-us if you prefer an American voice. Neat! Totally irrelevant to this project, but neat anyway!

Finally, let's make this 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 &
    

CTRL-X, Y to save. You can see I'm running this alongside OpenHAB, a DIY Bluetooth presence detector, and the HAP-NodeJS HomeKit server -- you should also have that running already if you followed the prerequisite Wi-Fi light tutorial already.

add to rc-local

Making a HomeKit Device for the Sonos

The crux of this project is that Sonos cannot be controlled by Siri, however we can add some degree of control by creating a fake HomeKit device that activates a particular playlist when we turn it on – a fake light is the easiest way to do this.

Navigate to your HAP-NodeJS/ directory first, and install the "request" module.

        sudo npm install request
    

Then jump down to the accessories/ directory and grab my premade fixture with the following simple command:

wget https://gist.githubusercontent.com/jamesabruce/72bd250fbcf054acaa25/raw/8272d4b9a4ef76db752cab2ddd9bdc47d09a65f1/Romantic_accessory.js

Make some changes if you need to -- this is set for the default Sonos "Master Bedroom" location, so change the string master%20bedroom toward the start of the code if you want it to be directed to a different room. Since we've faked being a light, sending the brightness command won't actually do anything, though at some point I'll update that to deal with volume. This is the code block that does the magic:

        setPowerOn: function(on) { 
    console.log("Turning the light %s!", on ? "on" : "off");
    FAKELIGHT.powerOn = on;
console.log(on);
    if(on){
        request('http://localhost:5005/master%20bedroom/playlist/romantic', function (error, response, body) {
          console.log("Sent play request");
        })
    }
    else{
        request('http://localhost:5005/master%20bedroom/pause', function (error, response, body) {
          console.log("Sent pause request");
        })
    }
  },

You can see it's surprisingly simple: when the light receives a setPowerOn command from HomeKit, it checks to see if the value is 1 (or true), and which point it pings the Sonos HTTP API url to play that playlist. If it's anything else (ie. 0, false), it sends the pause command. Restart your HAP-NodeJS server, then head on over to an iOS device and follow the same procedure as before to add your fake "Romantic Playlist" light (you'll need the pairing code 031-45-154).

Check your new device is working, then move on. If you're feeling up to a little programming, try mapping the brightness changes to volume (and share your code in the comments, please!).

(Optional) Fairy Lights and Other AC Devices

It may surprise you to learn that there aren't any official HomeKit fairy lights, nor could I find any HomeKit generic power sockets that I liked the look/price of – so I knocked together a DIY one using a NodeMCU/ESP8266 dev board, a relay, and a standard two-gang power socket. I won't detail the hardware too much as you shouldn't be putting things inside plug sockets if you're not totally confident with that kind of thing, but I will provide you with my code for the NodeMCU side of things (connect the relay trigger to pin D2/GPIO4), and the accessory to go with it.

nodemcu relay

Like the Wi-Fi light, this communicates commands on an MQTT channel ("bedroomplug"), so you'll need to modify the code with your MQTT broker address (check out part 2 of our OpenHAB guide on how to set up an MQTT broker), change the channel names if you wish, and of course enter your own Wi-Fi details.

Putting it All Together

Finally, we're going to make some "scenes" using the Elgato Eve app, or your preferred HomeKit manager. In HomeKit parlance, a scene can consist of any number of accessories and commands to those accessories.

You can name a scene whatever you like, and Siri will be able to match it even without saying "set scene". So I've made two scenes: one called "the kids are in bed", and another "let's get serious now".

The former turns off one of the Hue lights, turns the other to pink, then turns on the romantic playlist accessory and the fairy lights. The latter makes the lights white again, and pauses the Sonos (ie, turns off the romantic playlist accessory). Simples!

homekit scene creation

 

I hope you've enjoyed this tutorial, and can really see how we can extend Siri control to anything without too much trouble, thanks to the power of HAP-NodeJS. Is there something you'd like to see some special Siri actions for? Let us know in the comments, and tell us how you've been using Siri to control your home.