Creating our own custom smart mirror skill based upon the hello world example.
Now it’s time to create a new Alexa skill, dedicated to our smart mirror. We will be expanding the functionality of the skill gradually, but let’s start with the most basic functionality : hiding the modules on the mirror.
You might remember from my last post that you need the US-East region in AWS to be able to make lambda functions. However, if you remember the post where I created the first table in the DynamoDB setup, it was created in a different region. You’ll need to complete those steps again in the US-East region in order for the lambda function and the DynamoDB service to communicate. Check out this post for more info. Note that you’ll have to change you aws.config file as well in order to connect to it using the debug hub.
Anyways, let’s create our function.
The first thing I did was copy the “Hello world” example on my disk to a new folder. I opened it in Atom and replaced the “Hello world” references to SmartMirror references, like this :
That’s a good starting point. That way I was able to zip the contents and upload it to AWS console. The rest of the editing can be done inside the AWS console.
When configuring the function you can choose the settings below. I created a new role from a template and chose the basic lambda execution rule. Once saved the config looks like this :
From experience I know that using this role will cause the lambda function to give an error when accessing the DynamoDB table. The reason is a lack of permissions. This is easy to solve. You have to open the IAM module. The one you used in an earlier post to create the SmartMirror user.
Locate the role by navigating to the roles in the left hand pane, and in the Permissions tab, click “Attach Policy”. Locate the “AmazonDynamoDBFullAccess” policy. In fact, this is a bit overkill. You could setup a policy to only access the CommandQueue table, but in our case this project is only intended for personal use, so i’m not worried about security right now.
Now that we’ve got the permissions thing out of the way, we can start looking at the code.
Go to the code of the function, and on top enter the following code :
That way you’ll include the AWS SDK, and instantiate a new DynamoDB interface.
In the IntentHandlers function : create a new entry for a “HideAllModulesIntent”, which we’ll be defining later on in the Alexa Skill. The code for it is displayed below :
Small note: the code doesn’t contain the definition of the “Message” variable, just add it above these lines of code.
Notice how it uses the “putItem” method. It takes a parameter (in the form a JSON format) and a callback function. The parameter contains
- The tablename
- The content of the item
Notice the special syntax. Every item is a different JSON attribute as well. The callback function is fairly simple. If the “err” object is not undefined, it means there’s been an error, and we need to act accordingly. If Not, it succeeded. Note that we call the “response.tellWithCard” function in both branches inside the callback function. You would think that’s not very optimal and put it behind the “putItem” call. Well, been there done that. That doesn’t work. It turns out that lambda function returns when the “tellWithCard” function is called, and when doing that just after the “putItem” call doesn’t give the “putItem” enough time to complete its task. That means no error will be returned, but the callback function won’t be called either. The solution is the code above.
Save the function. You can test it with the button above.
When doing so, you can see the result :
And the log
Let’s log on to the DynamoDB console and refresh the contents of the table :
That worked like a charm.
Now let’s create the Alexa Skill. Go to the Alexa Skills overview and create a new one. Empty template & settings below.
I changed the invocation name of the “hello world” sample to “hello world”, so i can use “smart mirror” for this one. If I were to choose the same one, Alexa wouldn’t know which one to choose.
The interaction mode is shown below and resembles the “hello world” example, only customised for the smart mirror.
Configure the endpoint with the ARN of the lambda function. I’ve got no screenshot of that, but it’s quite straight forward.
You can easily test it :
And there we have it. Remember to change the APP_ID in the lambda function code in order to let them communicate.
If you change the Session ID parameter in the code of the debug hub, you can also see the output in the debug hub :