Enginursday: Creating a Custom, Phant-Interfacing Alexa Skill

How I taught my Amazon Echo to give me hyper-local weather reports

Favorited Favorite 7

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.

Amazon Echo

The Monolith Amazon Echo (Image courtesy of Frmorrisson via Wikipedia.)

It took less than a week for me to commandeer the cloud-enabled, voice-controlled speaker and begin hacking it to my will.

For a bit of background: Alexa interfaces with various online APIs using a particular (and ever-expanding) set of "skills." There are skills for playing Jeopardy or ordering pizza, for example, and installing those skills is as easy as searching for it, tapping a button, and maybe doing some OAuth magic.

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.)

Data.sparkfun.com stream

A view from my weather station stream

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.

Example Alexa IFTTT recipe

Example Alexa IFTTT recipe

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.

Creating an Alexa Skill

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.

  1. Amazon Developer Account -- The Alexa skill itself is managed in the Amazon Developer Portal, the same place you'd go if you were writing an app for an Amazon device.
  2. Amazon Web Services (AWS) Account -- Your skill's code needs a host that's capable of running it. Amazon's tutorials document using their Lambda AWS service, which runs Node.js, Java or Python scripts.

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.

Configuring an Alexa Skill

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."

Entering the skill's information

Configuring the skill's general name and invocation name

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.

Configuring the skill's interaction model

Configuring the skill's interaction phrases

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 ...

Creating a Lambda Function

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)."

Selecting the region

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.

Triggering your Lambda function with Alexa

Next comes the Lambda configuration page. There are a few big steps here:

  • Name your Lambda function, and configure it to run Node.js (or Java or Python if you prefer).
  • Add your code -- it can be pasted in (if it's just one file), or added as a ZIP file. This can be edited later on; it doesn't even have to function right now.
  • Configure the handler and define its permissions. You'll probably want to leave the Handler name as index.handler (this is the name of your entry point handler function). Choose an existing role and select lambda_basic_execution.
  • In the Advanced Settings, you may want to consider increasing the timeout to 30 seconds (data.sparkfun.com doesn't always send the speediest of responses).

Configure function page

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.

Pointing the Alexa Skill to your Lambda function

Point your Alexa skill to the Lambda function by entering its ARN.

And voilà! The skill and function are created, configured and linked!

Testing the Skill

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.

Testing the Weather Reporter skill with an example utterance

Testing the Weather Reporter skill with an example utterance

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.

How It Works

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.

Alexa app card response

In addition to a voice indicator, Alexa responds with cards 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!

Comments 4 comments

  • Member #184747 / about 8 years ago / 1

    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!

  • vvvjv / about 8 years ago / 1

    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 ''). 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!

Related Posts

Recent Posts

Why L-Band?


All Tags