Software apps and online services

Story

Enable the "Tracker for ISS" skill in Amazon Alexa app (or "enable Tracker for ISS" by voice) to try this out!

Overview

Where is the International Space Station right now? The "Tracker for ISS" Alexa Skill will calculate the International Space Station (ISS) longitude, latitude, speed, altitude and nearby geographical features as it orbits around the Earth faster than a speeding bullet.

This skill was created in an effort to better understand Amazon Web Services (AWS) Lambda functions, AWS Simple Storage Service (S3), AWS DynamoDB, AWS Elasic Compute Cloud (EC2), AWS security policies and Node.js. I wanted to build a fully featured and affordable cloud-based solution using all the tools mentioned.

alexaISSLonLatLookup (experimental): Stores water body, country, state and city used in reverse geo lookups based on ISS's longitude and latitude. Its purpose is to reduce latency caused by additional API requests that can return most of this data, and reduce long-term costs by not needing to run an OSM server to handle reverse lookups in realtime.

Lon/Lat Lookup Table Generator Script

This script uses shapefiles from Natural Earth to populate the alexaISSLonLatLookup table with water body, country, state and city for approximately 6,480,000 lon/lat points around the Earth (0.1 degree increments).

Caution: The table generator script is experimental and needs work. The resulting table has empty points and costs money to create (high DynamoDB capacity needed, lots of requests to handle). Next time: It may be better to generate this table with a OSM map server instead of shapefiles for improved performance and accuracy.

AWS Simple Storage Service (S3)

The skill currently delivers icon images (shown in Alexa app) from an S3 bucket. This may expand in the future to store and deliver dynamically generated images.

AWS IAM User, Roles, Policies

Under a root account, an IAM user with access keys is setup for local testing with IAM roles/policies attached that determine what the user can do with AWS. IAM roles are assigned to Lambda functions as well to restrict access to specific needs. See below for details.

Alexa Skill

How It Works

"ISS Tracker" skill schematic

Humans (or other vocal things) ask Alexa for the status of ISS. A response is calculated and returned by the alexaISS Lambda function after accessing stored TLE (two line element) data and nearby geographical features from the DynamoDB tables. Scheduled to run once per day, the alexaISSGetTLEs function retrieves and stores TLE data from the wheretheiss.at API. During setup of the skill, an GDAL-configured Ubuntu EC2 instance is launched and generates the geographic feature table later referenced by the skill (only run once during setup). All functions and tables run within the Amazon Web Services (AWS) services, with access policies configured using AWS IAM policies.

Amazon Web Services Setup

S3 Bucket

The ISS skill references images that can be seen in the Alexa mobile app and website response cards. An S3 bucket will be created and configured to deliver response images while meeting delivery requirements (SSL/TLS, extra headers).

Visit the S3 section of the AWS control panel. Choose the "Create Bucket" button. Name the bucket something meaningful and unique ("alexaissinput" used in this example). Choose a region. Make sure to use the same region when creating Lambda functions and DynamoDB tables ("US Standard" covered needs in this example).

Cross-domain access to S3 files will be required in order to show card response images in the Alexa app and website. To allow, choose the bucket that was just created. Select the "Properties" button (top-right). Expand the "Permissions" accordion section. Choose "Edit CORS Configuration". A modal window will show. Paste this CORS configuration in the box then choose the "Save" button:

(Note: Having issues posting XML code in the website editor. See this file in the project repository)

While still in the bucket, choose the "Upload" button on the top left of the page and select the cardImageLarge.jpg and cardImageSmall.jpg images. Once the images are uploaded, they will still need to be openned up for anonomous access. On the left of the page check/select one image, then select the "Properties" button on the top right. Open up the "Permissions" accordion panel on the right, then choose "Add more permissions". Select a "Grantee" of "Everyone", check "Open/Download", then save. The URL shown at the top of the right panel is what is referenced in the alexaISS Lambda function (bucket name just needs to be changed in settings to match).

DynamoDB Tables

Two DynamoDB tables are used as part of the ISS skill. To configure, visit the DynamoDB section of the AWS control panel.

The alexaISSOrbitalObjects table will store a single record containing Two Line Element (TLE) data used to calculate the orbital position of ISS. This record will be updated once per day by the alexaISSGetTLEs Lambda function (see below). The table will be read by the alexaISS Lambda function frequently when generating Alexa skill responses.

Choose the "Create table" button. Set the table name to alexaISSOrbitalObjects (any name will work, make sure to update script settings as needed). Set the primary key/partition key to satCatNumber as a number. Leave "Use default settings" checked and choose the "Create" button.

The alexaISSLonLatLookup table is currently experimental, storing water body, country, state and city for every 0.1 degree longitude/latitude increments covering the Earth. The purpose of this table is to suppliment response lon/lat information with nearby geographical features, while greatly reducing latency caused by making API requests to other reverse geo lookup services. Once data is generated and stored, the table will hold approximately 6,480,000 records. As the table is time consuming and costs money to make, the alexaISS lambda function that references this table will still function if the table is left empty.

Choose the "Create table" button. Set the table name to alexaISSLonLatLookup (any name will work, make sure to update script settings as needed). Set the primary key/partition key to lonlat as a string. Leave "Use default settings" checked and choose the "Create" button.

IAM Policies

IAM policies control who/what can do what on AWS. One IAM policy will be created and assigned to give users and created Lambda functions access to read and write to DynamoDB tables as needed (and nothing else for improved security).

Create a policy named "alexaISSReadDynamoDB" (could be any name) and enter the following policy configuration. This policy will allow test users and the skill functions to read (but not write) the alexaISSLonLatLookup and alexaISSOrbitalObjects tables. Note: Users for testing locally and roles assigned to Lambda functions will be assigned this policy later. Make sure to update the Amazon Resource Name (ARN) of the tables as needed in the policy (found on the DynamoDB table edit pages in the AWS console):

Create a policy named "alexaISSWriteDynamoDBTLEs". This policy, when assigned, will allow the scheduled alexaISSGetTLEs Lambda function to store/update retrieved TLE data for ISS orbital position calculations.

IAM User for Local Testing

If testing locally, setup a an IAM user to use with tests under the "Users" section. Choose a matching username for the task such as "alexaISSLocalTester" (anything useful for future memory). Once created, under the "Permissions" tab, attach the following policies:

Under the "Security Credentials" tab, choose the "Create Access Key" button. The resulting private and public key will be used locally to gain access to services as set in the attached policies. Take note of or download the private and public key for local installation instructions below.

IAM Roles for Alexa ISS Skill

Lambda functions can be assigned a role with attached policies in order to access permitted services.

The ISS skill will need a role that can read DynamoDB tables setup in the alexaISSReadDynamoDB policy. Visit the Roles section and choose the "Create New Role" button. Name the role "alexaISSSkill" (any name will work) then choose the "Next Step" button. Under "AWS Service Roles", choose the "AWS Lambda" option. On the "Attach Policy" screen, choose the "alexaISSReadDynamoDB" policy that was created earlier then choose the "Next Step" button. Review the role settings and choose the "Create Role" button.

The ISS skill will need a role that can write to the DynamoDB table specified in the alexaISSWriteDynamoDBTLEs policy. Visit the Roles section and choose the "Create New Role" button. Name the role "alexaISSSaveTLEs" (any name will work) then choose the "Next Step" button. Under "AWS Service Roles", choose the "AWS Lambda" option. On the "Attach Policy" screen, choose the "alexaISSWriteDynamoDBTLEs" policy that was created earlier then choose the "Next Step" button. Review the role settings and choose the "Create Role" button.

Lambda Functions

AWS Lambda allows code to be run on demand, only charging for compute time. It also integrates quickly with Alexa skills and other AWS services. The ISS skill is made up of two Node.js Lambda functions. Start by visiting the Lambda section of the AWS control panel.

The alexaISS Lambda function will handle ISS Skill requests. Choose the "Create a lambda function" button. Choose the "Skip" button at the bottom of the "Select blueprint" page. Set the function name to alexaISS (any name will work). Set "Runtime" to Node.js 4.3. Add a placeholder comment to the code area for now (e.g. \\). Dependencies need to be installed locally first prior to upload later, see Local Installation below. Keep "Handler" set to index.handler. Set "Role" to the newly created alexaISSSkill role. Leave all other settings as-is. It may be desired to set "Timeout" higher if testing out new features that make external API requests. Choose the "Next" button. Review settings, then choose the "Create Lambda function".

The alexaISSGetTLEs Lambda function will collect and cache TLE (Two Line Element) data needed to calculate ISS's orbital position. Follow instructions above, naming the function as alexaISSGetTLEs and selecting the alexaISSSaveTLEs role. This function will need to be scheduled to run once per day later once valid code has been added.

Local Installation

For development purposes, this skill can be installed and tested locally prior to uploading to Amazon Web Services as a Lambda function and skill. While it's possible to alter and upload Lambda functions as a .zip file and test in AWS, frequent alterations may result in much time savings if tested locally first.

Clone Amazon Alexa ISS Skill Repository

Note: Git is required to clone this repository. Git Installation instructions can be found here.

git clone git://github.com/owntheweb/alexa-iss.git

Install Node.js Dependencies (required prior to upload)

The ISS skill functions run as Node.js (server-side JavaScript) Lambda functions. After installing node if needed, install dependencies for the dependencies for the two functions.

Fill in prompts to match key information generated when creating the test user (see 'IAM User for Local Testing') above. When prompted, also make sure to enter the matching region where Lambda functions, DynamoDB tables and S3 were configured (e.g. 'us-east-1').

Configure Lambda Functions

After installing nodejs dependencies (see Install Node.js Dependencies above), update the settings sections near the top of the alexaISS and alexaISSGetTLEs Lambda function index.js files. Ensure that bucket names and DynamoDB table names match the existing names that were setup in AWS.

This can also added to ~/.profile for faster use in the future with this line added near the bottom of the file before the export PATH line (again, may vary between Mac OS and other platforms):

PATH="/Users/USERNAME/.node/bin:$PATH"

If not present at the end of the file, add this line:

export PATH

After fully closing terminal and/or restarting, lambda-local can be executed with a simpler command:

lambda-local

On Mac OS (need to follow up and test on Linux), lambda-local and/or aws-sdk node modules were found to run partially independently from the installed AWS-CLI configuration. While researching this for future efforts, setting AWS configuration values as environment variables in terminal before running lambda-local tests resolved issues that were occuring. Note: If the terminal window is closed, enter the environment variables again before further testing.

Local Testing

Now that lambda-local is installed and AWS-CLI environment variables are set, here is an example of how to use lambda-local to test the alexaISS skill function, passing in data that invokes the GetISSStatus intent:

Alexa Skill Setup and Testing

Generate alexaISSLonLatLookup DynamoDB Table

The alexaISSLonLatLookup table stores water body, country, state and city for every 0.1 degree longitude/latitude increments covering the Earth. This data is optional and the skill will work as long as the alexaISSLonLatLookup table and access policies are in place (empty or not).

EXPERIMENTAL, COSTS INVOLVED: The resulting table takes several hours to create. It requires high write capacity and adds millions of records (costs involved). Accuracy is not 100% with some land areas returning empty values. It's recommended to revisit this process utilizing an OSM database and not use shapefiles when generating this database. Benefit: No need to run an OSM server or other server/service (which can cost more money over time).

While any configured computer could be used to generate the alexaISSLonLatLookup table, configuration time (and possibly network transfer time) was saved by launching a pre-configured community GDAL server on AWS Elastic Compute Cloud (EC2).

Visit the AWS EC2 section of the AWS console and choose the "Launch Instance" button. Open the "Community AMIs" panel on the left and search for "GDAL". At the time of writing, an Ubuntu instance of "ubuntu-precise-12.04-amd64-cartodb-dev-geos-postgis-gdal-sqlapi-windshaft-cartodb" was chosen. Choose the "Select" button. A compute optimized instant type is recommended (c3.xlarge was chosen at the time of writing). Choose the "Review and Launch" button. Review then choose the "Launch" button.

Important: A c3.xlarge instance runs at $0.21/hour at the time of writing. If left running after the the script is finished for a month, thats over $150 (terminate the instance when finished to save money).

In the key pair window, choose "Create a new key pair", give it a name (e.g. alexaISSEC2KeyPair) then download the file. Move the file to a safe place that can be accessed from terminal. Check that you acknolodge then choose the "Launch Instances" button. A note mentioning "Your instances are now launching" is shown. Choose the instance name/link mentioned in the message to visit the instances list.

To connect via terminal, select the instance in the list, then choose the "Connect" button. A window will show with important access information. Based on that information, change the file permissions of the key pair for access requirements:

Write capacity for the alexaISSLonLatLookup table needs to be greatly increased to handle bulk write requests (6,480,000ish records over a few hours). In a browser, visit the DynamoDB section of the AWS console and choose the "alexaISSLonLatLookup" table. In the "Capacity" tab, set the write capacity to 500 and choose the "Save" button.

Important: Increasing capacity incurs more costs over time ($242 over a month at the time of writing if left active). Be sure to take this back down to 5 as soon as the table generating script is finished running to prevent large charges.

The last step is to run the generator script. This will take hours and it's good to monitor the metrics available in the "Metrics" tab (updated every minute) to track usage.

The above example will run two processes at the same time, one handling the lower half of Earth, the other handling the upper hemisphere. Note: it was found that the upper hemisphere takes much longer to process. It may be wise to split this up differently next round.

Contribute

Schematics

ISS Tracker Schematic

Humans (or other vocal things) ask Alexa for the status of ISS. A response is calculated and returned by the alexaISS Lambda function after accessing stored TLE (two line element) data and nearby geographical features from the DynamoDB tables. Scheduled to run once per day, the alexaISSGetTLEs function retrieves and stores TLE data from the wheretheiss.at API. During setup of the skill, an GDAL-configured Ubuntu EC2 instance is launched and generates the geographic feature table later referenced by the skill (only run once during setup). All functions and tables run within the Amazon Web Services (AWS) services, with access policies configured using AWS IAM policies.

Code

ISS Tracker Alexa Skill

The ISS Tracker repository includes two lambda functions utilized by the ISS Tracker skill, sample utterances, intent schema and even source graphics for the skill icon. It's all here.