Using your Amazon Echo to control a Sonos system
Amazon and Sonos announced late last year that 2017 would finally see the arrival of native Sonos control via the various Alexa products. 2017 is a very vague timeline, and I wanted that power now; enter Raspberry Pi (or any home internet connected machine that can be a web server), Alexa Skills and AWS Lambda. All of the code for this is in my GitHub (pardon the hacky python code): https://github.com/kylefowler/sonos-alexa-skill
The flow of how it all works goes something like this:
- “Alexa, ask Sonos to start playing in the kitchen”
- Amazon makes a request to your lambda function to get the response.
- Lambda function makes a request to a small web API running on your Raspberry Pi.
- Raspberry Pi runs the action on your kitchen Sonos.
- Music starts playing and the Alexa interaction is done!
Note: This all assumes a cursory knowledge of programming and working with a linux system.
Setting up your Raspberry Pi. For this you will need an internet connected machine with Python installed. I ended up adapting one of the web samples from the great SoCo library which is the driver behind the actual interaction with the Sonos speakers. It is a Flask python web app that serves up the API that our AWS Lambda function will talk to.
- In settings.py, set DEFAULT_PLAYER to the name of the speaker you want to play from when you talk to Alexa (so you don’t have to say something like “in the kitchen”).
- Music services: Right now I only have a Spotify account linked to my Sonos system so I only bothered to support one music service in my hack. If you want another, edit the index.py file to use a different music service.
- Exposing your web server to the world. You can do this however you like if you have experience with it. Personally I’ve grown fond of ngrok, as an easy way to expose my localhost projects to the world. It gives you a secure public URL that your Lambda function points to and a nice dashboard to look at all the incoming requests for debugging. You will need this URL later when configuring the environment variables on your lambda function.
On the Pi you should install tmux so you can keep all the processes alive when you disconnect your SSH session.
You can now test out your controls by going to your browser and hitting the URL ngrok gave you with something like http://url.com/info to get the information about the currently playing song.
Creating your AWS Lambda function. At this point we need to take a detour over to Lamba to set up our Lamba function so that in the next step of the Skill setup we have something to point it to for testing. Go to your lambda dashboard here and click on “Create a Lambda Function”. Next you will configure an Alexa Skills Kit trigger for invoking this Lambda function.
Hit “Next”, and then name your function, give it a description and select a runtime of Python 2.7. Under “Code entry type” you want to pick upload a ZIP file, and upload the zip file found in the GitHub repo which contains the Lambda function and the Requests Python dependency. https://github.com/kylefowler/sonos-alexa-skill/raw/master/lambda-function/bin/lambda-function.zip
After uploading the code, the last configuration step you need for your Lambda function is to setup an environment variable for your function that refers to the web server you setup earlier.
Setting up your Amazon Skill. I’ll spare the full details here but, you should follow the Getting Started guides on the Amazon developer site for creating a “Custom Skill”. Once you have created a skill, head over to the skill information page where you can name it and decide how it will be invoked aka the “Alexa, ask Sonos” part.
Next head to the interaction model section, which is where you will define the grammar for talking to your Skill. The top section is where you define the intents that your Skill can handle. For the Sonos skill you will want to add the ones below.
In those intents are a few custom slot types where you can define the locations of your Sonos speakers. For example I have a kitchen Play:3 and a bedroom Play:3 so I’ve added locations for those.
The final step before testing the whole thing is configuring your Skill to talk to your Lambda function. In the Configuration section of your Skill setup you will point it to your lambda resource name.