Hacking Alexa Skills with service virtualization: The value of simulation for IoT
April 27, 2017
If you’re like me, you’re constantly imagining the futuristic possibilities of fully-realized Internet of Things (IoT) ecosystems. In the context of the home, I imagine my car, GPS, and Nest...
If you’re like me, you’re constantly imagining the futuristic possibilities of fully-realized Internet of Things (IoT) ecosystems. In the context of the home, I imagine my car, GPS, and Nest working together to anticipate my arrival and make the proper adjustments to climate control. Or refrigerators, Egg Minders, and Amazon Fresh speaking effortlessly to one another to order eggs before I even know I’ll need them. What a future!
Other times, I’m convinced IoT will bring a dystopian future (as described in sobering detail by Wired).
We are, fortunately, some ways from that level of interconnection. IoT development is in its relative infancy and there are some key challenges that IoT developers must overcome. There seems to be consensus that environmental complexity is a major challenge, and that’s a tricky challenge to overcome because complexity is sort of the point in the world of IoT. As a developer of an IoT device, I may integrate with many downstream third party APIs, while other developers may consume my exposed APIs. Before the increased demands of IoT, we might have tested our device within an ecosystem of APIs and devices by creating physical test labs. Now, that is an outdated and expensive proposition, and a developer often can’t control the data coming from third party APIs or devices (this is critical for edge case testing).
This is why service virtualization is a critical part of the solution. We can simulate downstream APIs and control the data our device is consuming, to validate unusual situations during integration testing.
In this post, I’ll use the Amazon Echo to demonstrate these capabilities, as it can be a central hub of the IoT ecosystem for the home – perhaps you even have one available like I do. I’ll start by taking you through the steps to implement your own Alexa Skill with AWS Lambda. This call will allow you to ask Alexa the weather conditions for a zip code. We’ll then deploy Parasoft virtual services in Azure to simulate responses from the Weather API for edge case testing (for example, what will Alexa say when there’s a thunderstorm or when it’s 101 F outside?).
Prerequisites to follow along yourself:
- An internet connection (obviously)
- Your own Amazon Echo or Echo Dot would improve the experience, but you can also use a simulator.
- An Amazon Developer account (https://developer.amazon.com/) and Amazon web services account (https://aws.amazon.com/)
- Sign up as a developer at https://openweathermap.org/api to receive an API key for the Open Weather API.
- A Microsoft account (https://signup.live.com) to access Microsoft Azure
- A basic understanding of REST APIs and JSON
How will this work?
In Part 1, we’ll setup our Alexa Skill and Lambda function.
- The user will say something to Alexa (the user’s input is called an “utterance”).
- Our Alexa Skill will map this “utterance” to an “intent”.
- Our Alexa Skill will send a JSON request to our function in AWS Lambda. Lambda is a powerful service from Amazon that allows you to upload some code and execute it in the cloud on-demand; you are only charged for the time when it is executing. In this example, the Lambda function will decide what to do with our intent request and will have the logic to create a response message for the user on behalf of Alexa.
- To create the response, our Lambda function must invoke the open weather API to get the current weather information.
In Part 2, we’ll deploy a Parasoft virtual server in Azure. We’ll then place a Parasoft proxy in between our Lambda function and the OpenWeatherMap API. This proxy will allow us to control weather requests from AWS Lambda, flowing to the real OpenWeatherMap API or a virtual representation with canned responses.
Part 1: Setting up our Alexa Skill and Lambda function
- First, we need to make sure that we’re in the “US East (N. Virginia)” region in our Amazon Web Services Console (https://console.aws.amazon.com). Currently, this is the only region in which Lambda is available:
- Let’s start by creating our Lambda function. Log in (https://console.aws.amazon.com/lambda/) and select the blue “Create a Lambda Function” button:
- Under “Select blueprint” choose Blank Function and then select the Alexa Skills Kit as the trigger for our Lambda function. If you don’t see “Alexa Skills Kit” in the list, you’re probably not in the “US East (N. Virginia)” region.What’s happening here? We must specify the way our Lambda function will be invoked and the Alexa Skills Kit will allow Alexa to kick it off (once it receives the correct Utterance, which we’ll configure later).
- Give the function a name like “virtualWeather” and choose “Node.js 4.3” as the runtime. For the purposes of this article, we’ll be using the Skill I’ve already built here so go ahead and download it now. If you’d like to look at the underlying source code you can find it here.
- In the code entry type dropdown, choose “Upload a .ZIP file” and select virtual-weather.zip that you downloaded in step 4.
- And add two Environment variables — host and api_key:“host” should be equal to http://api.openweathermap.org for now. “api_key” is the 32-digit alphanumeric key you will receive from OpenWeatherMap when you sign up as a Developer (see the prerequisites list above for where to do that).
- Under “Lambda function handler and role,” select “Create a custom role” under the Role dropdown. In the new window that appears, leave everything default and select “Allow.”
- Back on the “Configure function” page, you can leave the default choices for everything else and click “Next.” On the Review page, choose “Create function” if everything looks good.
- Once you’ve created the function, make sure to copy the ARN id at the top right of the page. We’ll need it later:
- Now that our Lambda function is in place, we have to define an Alexa Skill. Log in to the Amazon Developer portal (http://developer.amazon.com) and select the Alexa tab. Choose “Get Started with Alexa Skills Kit:
- Click “Add a new Skill.” Give it name and invocation name of “weather”.
- Under “Interaction Model” post the following under “Intent Schema”:
{
"intents": [
{
"slots": [
{
"name": "Zip",
"type": "AMAZON.Number"
}
],"intent": "GetWeatherForZipIntent"
}
]
}
- Post the following under Sample Utterances:GetWeatherForZipIntent what’s the weather for zip code {Zip}
GetWeatherForZipIntent what’s the weather for {Zip}
GetWeatherForZipIntent what’s the weather in {Zip}The last two steps specify exactly how our user will interact with our skill. Our sample utterances map user vocal input to Intents.
The Intent type (GetWeatherForZipIntent, in this case) and the zip code specified by the user will be sent in a request to our Lambda function. - Under Configuration, select AWS Lambda ARN (Amazon Resource Name) and enter your function ARN you copied earlier:
We’re ready to test it out! Under the Text tab, enter a sample Utterance like “what’s the weather in 91016” and click “Ask weather.” You should see the JSON request sent to your Lambda function and its response:
If your Echo is connected to this account and you’ve enabled this skill for testing on your account (you can do this on the Test page), you can speak to Alexa to test this out too. Say something like “Alexa, ask weather, what’s the weather in 91016”.
And that’s it for the Alexa setup! That wasn’t so bad, right?
But what about the central challenge of complexity and external dependencies raised at the beginning of this article? Our Lambda function relies on an external API which provides real-time, real-world data. As a developer or tester of an IoT device, how do we ensure that we are receiving the downstream data we need to test different conditions?
Let’s take a look at part of our Alexa Skill, weather.js:
We have some simple logic here which adds weather appropriate phrases based on our weather description. For example, “Grab an umbrella!” to our Alexa’s response whenever rain is mentioned in the description field of our JSON response.
So how exactly are we going to test this? Unless you have a reliable rain dance ready or you happen to live in Seattle, this isn’t going to be easy. Add test automation (for which we’d need consistent, repeatable data from the OpenWeather API which is unlikely) into the mix and we have a very tricky problem.
The easy answer, clearly, is service virtualization. This will allow us to simulate the Weather API and test different circumstances. Parasoft has a free service virtualization platform (the Continuous Testing Platform) available for a free 30-day trial in Azure.
Part 2: Using Service Virtualization to Perform Edge Case Testing on our Alexa Skill
- Log in to your Azure portal, and select “New” to access the Marketplace:
- In the Marketplace, search for “Parasoft” and select “Service Virtualization On-Demand”. You may select the “BYOL” option if you’ve previously received a special license from Parasoft. Click Create.
- Provide a name for the VM then enter a username and password. You can choose to create a new resource group for the VM or add it to an existing VM. All other options can be left at the defaults. Click OK.
- Select a virtual machine size (recommended is DS2_V2 or better). Click OK.
- Under “Settings,” you may change other configurations if desired. It is recommended that you do not change the default configuration unless you have a specific reason for doing so. Click OK.
- Click the OK on the Summary view.
- Click Purchase on the Buy view. After your free trial is complete (the first 30 days), you will be charged. The VM creation process will take several minutes to complete.
- Once the VM’s status is “Running,” select the VM and copy its Public IP Address.
- Go to Error! Hyperlink reference not valid. in your browser. The Continuous Testing Platform main menu will appear. Once the “Online Percentage” widget shows “100%,” the virtual machine is fully configured and initialized:
- Near the top, click “Add System”:
- Select “Import a system from file,” then browse to AlexaWeatherSystem.zip (Download it here). Select “AzureVirtServer” as the Target server, then click “Import”:We’ve now imported the AlexaWeatherSkill system, virtual services and associated data.
- Let’s finish by placing our proxy endpoint between our Lambda function and the OpenWeatherMap API. The proxy is deployed at Error! Hyperlink reference not valid.
Go into your virtualWeather function in AWS Lambda (https://console.aws.amazon.com/lambda/) and change the Environment Variable we created to the proxy endpoint: - In our environment (http://
/em/ui/environments/1), we can now control the data being returned to our Lambda function to test different condition. This will change our Alexa’s behavior on-demand!Select T-Storm from the dropdown under the OpenWeatherMap API component and select the “Provision” button:Traffic is now being directed to our virtual “T-Storm” service and a response (indicating rain and thunderstorms) is being returned. Say something like, “Alexa, ask virtualWeather what the weather is in 91016” and you’ll hear as a response “Grab an umbrella! Thunderstorm and heavy rain in Monrovia.”
We now have the power to control the weather!
Next Steps:
Where to go from here?
If you’re curious about modifying the existing virtual responses (or creating your own) look at http://
Currently the virtual responses will report the weather in “Test City” and not the city name associated with the zip code which you specified. You could potentially enhance the virtual services to do a look-up by zip code to provide the correct city name in the virtual response.
You can modify my Lambda function code and build/deploy it onto AWS Lambda. Perhaps you could modify the Alexa response to include more weather data returned by the API. You can find the repo at https://github.com/sdebrosse/virtualize-weather.
Once you’ve cloned it onto your Linux machine (you’ll only be able to build it on a Linux environment), you’ll need AWS CLI configured and npm/nodejs installed. From the repo folder, you can execute “npm run deploy” to deploy changes to Lambda.
I’d highly recommend Brian Donohue’s article here about creating your first Alexa skill. I also recommend Ryan Ray’s article here. I’ve adapted code from both of their tutorials for the Lambda function we used in this article.