Here you can find the sources of a custom Alexa skill that controls an LED strand on a Christmas tree. This repo contains:
- Java code for an AWS Lambda function which is the endpoint for the Alexa skill
- An Arduino sketch which sits between AWS IoT and a WS2811 LED strand. The sketch is optimized for running on an Arduino Yun.
If you want to build your own Alexa-controlled Christmas tree with the help of these sources you need specific hardware. This project used the following components:
- 1 x Arduino Yun with Linino OS
- 2 x WS2811 LED strand with 50 LEDs each
- 3 x Jumper wires
- 1 x Power supply adapter and 2.1mm x 5.5mm DC connector
- 1 x Micro-USB to USB cable
- 1 x Amazon Echo or Amazon Dot or Amazon Tap
The following image illustrates a typical round-trip to handle a voice user request.
The solution leverages a bunch of AWS cloud services to communicate with the hardware backend - the Christmas tree. The only things you really need to set up is the Lambda function, an S3 bucket containing the MP3 files and an IAM role with AWS IoT and Dynamo permissions. The table in Dynamo as well as the thing shadow in AWS IoT will be created on the first skill invocation on the fly.
Understand what happens on a voice user request given to an Alexa device:
- User speaks to Alexa to "
open the christmas tree". ASR and NLU magic happens in the Alexa cloud service.
- An intent is given to the skill code hosted in AWS Lambda. You can find the code in this repo.
- If the user just desires an action like "
turn on the tree" or "
start the show" without giving this skill a color for the tree it looks up the last set color in Dynamo DB. If there's a color given the skill will persist the information in the same table. This is how Alexa keeps in mind the last set color of the tree. Secondly, the action and the color command is written to a thing shadow in AWS IoT.
- If the shadow is updated an MQTT message is exposed to the delta topic of the corresponding thing. The Arduino Yun is subscribed to that topic. Side note: The name of the thing being created by the skill code is equal to the skill-id coming in (all dots replaced with a dash). This might help you if you want to rebuild the project.
- The Arduino is polling on the Delta topic so it receives the commands as an MQTT message in JSON format. The information is extracted and the Arduino sketch performs an action with the LED strand according to what is given in the message (new color, Christmas show, on, off).
- Finally, the Arduino sends an MQTT message to the Update topic of the AWS IoT thing in order to let the world know that the action was performed.
- The message is consumed by the AWS IoT service and the contained state information is written back to the thing shadow as a reported state. It would be possible to also have the skill read the last tree state from the thing shadow instead of looking it up in Dynamo DB. The reason for this fall back approach is MQTT is asynchronous and we cannot rely on the Arduino to give an immediate response.
- Actually this step happens right after step 3) as the skill is decoupled from the hardware back end on purpose. So right after updating the thing shadow in AWS IoT the skill code returns output speech text and optionally an SSML tag with audio contents. The MP3s which are part of Alexa's playback (Christmas sounds) are stored in an AWS S3 bucket.
- Alexa reads out the text returned by the skill and plays back the audio in the response.
While Arduino does its work it lets you know of its current state over the first LED in the strand.
- a one time red blinking light indicates a AWS IoT connection setup failure
- a two times red blinking light indicates a failed AWS IoT connection attempt
- a three times red blinking light indicates a failed AWS IoT connection configuration
- a green flashlight indicates a successful connection to AWS IoT
- a blue flashlight indicates constant polling to the AWS IoT topic
- a yellow flashlight indicates an error while polling the AWS IoT topic
On startup you might see red flashlights for the period of time it takes for the Arduino to connect to the WiFi. If WiFi is connected there's the green flashlight followed by a constantly blinking blue light to indicate the tree is ready for commands.
If yellow is blinking the AWS IoT topic could not be reached. If that happens (e.g. Arduino lost WiFi connection) it keeps trying for nine more times until it automatically tries to reconnect. That said, after ten times yellow flashlight there should be red/green flashlight for reconnection progress. Once the Arduino reconnects to the WiFi and AWS IoT is reached again, the blue flashlights come up.