Yes, absolutely it’s possible. As
we few of many already know that Swift-programming language allow iOS
developers to build or develop iOS based applications. Here out of the box,
we’ll experience the way of methodology to expand Swift proficiency skill set
to include server-side programming and take part in the trend towards voice
user interfaces (i.e., Amazon Echo). Please be noted, currently AWS Lambda
(i.e., server-less compute) only supports code written in JavaScript (Node.js),
Python, C# and Java. But it’s easy to extend this to executable written in any
programming language you want.
In this
post we will learn and understand about methodology how to build or develop
Alexa skills (or app) with the proficiency of ‘Swift’ programming language? Also
achieve an idea of integrating created skills with other AWS cloud services too.
Before jump into the context, I really recommend here to check it out or follow
below highlighted links – will help to explore and understand the basic implementation
guidelines. Reading or follow amazon documentation will be plus to achieve the
target implementation result.
Important Links:
Blog Link:
·
Alexa skills from scratch with AWS
Lambda, SSML and Amazon S3
· Swift Programming (Server-Side) - Kick Start..!
Sample tested on below system-setup:
·
macOS Sierra – 10.12.4
·
XCode – 8.3 (8E162)
·
Swift – 3.1
·
Docker – Community Edition - Version 17.03.0-ce-mac2
(15654)
Objective Target:
Alexa will
send created skill a JSON message with the user’s intent and sample code
answers with a JSON message that determines what Alexa will answer to the user.
The
code for our custom skill can run as either a stand-alone web service (i.e.,
HTTP) or an AWS Lambda function. Using Lambda, Amazon’s server-less computing
platform, Amazon will take care of scaling and running sample Swift code.
1. HTTPS
Stand-alone web service (i.e., HTTP)
$ cd
/Users/ranbijaykumar/Alexa-AVS-Sample/Alexa-Swift-Skills/swift-lambda-app - using {Reference-Implementation} below instead of
the mentioned directory path.
2. AWS Lambda ARN (Amazon Resource
Name)
AWS Lambda is a server-less
compute service that runs code in response to events and automatically manages
the underlying compute resources.
Importantly I would like to
mention here that I pulled the source sample code from Github – developed by Claus Höfele. Though the sample
code is straightforward but I found personally few gap during time of implementation
– bridged and tried my best to make it easier from developer perspective.
Either clone or download the sample app from Github account.
Else, check out the swift-lambda-app repo on GitHub for the code and scripts to develop and deploy
a simple Alexa skill in Swift via Terminal command prompt in MacOS.
·
$ git
clone https://github.com/choefele/swift-lambda-app.git
·
$ swift build
·
$ swift package generate-xcodeproj
·
$ open ./AlexaSkill.xcodeproj/
We’ll need to understand the following for our Alexa
skill:
· An implementation of skill’s
functionality in Swift using AlexaSkillsKit
· A Lambda function set up with
your Swift code using the AWS Console
· An Alexa Skill configured in the Alexa Console that triggers your Lambda function
*Note that the Alexa Console and the AWS Console are two separate
services that user need to sign up for.
There are three targets:
· AlexaSkill: this is a library with the code
that implements the custom Alexa skill. It’s a separate library so the other
two targets can use it. Also, libraries have
ENABLE_TESTABILITY
enabled by default, which allows
user to access internal methods and properties in your unit tests.
· Lambda: The command line executable
for deployment to Lambda. This program uses stdin and stdout for processing data.
· Server (macOS only): To simplify
implementing a custom Alexa Skill, the server provides an HTTP interface to the
AlexaSkill target. This HTTP server can be exposed publicly via ngrok and
configured in the Alexa console, which enables you to develop and debug an
Alexa skill with code running on our development computer. This target is macOS
only.
HTTPS: To run a local HTTPS server
· Make sure the sample builds by running swift build
· Generate an Xcode project with swift package generate-xcodeproj
· Open the generated Xcode project, select the Server
scheme and run the product (CMD-R). This will start a server at port 8090
· Install ngrok via brew cask install ngrok. This tool allows you to expose a local
HTTP server to the internet
§ $ cd
{Reference-Implementation}
§ $
brew cask install ngrok -à Install ngrok
· Run ngrok
http 8090 and copy the HTTPS URL generated by ngrok (it looks
similar to https://6ebec3f2.ngrok.io)
§ $
ngrok http 8090 -à ‘Ctrl+C’ to get
back to command prompt.
* ngrok exposes your local
server to the public internet thus allowing the Alexa Voice Service to call
into your custom skill running in Xcode.
Configuring the Alexa Skill
To hook up your custom
skill to Alexa:
·
Go to the Alexa console and create a new skill
·
Skill type: Custom Interaction
Model
·
Intent:
{"intents":
[{"intent": "TestIntent"}]}
·
Sample utterances: “TestIntent test
Swift”
·
Service endpoint type: HTTPS (use the URL from ngrok) -
Copy above created HTTPS URL (i.e., in format
of https://6ebec3f2.ngrok.io)
and paste into the below endpoint field as depicted below. Press ‘Next’
·
SSL Certificate: Select “My
development endpoint is a sub-domain of a domain that has a wildcard
certificate from a certificate authority”
Now we can test the skill in the
Alexa Console’s Service Simulator using the utterance “test swift”. This will
call your local server allowing you to modify and debug your code while
interacting with the Alexa service. You can check the status ‘200’ into local running HTTPS server
over ngrok terminal. Please check
above in diagram.
Running
Tests for Your Code
Before uploading to Lambda, it’s worthwhile to run your
unit tests in a Linux environment and run integration tests that simulate the
execution environment. The sample provides run-unit-tests.sh to do the former and run-integration-tests.sh to do the latter.
run-unit-tests.sh builds and tests
the Lambda target inside a Swift Docker container based on Ubuntu because
there's currently no Swift compiler for Amazon Linux (based on RHEL).
Executables built on different Linux distributions are compatible with each
other if you provide all dependencies necessary to run the program. For this
reason, the script captures all shared libraries required to run the executable
using ldd.
To prove that the resulting package works, run-integration-tests.sh runs a release build of the Swift code
inside a Docker container that comes close to Lambda’s execution environment
(unfortunately, Amazon only provides a few Docker images that don't necessarily match what Lambda is using).
The integration with Lambda is done via a small Node.js script that uses the child_process module to run the Swift executable.
The script follows Amazon's recommendations to run arbitrary executables in AWS Lambda.
*After configuration, we
need to run the same integration script again for every commit or possible
changes.
Deploying
Sample Code to Lambda
To deploy sample code to AWS Lambda:
· Before jumping to below steps, first
run the Docker container, Install
Docker S/W in development machine from above link and check the status of
Docker container – as depicted above screenshot.
· Run run-integration-tests.sh to produce a zip file at .build/lambda/lambda.zip
with all required files to upload to Lambda
$ cd {Reference-Implementation}
$ mkdir -p
.build/lambda/libraries/
$ ./run-unit-tests.sh
$
./run-integration-tests.sh
It will create
the .zip in hidden folder - Hold down CMD-Shift-. (dot) keys
in Mac machine --à All the hidden files will become visible. Press
same group of keys again to make the hidden files/folder disappear as previous.
· Create a new Lambda function in
the AWS Console in
the US East/N. Virginia region (for Europe use EU/Ireland). Select
‘alexa-skill-kit-sdk-factskill’ blueprint
· Use an Alexa Skills Kit trigger
· Runtime: NodeJS 4.3 or NodeJS
6.10
· Code entry type: ZIP file
(upload the lambda.zip file from the previous step)
· Handler: index.handler
· Role: Create from template or
use existing role ‘lambda_basic_execution’
Once we uploaded the Lambda function, we can use the test actions in
the AWS Console, for example by using a Start Session action.
Configuring
the Alexa Skill for Lambda
After creating the Lambda function, you can now create an Alexa skill.
If you have previously created an Alexa skill for the local HTTP server — the
only difference is the service endpoint:
·
Go to the Alexa console and create a new skill
·
Skill type: Custom Interaction Model
·
Intent:
{"intents":
[{"intent": "TestIntent"}]}
·
Sample utterances: “TestIntent test swift”
· Service endpoint type: AWS
Lambda ARN (use the ARN for
the Lambda function from the AWS Console) – ARN:
arn:aws:lambda:us-east-1:280019173811:function:swiftDeploymentInLambda.
See previous of previous image to specified/copied the created ARN value at
endpoint field. [Please refer above mentioned blog links as well to understand
more into the deep].
Now we can test the skill in the Alexa Console using the utterance
“test swift”. More details on configuring Alexa skills can be found on Amazon’s developer portal.
Done J
I hope this
post will give you a great kick-of start using Swift programming language in
both client and server side on creating of an Alexa skills, also integrating
those skills with other AWS cloud services seamlessly. Thanks you and good
luck, happy programming!