Spotify of Things Button
Setting up the Lambda
Before you do anything in AWS, make sure you're in the correct region for your AWS Console. If you use the IoT mobile app to setup your button, the only regions it currently supports are:
N. Virginia (us-east-1)
So you want to make sure you're using one of the above regions in your AWS Console. I spent about two hours trying to figure out why I wasn't seeing my button's messages, but finally realized my console was on us-east-2, but my button was on us-east-1. Once you're using the correct AWS region, go ahead and create an empty Lambda. Look for the Lambda Service in the AWS console, and find the "Create function" button. We'll create a function from scratch using Node.js 8.10.
We'll need to get an access token from Spotify before we can do anything fun. Spotify has a few different authorization flows you can follow, but they suggest using the authorization code flow for what we're doing. Follow the four steps to get your authorization code. Make sure you request the following scopes for your token: playlist-modify-private, playlist-modify-public, and user-read-currently-playing. There are two values you'll need to save so that you can use them in your lambda, the encoded client_id and client_secret you use in step two, and then the refresh_token you get at the end of step two. Once you have those, go ahead and store them under the "Environment Variable" section of your lambda. While you're here, you can also get the playlist IDs you'd like to add songs to. You can find them using Spotify's console, and go ahead and save them as environment variables as well.
Calling Spotify's API
We'll first need to setup the call to refresh the token. The Spotify access_token you get from step two of the authorization flow actually expires ever so often. So we'll actually refresh the token every time an event happens and save the access_token in an environment variable programmatically.
You notice the process.env.ENCODED_CLIENT and process.env.REFRESH_TOKEN, that is how we access the environment variables we saved in the previous step. You also want to make sure you have the correct Content-Type set in the header. This particular endpoint required we use x-www-form-urlencoded; which is really similar to how query string parameters are used in URLs. We can now call this function from the handler. You may notice that just like how we can access environment variables, we can save them too. So we get the access_token from the body of the response and store it in process.env.ACCESS_TOKEN.
Next is getting the currently playing song and adding it to a playlist of our choice. The actual code for both of these request are really similar to the refresh token request. The difference is the header and the request body.
I did stumbled around writing the HTTP requests for couple of hours. I was originally trying to use the AWS SDK to write a custom AWS service. It seemed pretty slick, so I wanted to give it a try. The problem was that the examples I found were for pretty basic requests and I couldn't find the documentation I needed for what I wanted to do. I finally decided to pivot and just use Promises and the https library. Once I got the first request working, the rest was a breeze.
You can see the full code here.
Setting up the IoT Button
Now the easy part! All you have to do is follow the first eight steps of this tutorial. "Configure and Test Rules" and "Create and Track an AWS IoT Job" are not necessary since we're using a Lambda and already have our code written. During the "Configure Your Device" section, you should see the Lambda you just wrote as an option during setup. If you're ready to test out your lambda and button, WHAT ARE YOU WAITING FOR?! If not, go ahead and select one of the pre-build lambdas to test and make sure the button's configuration is correct.
And that's it! The most time consuming parts were trying to figure out how to use the custom AWS service, and the time wasted using the wrong AWS region 🤦🏻♀️. This was a super fun and easy weekend project. I'd be interested to see what other have done with IoT buttons and maybe get some ideas for a Skunkworks project. Really, this whole thing has me a little bit excited as to what kind of projects I could do with hardware and external devices.