Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Alexa, Meet Marvel

DZone's Guide to

Alexa, Meet Marvel

Build an Alexa skill that will put you in touch with the mightiest Marvel heroes in the galaxy! See how you can plug Marvel's API and database into an app!

· IoT Zone
Free Resource

Discover why Bluetooth mesh is the next evolution of IoT solutions. Download the mesh overview.

Imagine a world where heroes and villains are at your beckon call. Voice assistant technology has been a game changer in the smart home space. Products like Google Home and Amazon Alexa provide the ability to talk naturally to your smart devices. But this technology goes further. It allows consumers to get general information without opening a book, or turning on your favorite computer, tablet, or phone. This article goes into building an Alexa skill, integrating a secure REST service, and testing your new skill.

Time to put on your superhero hats as we go through building an Alexa skill to interact with the Marvel Comic database. This project is going to require a few things to get going.

The Setup

Image title

First, it is more fun to try your skills on an Alexa device like the ever-cheaper Echo Dot, or the nicer Echo, but it is not necessary. Amazon has built out a nice set of basic testing tools, which will be covered later.

Then we need a superhero database. A few years back, Marvel Comics released a set of rest APIs of their Marvel content. The idea is to allow the developer community to create innovative applications with their data. The APIs let developers query all sorts of goodness about the Marvel universe. Head over to the Marvel Developer Portal and sign in for free access to their API. Marvel’s API limits the number of calls per day and requires a public and private key.

Finally, sign up for the Amazon Developer Portal to get access to build an Alexa skill. You will also eventually need an Amazon Web Services account, which you can sign up at for the free tier. It will be used in this project to integrate an AWS Lambda function using a Node.js implementation.

Interaction Skills

Amazon Alexa has a basic set of functionalities, and you can enhance it by adding skills to your Alexa device. A skill simply allows Alexa to respond to a user’s voice request. For example, when you say “Alexa, ask Marvel Hero, 'Who is Daredevil?'” the skill in this sentence is “Marvel Hero”. This becomes the trigger to process an utterance and intent of the user. This is all driven by the Alexa voice user interface, which allows a voice to interact with software and the software to respond through speech and text.

Alexa’s skill consists of  Alexa ask {invocation name} [utterance {slot}]. Notice that within an utterance is a concept called “slots”, and we will get to that in a moment.

The intention is mapped to call another service to do what the user asked. This is where the AWS Lambda function comes into play. Although you can choose to write your own Alexa-capable REST service, we will stick with AWS Lambda. When the service completes, it responds back to the Alexa skill to allow Alexa to respond back to the user. The user hears the response from the Echo device and also receives textual information that is displayed as a card in the user’s mobile Alexa app.

In the Amazon Developer Portal, go to the Alexa tab in the dashboard. Start creating the Alexa skill by clicking the Alexa Skills Kit option, then click the “Add new skill” button. This will launch a skills wizard.

For the skill type, select the “Custom Interaction Model”. The skill name can be any name that will be displayed to customers in the skill store.

The invocation name is important. This becomes the verbal trigger of your skill, i.e. “Alexa, ask {invocation name} [who is intention]”. Amazon has standards that apply to invocation names, but also think about the user and how they might easily remember the name of your skill. Be creative. Like, in this case, “Alexa, ask Nick Furry ...”, or “Alexa, ask Stan Lee...”

Image title

Enter the invocation name, ignoring the global values settings, and Save.

There will be an application ID — copy this down. This number will be needed when building the Lambda function. It will also be on the skill’s information page.

Intentions

The Beta Skill Builder interface makes it easier to build out the intents for an Alexa skill. Click the Add button under Intents and use ‘Create New Custom Intent’. Give it a name like “getHeroIntent”. This is the name of the function call in the AWS Lambda piece that we will create later.Image title

For this action, we need to associate a set of utterances that will cause it to trigger and pass in key information the user will say. An example is, “Alexa, ask Shield Database, [who is Daredevil]”. Create a number of utterances or phrases that your users will say when using the skill to ask about a particular superhero. This would be “who is”, “describe”, “tell me about”, and so forth. Get creative!

Slots

The concept of slots is a placeholder value when the user asks about a particular hero. Within the utterance text, you can use slots to allow the skill to use that as a sort of validated data field that allows the value to be passed to the Node.js service.Image title

Creating a number of utterances in Alexa with the phrase of each character would be a lot of work. Instead of asking the questions, “Who is Spider-Man?” or, “Who is Doctor Strange?” a developer can add “who is {heroname}”. The {heroname} is a slot placeholder in the utterance. A slot takes a user’s spoken words and converts it to a standard mapped value that can be passed to a REST endpoint. This can be numeric, date, times, lists or even a customizable list. Read more about Slot Reference Types.

For the hero names, click Add Intent Slot and give it a name. There is no need to create a custom slot type as we can use the Amazon.FictionalCharacter slot type. Select the Amazon.FictionalCharacter from the slot type drop down or via quick search in the drop down.

Image title

Save the skill model, then build it. We will come back to the final configuration of the skill to tie it into the AWS Lambda function.

AWS Lambda

AWS Lambda is a serverless code platform that can deploy and run your code on demand without it running all the time. It is a great platform for part-time code computations, batch processes, or, in our case, an Alexa skill. There are also tradeoffs based on how often your functions run and the technology language stack you choose. Lambda supports Node.js, Python, Java, and C#. For this example, we will pick Node.js.

Log into the AWS Console. Go to Services and search for “Lambda” in the search bar — there are so many services within AWS that it is faster just to search for it. When you come to the Lambda dashboard, click the “Create function” button. The Lambda wizard will prompt you for a set of questions. Select a blueprint called ‘alexa-skill-kit-sdk-factskill’. It is a basic template, and we will replace the template code with our own.

For the trigger for this function, select the ‘Alexa Skills Kit”.

Image title

Fill in the name of your intent you used for your Alexa skill — for example “HeroLambdaIntent” – and some description.

Image title

This is the step where we will drop in our Lambda code and set up our AWS security permissions — called IAM roles. Keep the template code for now and skip to giving security access to our Lambda function.

If you have never created an IAM role, it is pretty easy. There are more instructions on how this is done at Setting up your first Lambda Role.

After setting the "lambda_basic_execution" role and saving, the Lambda function will be created and there will be an ARN number in the top corner of the screen. Copy this number to add it to your Alexa skill configuration.

Image title

Add the ARN number to the Alexa skill's configuration page. The number goes into the Global Endpoint default field. 

Image title

The Code

This article will not go into a line-by-line tutorial of how to write a Node.js application. Rather, we are going to touch on the finer points that pertain to Alexa and AWS Lambda intricacies. The basic code is all available on GitHub. This file can be copied into the Lambda online code editor with the necessary modifications. 

AWS Lambda already has the library dependencies to the Alexa skills and core Node.js libraries. In the past, you would have to zip your files and node_modules dependencies and then deploy the ZIP to Lambda. This is still the case if your applications has additional module dependencies.

'use strict';

const Alexa = require('alexa-sdk');
const https = require('https');
const crypto = require('crypto');

const APPLI_ID = '<your alex skill id>';
const MARVEL_PUBLIC_KEY='<Marvel api public key>';
const MARVEL_PRIVATE_KEY='<Marvel api private key>';


Notice that alexa-sdk is imported. If you are creating a clean slate Alexa Lambda function, you will need this one import.

Add your own Alexa skill, which was issued when you created the Alexa skill to the APLI_ID constant. The Marvel public and private API keys, which Marvel issues when you sign up for an account, will need to be placed in the appropropriate constant values. 

The next code block is the multiple language support. 

const languageStrings = {
    'en': {
        translation: {
            SKILL_NAME: 'Marvel Heros',
            WELCOME_MESSAGE: "You can ask me for an marvel hero name. Who will it be?",
            GET_FACT_MESSAGE: "You asked about the character, ",
            NOT_FOUND_MESSAGE: "I did any further description of this character.",
            HELP_MESSAGE: 'You can ask me for a marvel hero that starts with a name?',
            HELP_REPROMPT: 'Name a hero from marvel universe',
            STOP_MESSAGE: 'Goodbye!',
        },
    },
    'en-US': {
        translation: {
            SKILL_NAME: 'American Marvel Heros',
        },
    },
    'en-GB': {
        translation: {
            SKILL_NAME: 'British Marvel Heros',
        },
    },
    ...
}
};


This is used by the Alexa handler call to toggle language resources based on the user's origin. For English, the values are defaulted to EN, and any overriding values are specifically declared for that country. In the above example, the SKILL_NAME value is different for US English and British English. 

The core of our Alexa Lambda implementation is the handlers. Notice in the Alexa interaction model dashboard that the Intent names map to the various handler functions.  

Image title

The following illustrates that the various functions in the handler are mapped to the Amazon intents in the Alexa interaction builder. The handlers are various function calls that the Alexa lifecycle and intents may call. When a user says, "Alexa, open Marvel," for instance, the LaunchRequest will display and emit a response back to Alexa. In this example, it is outputing the welcome message, and some help. 

const handlers = {
    'LaunchRequest': function() {
        output = this.t('WELCOME_MESSAGE');
        this.emit(':ask', output, this.t('HELP_MESSAGE'));
    },
    'getHeroIntent': function() {
        ....
    },
    'AMAZON.HelpIntent': function() {
        ...
    },
    'AMAZON.CancelIntent': function() {
        ...
    },
    'AMAZON.StopIntent': function() {
        ...
    },
    'SessionEndedRequest': function() {
        ...
    },
    'Unhandled': function() {
        ...
    }
};


The getHeroIntent function call is the main driver of this Alexa skill. It is also the same name of the intention. Therefore, if the intention in the Alexa skill was named "GetMyHero", then this function call should have the same name.

The function gets the value of the slot from the request intent, called heroname. This value is passed to the Marvel REST service to query for characters with a name starting with the value in the heroname slot.

'getHeroIntent': function() {
    var slotValue = '';
    var heroName = ''
    if (this.event.request.intent.slots.heroname) {
        if (this.event.request.intent.slots.heroname.value) {
            slotValue = this.event.request.intent.slots.heroname.value;
            heroName = encodeURI(slotValue);
            console.log(' Got hero name from slot ' + slotValue);
        }
    }
    var introText = this.t('GET_FACT_MESSAGE') + slotValue + ". ";
    var description = this.t('NOT_FOUND_MESSAGE');
    httpGet(heroName, function(response) {


An httpGet call is made to the Marvel database, where it uses the slot value to query the character name that starts with this value. The httpGet function call also hashes the public and private key and makes the request, limiting it to only the first Marvel character returned. The response back from the Marvel API is a JSON response. Here is the basic code block for the httpGet function call. 

function httpGet(heroNameQuery, callback) {
    var timestamp = Date.now();
    var myHash = crypto.createHash('md5').update(timestamp + MARVEL_PRIVATE_KEY + MARVEL_PUBLIC_KEY).digest("hex");
    var options = {
        host: 'gateway.marvel.com',
        port: 443,
        path: '/v1/public/characters?nameStartsWith=' + heroNameQuery + '&limit=1&ts=' + timestamp + '&apikey=' + MARVEL_PUBLIC_KEY + '&hash=' + myHash,
        method: 'GET'
    };
    var req = https.get(options, (res) => {

        var body = '';
        console.log("STATUS: " + res.statusCode);
        res.on('data', (d) => {
            body += d;
        });

        res.on('end', function() {
            console.log('Successfully processed response')
            callback(body);
        });

    });
    req.end();

    req.on('error', (e) => {
        console.error(e);
    });
}


The final part of the Alexa Node.js portion is registering an Alexa handler with the multi-language resources defined in 'languageString'. The Alexa handler also needs the Alexa skill ID that was created in the first step of creating a skill. Finally, we need to register our own handlers to the Alexa handler. 

exports.handler = function(event, context, callback) {
    alexa = Alexa.handler(event, context);
    alexa.APP_ID = APPLI_ID;
    alexa.resources = languageStrings;
    alexa.registerHandlers(handlers);
    alexa.execute();
};


The full code is here, and you can copy and paste the index.js content into the AWS Lambda code section. 

Testing

Once the Lambda function is saved, the first step to setting up a test for the cloud is to use an Alexa test template. Under 'Actions' on the Lambda function page is an option to 'configure test event'.

Image title

This will bring up a dialog box, which has a number of templated tests. Use the "Alexa Intent - GetNewFact" template. Modify the JSON section called "intent" and add a slot object with a name and value. For further reference, see the testEvent.json file here.

"intent": {
    "slots": {
        "heroname": {
            "name": "daredevil",
            "value": "daredevil"
        }
    },


Save the changes and the Lambda function can be tested in the cloud by clicking the "Test" button. If the test is successful, you will get a green check. If not, there will be a log file that you can use to debug the problem. 

Another option is to test on your local system.  Using a project called lambda-local makes this easy. Install lambda-local via: 

npm install -g aws-lambda-local


Create your JSON test file, which is basically a copy of the modified "Alexa Intent - GetNewFact" template. Run the test locally against a local copy of the Node.js code type with the following:

lambda-local -f index.js -e testEvent.json


Once the AWS Lambda function is working. Test the Alexa integration by going back to the Alexa skills developer page. Select the Test tab of the skill. Here, you can enter text of what the user would say to your skill and test it triggering your intentions. If everything works, you should see a service request and response. 

Image title

You can even click the listen button and listen to how it would sound through Alexa. In addition, if you have an Echo device, and it is associated with your Alexa developer account, you can test it out with your Echo.

Building an Alexa skill is simple — it is just knowing how all the plumbing fits together. This hopefully illustrates how cloud-based environments can scale quickly and call many different services. One final point is that voice assistant-based applications change how developers have to think about the user experience.  

Take a deep dive into Bluetooth mesh. Read the tech overview and discover new IoT innovations.

Topics:
iot ,alexa skills ,marvel api ,aws lambda ,rest api app ,tutorial

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}