When using Alexa with my Echo Dot, I found that the integrated weather forecast was not that accurate for my location. Where I live, we have a significant microclimate, and getting the accurate forecast for my location is best done through Weather Underground. I have my own
personal weather station which provides a good forecast, and I wanted to link that in to my Alexa Flash briefing. Unfortunately, there doesn't appear to be a Skill for that at this time, so I went through the process of creating my own and wanted to share details of that here.
The basic steps to set this up are as follows:
- Get a Weather Underground API key to get the forecast and alert data in JSON format
- Setup an Amazon Lambda function to read the WU API and translate it into a format that Alexa can understand for the Flash Briefing
- Create an Amazon API interface to call the Lambda function
- Setup the Alexa Skill for a Flash Briefing item which uses the API interface just setup
- Turn on the skill on your Amazon Echo Dot (or other Alexa device)
Get a Weather Underground API key
Sign for weatherunderground.com if you haven't already, and
login to generate an API key. The process is simple, and free for under 500 calls per month. Just be sure and sign up for the "Cumulus" plan to get both forecast and alerts. Once you have the API key, you'll be using two of the API calls to get the information for Alexa. These are:
http://api.wunderground.com/api/xxxxxxxxxxxxxxx/forecast/q/pws:KVTSTARK3.json
http://api.wunderground.com/api/xxxxxxxxxxxxxxx/alerts/q/pws:KVTSTARK3.json
where xxxxxxxxxxxxxxx will be your WU API key.
For the actual location, you will want to replace q/pws:KVTSTARK3.json with the refined location for you via weather underground. To get this, go to the weather underground home page and look at the full forecast for your location. If you have a personal weather station, you can just substitute KVTSTART3 with your PWS station id. If not, then look at the URL of the full forecast, which will be something like this:
https://www.wunderground.com/q/zmw:05487.1.99999?sp=KVTBRIST11
and then replace the part of the url including and after the q (q/zmw:05487.1.99999?sp=KVTBRIST11 in the above example) with q/pws:KVTSTARK3 where KVTSTARK3 is your PWS station id.
Test out the urls in your browser to make sure you're getting back valid JSON, and then you're ready to move on to the next step.
Setup an Amazon Lambda function
Amazon Lambda functions provide quick and easy ways to implement snippets of code that are only executed when called. They are efficient ways to handle API implementations without having a full-blown server running, and are only charged on the per-usage basis.
The assumption here is that you've already setup an AWS account. From the AWS console, go to the Lambda service (https://console.aws.amazon.com/lambda/home). You'll want to create a blank lambda function without any triggers at this time. Call it something like getWUForecast and use the Node.js 4.3 runtime. For the inline code, you can use the following code snippet:
'use strict';
console.log('Loading function');
exports.handler = (event, context, callback) => {
var http = require('http');
var alertsurl = "http://api.wunderground.com/api/xxxxxxxxxx/alerts/q/pws:KVTSTARK3.json"
var forecasturl = "http://api.wunderground.com/api/xxxxxxxxxx/forecast/q/pws:KVTSTARK3.json"
// Get alerts first
http.get(alertsurl, function(res) {
res.setEncoding('utf8');
var rawData = "";
res.on('data', (chunk) => {
rawData += chunk;
});
res.on('end', () => {
var alert = JSON.parse(rawData);
// Now do the forecast portion
var obj = doForecast(http, forecasturl, alert, function(obj) {
callback(null, obj);
});
});
}).on('error', function(e) {
console.log("Got error: " + e.message);
context.done(null, 'FAILURE');
});
};
// Handle forecast API call
function doForecast(http, url, alert, callback) {
// Add in the alert to the beginning of the flash message
var alertObj = null;
if (alert.alerts.length > 0) {
console.log(alert.alerts[0].description);
console.log(alert.alerts[0].message);
alertObj = {
"uid": "00000000-0000-1000-0000-000000000001",
"updateDate": new Date().toISOString(),
"titleText": alert.alerts[0].description,
"mainText": alert.alerts[0].message,
"redirectionUrl": "https://www.weatherunderground.com"
}
}
// Get the info from Weather Underground
http.get(url, function(res) {
res.setEncoding('utf8');
var rawData = "";
res.on('data', (chunk) => {
rawData += chunk;
});
res.on('end', () => {
var forecast = JSON.parse(rawData);
// Put together all the next 4 forecast periods
// TBD: Ideally we should check to make sure we have 4 items in the array
var curForecast = "The current forecast for " + forecast.forecast.txt_forecast.forecastday[0].title;
curForecast += " calls for ";
curForecast += forecast.forecast.txt_forecast.forecastday[0].fcttext + " ";
curForecast += "For " + forecast.forecast.txt_forecast.forecastday[1].title;
curForecast += " " + forecast.forecast.txt_forecast.forecastday[1].fcttext + " ";
curForecast += "For " + forecast.forecast.txt_forecast.forecastday[2].title;
curForecast += " " + forecast.forecast.txt_forecast.forecastday[2].fcttext + " ";
curForecast += "For " + forecast.forecast.txt_forecast.forecastday[3].title;
curForecast += " " + forecast.forecast.txt_forecast.forecastday[3].fcttext + " ";
// Setup the results for Alexa feed
var forecastObj = {
"uid": "00000000-0000-1000-0000-000000000002",
"updateDate": new Date().toISOString(),
"titleText": forecast.forecast.txt_forecast.forecastday[0].title,
"mainText": curForecast,
"redirectionUrl": "https://www.weatherunderground.com"
};
var obj = null;
if (alertObj !== null) {
obj = [alertObj, forecastObj];
} else {
obj = [forecastObj];
}
callback(obj);
});
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
console.log('end request to ' + url);
}
After you've got the inline code, you also need to setup some config info. Under
Role, select to
Create new role from template(s). Give the role a name, such as WULambaRole and choose
Simple Microservice Permissions as the template. Everything else you can leave as defaults and then
Next and
Create Function.
You're now ready to integrate the lambda function to the API.
Create an Amazon API interface
Go to the Amazon console and navigate to the API Gateway services. From there select
Create API and give it a name such as WeatherUndergroundAPI. Select
Create API to create it. Now select the root of the API (/) and under Action, select
Create Method. Select a
GET method, a Lambda region where you created your Lambda function (probably us-east-1 if you didn't specify anything different before). Enter your Lambda function name you created above (
getWUForecast in the example) and save it.
Once the saving is complete, click on the
GET method and then the
TEST button to test it out. If all is well you'll get a 200 status code and a JSON response that is formatted for Alexa.
Now you'll need to deploy the API. Click on Actions,
Deploy API. Give it a new stage name of Production and then
Deploy it. Make not of the
Invoke URL which will be something like this:
Invoke URL: https://xxxxxx.execute-api.us-east-1.amazonaws.com/Production
You'll need that URL to link to the Alexa Skill.
Setup the Alexa Skill
Now you'll need an Amazon Developer Account to create the Alexa skill in. Go to the
developer Alexa skills page and
Add A New Skill. You'll want to select a Skill Type of
Flash Briefing Skill API and then give it a name, such as
Weather Underground Skill. Next through until you get to the
Configuration tab and enter a custom error message. Something like "The Weather Underground Skill is not currently available".
Now click on
Add A New Feed and a preamble to describe the feed, such as "Here is your weather briefing for Starksboro, VT". Name the feed WeatherUnderground with content type of
Text. Select a genre of
Weather and then enter the API Invoke URL you have from above in the URL field. Click on
Save and it will validate the link and continue on.
Next on the
Test tab, flip the switch to
ON so that you can integrate it with your Alexa. Next on through and
Save your skill.
Don't worry about publishing the skill, as this is just setting it up for your own personal use. If you publish it, you run the risk of using up your Weather Underground API calls pretty quickly, as everyone will be using your API key then.
Turn on the skill
Finally, you need to turn the skill on in Alexa.
Go to the Alexa and navigate to
Skills and then
Your Skills. The new skill will show up in the list, just click on it and then enable it. After it's enabled, you can go to
Manage in Flash Briefing to turn it on and set the order it shows up. When it's ready, you can just go to Alexa and say "Give me my Flash Briefing" and it should all work.
That's it. Hope this helps you in setting up a simple Alexa skill and doing some integration to Weather Underground!