Controlling Anything With Alexa And Raspberry Pi

From ProjectPages
Jump to: navigation, search


The aim of this project is to demonstrate how to control anything with an Amazon Echo, via a Raspberry Pi. The key to this is the availability of IFTTT for the Amazon Echo. IFTTT lets you build applets. Applets have a trigger and an action. IFTTT now supports using Amazon Alex as a trigger. You build the trigger just by adding the phrase to say. Then, whenever you say "Alexa, trigger [my phrase]", you IFTTT action will happen. Another recent addition to IFTTT is Maker. Maker allows your IFTTT actions to be web requests.

So, we now have the situation where you can say any phrase to Alexa and trigger an IFTTT applet that fires of a web request.

Stage 2, we have a web server that receives the web request and performs an action based on that. If we use a Raspberry PI as our web server, then anything can be achieved from "Alexa, trigger the led" to "Alexa, trigger turn up my heating, or "Alexa, trigger camera feed 2". The list is endless.

Alexa - IFTTT - Pi.png

Raspberry Pi

The first step is to get you raspberry Pi set up. This tutorial assumes you are working with your raspberry Pi using an SSH link to a terminal. See my Getting Started page.

Web Service

Set Up

In order to host the web service I'm using Bottle The first thing to do is install Bottle

Installing Bottle


Now we need to create our server file. Create a sub-folder called python in you Pi home folder.

Then create another sub-folder in that called post.

If you have followed my Getting Started instructions, you can do this really easily by browsing to the Pi by name from the Windows desktop.

Save the file to the post folder

Create a file in the post folder called and copy and paste the code below into the file.

from bottle import route, run, template, post, request

# route for a GET request
def do_get():
	# get the body of the request
	body =
	# print the body 
	print body
	# return the HTML we want the user to see on screen
	return "<b>I'm here!</b>"

# route for a POST request
def do_post():
	# get the body of the request
	body =
	# print the body 
	print body
	# get the value of the 'name' parameter 
	name = request.forms.get("name")
	# get the value of the 'surname' parameter 
	surname = request.forms.get("surname")
	# return a string that concatenates the two values
	# here is where you can get the Pi to perform various actions based on the 
	# values passed in the parameters
	return "Hi {name} {surname}".format(name=name, surname=surname)
# run the server forever
run(host='', port=8080)

Run A Test

Change the current folder to post

cd python/post

Then start the server by typing


Now, fire up a browser. It must be on the same network as your PI. In other words, probably on the same router. You need to kow your Pi's IP address- you can get this by running ifconfig

Now type into the browser address bar, substituting your Pi IP address for the one shown and hit enter.

You should get the result below.

Sending a request from the browser

An extra line will have appeared on your SSH terminal as below.

Running The Server

The IP address is the address of the machine where you ran your browser

The date and time is the date and time of the request

"GET / HTTP/1.1" shows this was a GET request

200 is the return Status Code. 200 means OK

and 16 is the size of the content returned - which was <b>I'm here!</b>

So, at this point we know our server is running.

Test Code

We have tested the response to a GET request, but we can't test the POST from a browser.

But we can get our Raspberry Pi to test it. Fortunately this is really easy.

We will use the Requests library.

Just run sudo pip install requests in your SSH terminal.

Now copy and paste the code below into a file called in our ~/python/post folder.

import requests
r ='', data = {'name':'Tony','surname':'Norman'})
print r.text

Make sure you change the IP address to the IP address of your Pi as identified before.

Now, make sure is running.

In a new SSH session, Change to our post folder cd python/post.

And run by typing python

You should see the screen below.

This means the Server has received the parameters 'name':'Tony' and 'surname':'Norman'

And returned them in the string using return "Hi {name} {surname}".format(name=name, surname=surname)


Now if we look at our Server messages we can see it got the parameters surname=Norman&name=Tony

And this time the request was type POST "POST /post/try HTTP/1.1".


Going External

So, we have now shown that out Server responds to POST requests, but only from a request made on the same network.

In order for IFTTT to use our Server we have to make it accessible from the outside world.

I, like many of you, have a domestic ADSL Broadband service and my external IP address is not fixed.

That means that, if I give IFTTT my current external IP address, it could change in the future and my IFTTT applet would stop working.

We solve this using Dynamic DNS.

Essentially, a Dynamic DNS provider gives you a Domain Name, and, when an external site uses that name, it presents a DNS look up to whatever you current IP address is.

There are a number of free and paid for providers. I use no-ip.

no-ip provides a free service, on the proviso that you log in and confirm you wish to continue the service once a month. This seems to me a fair exchange. They also provide paid for services at a reasonable rate, which removes the need for renewals.

All you have to do is register with a username and you get url of [username]

Next you will need to set up your router.

First of all you need to configure your provider. Below is an example page from my BT Router. I have blanked out my username and URL.


Now external traffic can get to your router, but no further. You have to tell the router which device on your network has to receive the traffic.

This is done with Port Forwarding.

Port Forwarding is a rule in your router that says "when I get a web request from the outside world, on this particular port, I should route it to this particular IP address on my internal network"

So we need a rule that says

"when I get a web request from the outside world, on port 8080, I should route it to my Raspberry PI on - also on Port 8080"

You can choose to pass traffic on using a different port to the incoming one, but, unless you really need to, I find that confusing.

So, now we can change our to test external access.

import requests
r ='', data = {'name':'Tony','surname':'Norman'})
print r.text

Where you change yourusername to your own.

Now, when you run, you should see the same result as before, but the IP address shown by will be your External IP address


To start using IFTTT you will need to register here

Next click on My Applets and then on New Applet

Create Trigger

The first thing we are going to do is set the trigger.


Click on the + sign and you will go to the Choose a service screen

Type alexa into the search screen and you will find the Amazon Alexa Trigger


Click on the service and you will see a selection of services configured for Amazon Alexa

The one you want is Say a specific phrase

Say a specific.PNG

Click on the trigger and then enter your phrase in the box


Click on Create trigger

Create Action

Now we're going to create the action

Make action.png

Click on the + sign and you will go to the Choose action service screen

Type maker into the search and click on the Maker service

Maker service.png

Click on the Make a web request button

Maker service2.PNG

Fill in the form as below making sure you change yourusername to the right one for your Dynamic DNS.

Maker service3.PNG

Click on Create Action and you should be done.

Maker service4.PNG

Now just click on Finish

Maker service5.PNG

Trying It Out

Now just say "Alexa trigger my post"


You will see that the request was successful - return code 200 and the IP address comes from IFTTT.


As a footnote, I have produced some code to run the POST Server on an ESP8266. See my page ESP8266_POST_Server. So now you can get Alexa to control your ESP8266

An Alexa skill for openHAB has just been announced. I will be trying this next!