We just moved into a new house, and for a house-warming present we gifted ourselves an Amazon Echo -- the future hub for our IoT-decked-out home.
It took less than a week for me to commandeer the cloud-enabled, voice-controlled speaker and begin hacking it to my will.
Even before the Echo, one of the first things I set up at our house was a Photon/Weather Shield/Weather Meter-based weather station. It's posting once-a-minute weather readings to my data.sparkfun.com stream. (Want to set up one of your own? There's a tutorial for that.)
The ease of asking Alexa how hot it is outside before I go on a Pokémon-hunting adventure is enticing, but she stubbornly believes I still live 50 miles north of my actual location. The uneven Colorado weather renders her reports generally useless. The obvious solution: teach my shiny new Echo how read from my data.sparkfun.com stream and give me a hyper-local weather report.
Alexa already has all sorts of home-automation and environment-monitoring skills, but they're all designed to work with proprietary services like SmartThings or WeMo. For my project, I needed something a little more customized.
There are a few DIY-type avenues for creating custom Alexa skills, most prominently If This Then That (IFTTT). There's an Alexa channel on IFTTT, from which you can connect to services like Particle or Maker to easily interface Alexa with your hardware.
If I had started from scratch, and didn't already have my weather station up and running, IFTTTing Alexa to the Particle channel would have been the quickest solution to my problem. Apparent masochist that I am, though, I decided to make the project a little harder on myself. Prompted by Amazon's wealth of documentation, tutorials, and sample code, I set out to create an Alexa skill of my own. After a little reading, and a lot of painful re-re-re-learning of JavaScript, I was successful!
Here is a quick primer on how I did it.
In creating my custom skill, I mostly followed along with Amazon's Steps to Build a Custom Skill guide, but there were a few trip-ups I encountered. Here are some tips for creating a data.sparkfun.com-reading Alexa skill like mine.
Creating an Alexa skill requires two back-end management systems. Both accounts are free to create, and one is optional.
AWS is an amazingly powerful service, and they offer a free tier, but a credit card is still required to make the account. AWS Lambda can be replaced by any host capable of running your code, but it'll require a bit more setup. Fortunately, Amazon has a Hosting a Custom Skill as a Web Service tutorial to help get you started.
Setting up the voice interaction interface for an Alexa skill is super straightforward. In Amazon's Developer Console, you click over to the Alexa tab, then click "Add a New Skill." Give the skill both a Name and an Invocation Name. The invocation name is what you say to Alexa to have her run your skill. By assigning my skill the invocation name my weather station, I was more naturally able to ask Alexa to "get the temperature from my weather station."
Next you create an interaction model. This pairs a "Sample Utterances" text file with a JSON-encoded "Intent Schema." These files map phrases you say to Alexa with the interface code we'll be writing next.
The final step before testing your skill is configuring it. This is where you give Alexa the link to your skill's code, which actually requires us to step over to Lambda ...
Lambda, part of Amazon's vast AWS suite, is an online computing service. You upload your code, set up a few parameters, and Lambda will run the script on demand. Lambda can be replaced by any host capable of HTTPS (including a certificate), but it's a nice place to put your code while you're practicing.
Amazon's AWS suite features a variety of regional endpoints for your hosted content, but Lambda's Alexa support is only available on their U.S. East region servers. To select that region, make sure you click the dropdown in the upper-right corner of the AWS top-menu, and select "U.S. East (N. Virginia)."
Click "Create a Lambda Function" and skip the blueprint-selection by clicking Next. On the next page, "Configure triggers," select Alexa Skills Kit as your trigger. This allows an Alexa service to call your Lambda code.
Next comes the Lambda configuration page. There are a few big steps here:
index.handler
(this is the name of your entry point handler function). Choose an existing role and select lambda_basic_execution
.Then click Next, verify everything and create your function! There will be an ARN in the upper-right corner of the window. Copy that and paste it into the "Endpoint" textbox on your skill's Configuration page.
And voilà! The skill and function are created, configured and linked!
You can use the skill Test tab to enter test utterances and see how an Alexa device might respond. For example, in the image below I asked the skill to test an utterance of "ask my weather station the temperature." The result is a JSON-encoded string including the content of Alexa's output speech. There's even a "Play" button, which you can click to listen to an example response.
At this point you can also vocally test your skill on an Echo. Just make sure it's enabled in the "Your Skills" section of the Alexa app.
All of my custom code lives in index.js. WeatherReport.prototype.intentHandlers
-- an inherited function of the AlexaSkills
class provided by Amazon and defined in AlexaSkills.js -- maps the skill's Intent Schema to code-execution blocks. This is where a quick interaction with Alexa begins executing.
For example, if Alexa senses an utterance like "Alexa, ask my weather station how hot it is," she will find the "how hot it is" blurb mapped to WeatherReportTemperatureIntent
in the sample utterances. Then, in the intentHandlers()
function, the following code is called:
"WeatherReportTemperatureIntent": function (intent, session, response) {
getPhantReport("temperature", function cb(err, data) {
var speechOutput;
if (err) {
speechOutput = err;
} else {
speechOutput = "The temperature is " + data + " degrees farenheit.";
}
response.tellWithCard(speechOutput, "Weather Station Temperature", speechOutput);
});
},
getPhantReport
works Phant's API to find the most recently posted temperature measurement, which Alexa vocally relays. The data is also pushed out as a "card" in the app.
The same format is followed to generate a relative humidity response and a "full" weather report from my station.
Whether you picked up an Alexa-enabled device on Prime day, or already have one sitting around, hopefully this gives you some inspiration for designing skills of your own! I've posted the example code in a GitHub repository. (I'll caveat that with the warning that I was (re-)learning JavaScript on-the-go while writing that code. It's kludgy at best.) Thanks for reading, and have fun!
I've been looking for an easy-to-follow tutorial for Alexa skills forever! This one is great. Thank you!
That is something very interesting!
Thanks fort the article. I've been planning on trying something like this myself.
I already have a home server (old laptop) hooked up to various home made gadgets and running an http server to control said gadgets. I was hoping that I would be able to host my own Alexa skill on my home network (i.e. point Alexa to 'oldlaptop.local' or '192.168.254.13'). Looking through the Amazon documentation at https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing-an-alexa-skill-as-a-web-service , it's not clear whether Amazon allows this.
Has anyone successfully hosted an Alexa service on their home network?
I was trying to hack together an Alexa skill for my robotic vacuum project the other week, but this makes things much clearer. Thanks!