The Random Ramblings

lost? dazed? confused? dont come here then as this aint goona help!!

Building an Alexa skill

I broke, the price of the dot dropped to match the google home so I got one. This now means that I can actually use some skills and start the home automation piece. First thing on the list, the temperaure of the boys room. We have a Groegg which is good as long as you can be arsed to go to the room. The misses is paranoid about getting the temperature right, which has done more dmage to my nees than the years of playing rugby. The answer, a Pi Zero with temperature sensore wrtiing bac to a database and then an app to show the temperature. First part was easy, I had been playing with this previously, so this was a case of finishing it off by actualy soldering components to a board and attaching it all together. The app is a different matter, time and the faff has said no. Now, Alexa to the rescue. Why? It so easy and I dont need to thin kinterfaces, refreshing. A simple question, grab the latests info and send it back. So easy, I think its perfect to give a quick walk through.

This is going to be built in python, simply because thats what I am most confitable with, both in AWS terms and Alexa. Who knows, I might get round to using the javascript I learned many moons ago and build an app in that at somepoint but back to the task in hand.

  • virtualenv, yeah pyenv and pipenv should be how you do it but virtualenv will keep it all in the folder you are in, something thats very important for lambda. I know this works so its what I keep to right now.

  • Activate the virtualenv

  • pip install flask-ask zappa flask-ask is a really good frame work by John Wheeler (no I havent yet done wnything on his page), that means you dont have to think about all the requirements that amazon put on you. You can go from nothing to an app very very quickly. As this is going to be powered by lambda, zapper is a tool that does the deployment and setup for you. Other out there are serverless but, once aging, not really tried it but have heared lots of good things. Once again, remember, the standing up of this app is just about getting it done. One additional package is required, Boto3. This is already installed on lambda

  • The code:-

import boto3
import time

from boto3.dynamodb.conditions import Key, Attr
from datetime import datetime, timedelta, date
from flask import Flask
from flask_ask import Ask, request, statement

dynamodb = boto3.resource('dynamodb', region_name='eu-west-2')
temp1 = dynamodb.Table('temp1')

app = Flask(__name__)
ask = Ask(app, '/')

@ask.launch
def launch():
    return get_temp()

@ask.intent('TemperatureIntent')
def get_temp():
    now = datetime.today()
    weekago = now-timedelta(days=7)
    timestampnow =  time.mktime(now.timetuple())
    timestampweekago = time.mktime(weekago.timetuple())
    response = temp1.query(
            KeyConditionExpression=Key('date').eq(str(date.today()))  & Key('timestamp').between( str(timestampweekago),
                                                                                                 str(timestampnow) ),
            ScanIndexForward=False,
            Limit=1
            )
    speech_text = "The temperature is %s" % response['Items'][0]['temp']
    return statement(speech_text).simple_card(speech_text)

@ask.intent('AMAZON.HelpIntent')
def help():
    help_text = "This will give you the latest recorded temperature in Harri's room"
    return statement(help_text)


@ask.intent('AMAZON.StopIntent')
def stop():
    bye_text = ""
    return statement(bye_text)


@ask.intent('AMAZON.CancelIntent')
def cancel():
    bye_text = ""
    return statement(bye_text)


@ask.session_ended
def session_ended():
    return "{}", 200

if __name__ == '__main__':
    app.run()
  • deploy using zappa:- zappa init - follow the questions, if this is your first time the default are normally pretty good zappa deploy live - live should equal what you used for your environment name in the above init task A quick test of the function in lambda to check its working.

  • Drop on to developer.amazon.com and log in. Alexa -> Alexa skills kit and hit the add new skill button.

  • You now have to work through the stages for getting the app certified, this app is never going to see the public so we dont have to worry about certification but you still need to go through most of the steps.

  • Skill Information The type is a custom interaction model Language is English (u.K.) Name, names are not unique in the skills environment so you never have to worry but you must consider you cant install two apps with the same name. As this isn't going to be public I can obviously change it whenever I want but, just so it makes sense I have called mine Harri's room temp. Invocation name, this is what you ask alexa. Normally I just repeat the name but in this case I have decided Harri's room. Global fields all stay the shameless

  • Interaction model, I stay in the classic view, mostly because I know what I'm doing and what I want making it slightly quicker. I'm sure you can just copy and paste information in as I currently do, I just didnt find it when I last played with the beta. Its just a very imposing interface, that I can see the value in for new devs. Anyway, for this example, just remember that. Intent Schema

{
"intents": [
  {
    "intent": "TemperatureIntent"
  },
  {
    "intent": "AMAZON.HelpIntent"
  },
  {
    "intent": "AMAZON.StopIntent"
  },
  {
    "intent": "AMAZON.CancelIntent"
  }
  ]
}

No custom slot type, this is only returning one piece of Information Sample Utterances 'TemperatureIntent temp'

  • Configuration. Endpoint. As I am using zappa you cant use lambda, so you need to point it at https and then copy the api gateway endpoint address you have from zappa geogrphical endpoints is a no Account linking no Permissions, everything remains blank

  • SSL Cert. we are using api gateway so amazon have a cert there for us so you need to select "My development endpoint is a sub-domain of a domain that has a wildcard certificate from a certificate authority"

  • Test. Only done so you know it will work. We Can see there is only one custom intent and that needs the utterance temp so all thats needed to test is entering the word temp in the text utterance and see what it returns. If you see something like

{
  "version": "1.0",
  "response": {
    "outputSpeech": {
      "text": "The temperature is 17.625",
      "type": "PlainText"
    },
    "card": {
      "title": "The temperature is 17.625"
    },
    "speechletResponse": {
      "outputSpeech": {
        "text": "The temperature is 17.625"
      },
      "card": {
        "title": "The temperature is 17.625"
      },
      "shouldEndSession": true
    }
  },
  "sessionAttributes": {}
}

Then you know its working fine

  • Thats it, your not pusing this out to the public so no need for anything else you just need to announce loudly to your Alexa device

"Alexa ask harris room temp"

and it should tell you its 17.625.

Obviously there is way more to this when you want to do something you are going to release to the public, I could also go through the code but, as stated at the start, this is a quick walk through. If you have any questions, drop me a line email, social media or at some point I might add discus to the blog at somepoint, if thats there drop me a question there.

Find Me
Category
100daysofcode
Alexa
films
Javascript learning