Day 22 of the Anvil Advent Calendar

Build a web app every day until Christmas, with nothing but Python!

Give Alexa a Festive Skill

By now I’m sure you think you have enough ways to control the lights on your Christmas tree, but you’re wrong. What if there’s no cell reception, and your browser, email client and Bash terminal are all the way in the other room? Alexa to the rescue! This is the last one, I promise 1.

Today we’re going to teach Alexa to control the tree lights, and it’s only going to take 26 lines of code.

Let’s get going.

Firstly, you’ll need an Amazon Alexa device of some description. She hides in everything these days, so you’ve probably already got one - here’s a good way to find out. Make sure the device is registered to your Amazon account, then head to the Alexa Developer Console and create a new Skill. I called mine remote-christmas-tree.

Then we need to configure:

  • How to invoke the new skill
  • What commands Alexa will understand once the skill is invoked.

Head to the “Invocation” section of the Skill Builder, and give a “Skill Invocation Name” of “the christmas tree”. Then you’ll be able to say something like “Alexa, ask the Christmas tree…” and your Skill will be invoked.

Next, add an Intent (call it something like “control_tree”), and add a Sample Utterance of “switch its lights {action}”. Create a new Slot Type called something like “OnOff”, give it two possible values (“on” and “off”) and then set the type of the “{action}” slot to OnOff. Now Alexa will understand full commands like “Alexa, ask the Christmas tree to turn its lights on”. She’ll even be clever enough to spot that the value of the action slot is “on”.

This is great, but we still need to connect the new Alexa skill to our Christmas tree. That’s where Anvil comes in. Head over to your Christmas Tree app, and add an @anvil.server.http_endpoint to serve Alexa requests:

@anvil.server.http_endpoint("/alexa")
def alexa():
  req = json.loads(anvil.server.request.body.get_bytes())

My app is at https://tree-lights.anvil.app, so this API endpoint will be https://tree-lights.anvil.app/_/api/alexa. Yours will be something different, of course - check the bottom of your Server Module window for the address:

Back in the Alexa Skill Builder, set the endpoint to the URL of your Server Function:

Now, whenever you ask Alexa to control your tree lights, she will make a POST request to this endpoint, and you can control the lights and return a JSON response to tell her what to do next. Here’s my full server function:

@anvil.server.http_endpoint("/alexa")
def alexa():
  req = json.loads(anvil.server.request.body.get_bytes())
  
  try:
    action = req['request']['intent']['slots']['action']['value']
    
    if action == "on":
      anvil.server.call("lights_on")
    else:
      anvil.server.call("lights_off")
      
    response = "Sure, that's done for you."
  except Exception as e:
    response = "Sorry, the Christmas tree isn't listening to me right now. %s" % str(e)

  return {
    "version": "1.0",
    "response": {
      "outputSpeech": {
        "type": "PlainText", 
        "text": response,
      },
      "shouldEndSession": True
    }
  }

And there you have it, a fully voice-activated Christmas tree. An ingenious solution to a problem you didn’t even have. Merry Christmas!


  1. Probably. Suggestions of even sillier IOT ideas gratefully received. ↩︎


Give the Gift of Python

Share this post: