Enable the "Tracker for ISS" skill in Amazon Alexa app (or "enable Tracker for ISS" by voice) to try this out!
OverviewWhere 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.
Skill IngredientsAWS Lambda Functions- alexaISS: Responds to Alexa skill requests, Node.js script that needs dependencies installed prior to upload to AWS (see below)
- alexaISSGetTLEs: Collects and caches TLE (Two Line Element) data needed to calculate ISS's orbital position, scheduled via AWS CloudWatch Rules to run once per day, Node.js script that needs dependencies installed prior to upload to AWS (see below)
- alexaISSOrbitalObjects: Caches TLE data collected by alexaISSGetTLEs Lambda function. TLE data changes every 1-3 days. Caching it here reduces skill request latency and prevents abuse of external APIs.
- 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.
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, PoliciesUnder 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 SkillAlexa skills are setup in the Amazon Developer Console. This is where skills are tested on Amazon Echo devices and published. Intents, slots, and sample utterances for this skill are available here.
How It WorksHumans (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 SetupTo start, sign up for an AWS account if needed.
S3 BucketThe 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 TablesTwo 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 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).
Visit the Policies section and choose the "Create Policy" button.
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):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Action": [
"dynamodb:GetItem",
"dynamodb:Query",
"dynamodb:Scan"
],
"Effect": "Allow",
"Resource": [
"arn:aws:dynamodb:ZONEHERE:SOMENUMBERHERE:table/alexaISSLonLatLookup",
"arn:aws:dynamodb:ZONEHERE:SOMENUMBERHERE:table/alexaISSOrbitalObjects"
]
}
]
}
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.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Action": [
"dynamodb:PutItem"
],
"Effect": "Allow",
"Resource": "arn:aws:dynamodb:ZONEHERE:SOMENUMBERHERE:table/alexaISSOrbitalObjects"
}
]
}
Optional: Create a policy named "alexaISSWriteDynamoDBLonLat". This policy will allow test users that run the makeLonLatLookupTable.py script.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Action": [
"dynamodb:PutItem",
],
"Effect": "Allow",
"Resource": "arn:aws:dynamodb:ZONEHERE:SOMENUMBERHERE:table/alexaISSLonLatLookup"
}
]
}
IAM User for Local TestingIf 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:
- alexaISSReadDynamoDB
- alexaISSWriteDynamoDBTLEs
- alexaISSWriteDynamoDBLonLat (if planning to generate the LonLat table data, optional)
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 SkillLambda 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 FunctionsAWS 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.
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 RepositoryNote: 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.
alexaISS: Lambda function that handles skill responsescd lambda/lambdaFuncitons/alexaISS
mkdir node_modules
npm install aws-sdk dynamodb-doc satellite.js then-request
alexaISSGetTLEs: Lambda function run once per day to retrieve TLE datacd ../alexaISSGetTLEs
mkdir node_modules
npm install aws-sdk aws-cli dynamodb-doc request
Install and configure AWS-CLIAmazon Webs Services Command Line Interface will be used to connect the local project to remote DynamoDB databases and for authentication purposes.
Note: pip is required prior to install.
pip install awscli
Test to make sure aws-cli is installed correctly.
aws
Configure to match your skill skill user account key/region settings (not recommended to use your root account for this).
aws configure
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 FunctionsAfter 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.
Install lambda-localTo run Lambda functions locally for testing prior to uploading to AWS, install the lamnda-local Node.js module globally.
npm install -g lambda-local
As lambda-local installs, take note of the path of where it was installed. Example on a Mac:
/Users/USERNAME/.node/bin/lambda-local -> /Users/USERNAME/.node/lib
ode_modules/lambda-local/bin/lambda-local
To test this in terminal:
/Users/USERNAME/.node/bin/lambda-local
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.
export AWS_ACCESS_KEY_ID='TEST_USER_ACCESS_KEY_HERE'
export AWS_SECRET_ACCESS_KEY='TEST_USER_SECRET_ACCESS_KEY_HERE'
export AWS_REGION='us-east-1'
Local TestingNow 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:
cd lambdaFuncitons/alexaISS
lambda-local -l index.js -h handler -e testData/GetISSStatusIntent.js
Argument explanation:
- -l, --lambdapath [lambda file name] Specify Lambda function file name.
- -e, --eventpath [event data file name] Specify event data file name.
- -h, --handler [lambda-function handler name (optional)] Lambda function handler name. Default is "handler".
When run, an Alexa skill format response should be printed in terminal:
Logs
----
START RequestId: 90edd3a8-e845-bbdc-4ce3-3cbb5d38e191
onIntent requestId=request5678, sessionId=session1234
END
Message
------
{
"version": "1.0",
"sessionAttributes": {
"new": false,
"sessionId": "session1234",
"attributes": {},
"user": {
"userId": null
},
"application": {
"applicationId": "amzn1.echo-sdk-ams.app.[unique-value-here]"
}
},
"response": {
"outputSpeech": {
"type": "PlainText",
"text": "At a latitude of 47 and longitude of -151, ISS is currently traveling at 27,624 kilometers per hour at an altitude of 407 kilometers. That's 17,165 miles per hour at an altitude of 253 miles."
},
"card": {
"type": "Standard",
"title": "ISS Status",
"text": "At a latitude of 47 and longitude of -151, ISS is currently traveling at 27,624 kilometers per hour at an altitude of 407 kilometers. That's 17,165 miles per hour at an altitude of 253 miles.",
"image": {
"smallImageUrl": "https://s3.amazonaws.com/alexaissinput/cardImageSmall.jpg",
"largeImageUrl": "https://s3.amazonaws.com/alexaissinput/cardImageLarge.jpg"
}
},
"reprompt": {
"outputSpeech": {
"type": "PlainText",
"text": " "
}
},
"shouldEndSession": true
}
}
Tests are available for all functions, intents and slot values.
Upload to AWSFollow Amazon's instructions here (you'll want to zip up everything inside the Lambda function folder and upload as a zip on the Lambda function configuration page).
Alexa Skill Setup and TestingSign in at the Amazon Developer console, and follow Amazon's instructions here. Sample utterances can be copied from the project page, along with the intent schema.
Generate alexaISSLonLatLookup DynamoDB TableThe 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:
cd folder/with/keypair
chmod 400 alexaISSEC2KeyPair.pem
Then login using the downloaded key pair (this file can be reused):
ssh -i "alexaISSEC2KeyPair.pem" ubuntu@ec2-XXX-XXX-XXX-XXX.compute-X.amazonaws.com
Install Python requirements (saving time as these requirements require other GDAL-related programs):
#upgrade pip
sudo pip install setuptools --no-use-wheel --upgrade
#AWS SDK for Python (Boto3)
sudo pip install boto3
#AWS-CLI
sudo pip install awscli
Configure AWS-CLI with same test user info as local setup:
aws configure
#!!! CHECK IF STILL NEEDED NEXT ROUND:
#set AWS-CLI environment variables:
export AWS_ACCESS_KEY_ID='TEST_USER_ACCESS_KEY_HERE'
export AWS_SECRET_ACCESS_KEY='TEST_USER_SECRET_ACCESS_KEY_HERE'
export AWS_REGION='us-east-1'
Download shapefiles from Natural Earth:
#get countries
wget http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural
e_10m_admin_0_countries.zip
unzip ne_10m_admin_0_countries.zip
# get states/provinces
wget http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural
e_10m_admin_1_states_provinces.zip
unzip ne_10m_admin_1_states_provinces.zip
# get points for populated placces e.g. cities
wget http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural
e_10m_populated_places_simple.zip
unzip ne_10m_populated_places_simple.zip
# get water coverage and names
wget http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/50m/physical
e_50m_geography_marine_polys.zip
unzip ne_50m_geography_marine_polys.zip
Download the table generating script from the project source:
wget https://raw.githubusercontent.com/owntheweb/alexa-iss/master/source/makeLonLatLookupTable/makeLonLatLookupTable.py
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.
nohup nice -n 10 python makeLonLatLookupTable.py "-1800" "1800" "-900" "0" "i01p01" &
nohup nice -n 10 python makeLonLatLookupTable.py "-1800" "1800" "0" "900" "i01p02" &
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.
Reminder: Use at your own risk!
Todo/Wishlist- Enhance and recreate lonlatLookup table using OSM database/server instead of shapefiles.
- Generate Alexa app images that show ISS on a map.
- Create Space-Track.org TLE retrieval script; Space-Track.org a more direct source of data, requires submittal of Orbital Data Request (ODR) form.
- Days in orbit
- Days occupied
- Number of orbits?
- Perigee
- Apogee
- Orbital inclination
- Orbital decay rate?
- Crew details (how many?, who?, how to keep up with these details?)
- News (Where to grab the latest ISS-only news in a usable data feed with permission to use?)
- FAQs (e.g. What do astronauts eat on ISS? Who built ISS? How do people go to the bathroom on ISS? [That's a common one])
- ISS module details?
TLS data API courtesy of wheretheiss.at.
TLS data made available for public sharing by Space-Track.Org
The satellite.js project makes position calculations/predictions possible.
Geographic data made with Natural Earth.
Quality coffee makers everywhere.
The Space Foundation that enspires me to explore space in ways that I can!
ContributeHelp this skill grow by contributing to the repository at:
Comments