Control Raspberry Pi GPIO With Amazon Echo and Python

70,782

154

102

Posted

Introduction: Control Raspberry Pi GPIO With Amazon Echo and Python

The main goal of this instructable to use Alexa's voice commands with an Amazon Echo to control the GPIO on a Raspberry Pi using Python. This instructable has been adapted from the Memory Game example at Flask-Ask: A New Python Framework for Rapid Alexa Skills Kit Development.

An Echo is not required but is highly recommended. This is a very simple example but demonstrates how easy it is to expose the Raspberry Pi's functionality to Alexa with just a few lines of Python.

The main reason I am writing this is because I could not find a similar guide elsewhere and felt the functionality was cool enough that it deserved one. There are currently several different ways of adding custom Smart Home programming to Alexa but as far as I know this is the first method using Raspberry Pi and Python.

Step 1: Initial Setup

I used a Raspberry Pi 3 and a fresh Raspbian Jessie-lite image downloaded from https://www.raspberrypi.org/downloads/raspbian/

Two terminal sessions will be needed so using SSH to access the Pi is recommended. Once logged in, enter the following commands to install the required packages and python libraries:

sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install python2.7-dev python-dev python-pip
sudo pip install Flask flask-ask

Step 2: Setup Ngrok

I couldn't think of a better explanation so here is a quote from Amazon's guide I linked earlier:

ngrok is a command-line program that opens a secure tunnel to localhost and exposes that tunnel behind an HTTPS endpoint. ngrok makes it so Alexa can talk to your code right away. Follow the next three steps to generate a public HTTPS endpoint to 127.0.0.1:5000.

Visit https://ngrok.com/download and get the latest Linux ARM release as a zip and unzip inside the home directory:

unzip /home/pi/ngrok-stable-linux-arm.zip

Next, run it from the command line with:

sudo ./ngrok http 5000

Your screen should look like the image above. Note the 'Forwarding' URL that starts with https, it will be used later.

Note: Unfortunately the ngrok URL changes every time the service is started so it is not a permanent solution if you are trying to run this full time. I'd recommend a service like Yaler or Page Kite if you need a more permanent URL to use with your new Skill.

Step 3: Python Script

Open a new terminal session and create a new python file named gpio_control.py:

nano gpio_control.py

Copy/paste the following code into the new file:

from flask import Flask
from flask_ask import Ask, statement, convert_errors import RPi.GPIO as GPIO import logging

GPIO.setmode(GPIO.BCM)

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

logging.getLogger("flask_ask").setLevel(logging.DEBUG)

@ask.intent('GPIOControlIntent', mapping={'status': 'status', 'pin': 'pin'}) def gpio_control(status, pin):

try: pinNum = int(pin) except Exception as e: return statement('Pin number not valid.')

GPIO.setup(pinNum, GPIO.OUT)

if status in ['on', 'high']: GPIO.output(pinNum, GPIO.HIGH) if status in ['off', 'low']: GPIO.output(pinNum, GPIO.LOW)

return statement('Turning pin {} {}'.format(pin, status))

Save and close the file.

Start the flask server with:

sudo python gpio_control.py

Leave both ngrok and gpio_control.py running while we setup the new skill in AWS...

Step 4: AWS Account

First create or login to your AWS Developer Account and open your list of Alexa skills.

Step 5: Alexa Skill - Information

Set the Skill Name to 'GPIO Control' and the Invocation Name to the word(s) you want to use to activate the skill. Click 'Next' to continue.

Step 6: Alexa Skill - Interaction Model

Copy/paste the following into the 'Intent Schema' box:

{
"intents": [{

"intent": "GPIOControlIntent",

"slots": [{

"name": "status",

"type": "GPIO_CONTROL"

}, {

"name": "pin",

"type": "AMAZON.NUMBER"

}]

}]

}

Next, click 'Add Slot Type' and under 'Enter Type' write in 'GPIO_CONTROL'. Under 'Enter Values' write:

on
off

This is just a simple example. 'high', 'low' or pretty much any other word could be added.

Copy/paste the following into the 'Sample Utterances' box:

GPIOControlIntent to turn pin {pin} {status}

Click on 'Save' and then 'Next'.

Step 7: Alexa Skill - Configuration

Select 'HTTPS' as the Service Endpoint Type and select a region.

Enter the ngrok URL from step 2 and click 'Next'. The URL should be something like:

https://ed6ea04d.ngrok.io

Step 8: Alexa Skill - SSL Certificate

Select the 'My development endpoint is a sub-domain of a domain that has a wildcard certificate from a certificate authority' option and click 'Next'.

Step 9: Alexa Skill - Testing

If everything was setup correctly you should now see a screen similar to the first image above. The Skill is now enabled and can be accessed through any Amazon Echo device(or at http://echosim.io/) that is connected to your AWS Developer Account using the following syntax:

Alexa, tell Raspberry Pi to turn pin {pin number} {on or off}

For example:

Alexa, tell Raspberry Pi to turn pin twenty one on

If you are having any issues, the simplest way to test the Skill would be to use the Voice or Service Simulator found on the Test page. Try entering the following into the 'Enter Utterance' box under the Service Simulator:

 turn pin twenty one on

Then hit 'Ask GPIO Control' to run the test.

Step 10: Wrapping Up

After testing there is no need to continue through the Skill setup any further as the rest applies to releasing the skill publicly. As far as I can tell there is nothing stopping someone from running this continuously in a 'development' mode for personal use though... My ultimate goal is to use this to integrate Alexa into my existing Raspberry Pi-based Smart Home setup so that everything can be controlled hands-free.

This was my first Instructable so any feedback is appreciated. If you have any questions or trouble setting this up I will do my best to help. Good luck!

Step 11: Bonus Points - Using Words Instead of Pin Number

If you've followed all of the above steps and want to add some more functionality you can create an intent that can be called with actual words like 'fan' or 'light' by following the steps below.

Add the following code to gpio_control.py:

@ask.intent('LocationControlIntent', mapping={'status': 'status', 'location': 'location'})
def location_control(status, location):

locationDict = { 'fan': 12, 'light': 21 }

targetPin = locationDict[location]

GPIO.setup(targetPin, GPIO.OUT)

if status in ['on', 'high']: GPIO.output(targetPin, GPIO.HIGH) if status in ['off', 'low']: GPIO.output(targetPin, GPIO.LOW)

return statement('Turning {} {}!'.format(location, status))

Copy/paste the following into the 'Intent Schema' box:

{   

"intents": [{
        "intent": "LocationControlIntent",
        "slots": [{
            "name": "status",
            "type": "GPIO_CONTROL"
        },
                  {
            "name": "location",
            "type": "LOCATION"
        }]
    }]

}

Next, click 'Add Slot Type' and under 'Enter Type' write in 'LOCATION'. Under 'Enter Values' write down any words you want to be able to use to trigger this intent, for example:

fan
light
television

Copy/paste the following into the 'Sample Utterances' box:

LocationControlIntent to turn {location} {status}
LocationControlIntent to change the {location} to {status}

Click on 'Save' and it will update your settings and after that the new phrases will be usable. Example:

Alexa, tell Raspberry Pi to turn fan on
Alexa, tell Raspberry Pi to change the light to off

6 People Made This Project!

Recommendations

  • Epilog Challenge 9

    Epilog Challenge 9
  • First Time Author Contest 2018

    First Time Author Contest 2018
  • Sew Warm Contest 2018

    Sew Warm Contest 2018
user

We have a be nice policy.
Please be positive and constructive.

Tips

Questions

70 Comments

Amazon Test phase:
There was an error calling the remote endpoint, which returned HTTP 502 : Bad Gateway

to launch the script python on port 5000, use the following commands :
export FLASK_APP=gpio_control.py
python -m flask run

I'm new to python and Pi...and Linux so I might have missed something but for me to get this to work I had to add this code to the end of gpio_control.py

if __name__ == '__main__':

port = 5000 #the custom port you want

app.run(host='0.0.0.0', port=port)

thank you, I have to add your code to work:

from flask import Flask
from flask_ask import Ask, statement, convert_errors
import RPi.GPIO as GPIO
import logging

GPIO.setmode(GPIO.BCM)

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

logging.getLogger("flask_ask").setLevel(logging.DEBUG)

@ask.intent('GPIOControlIntent', mapping={'status': 'status', 'pin': 'pin'})
def gpio_control(status, pin):

try:
pinNum = int(pin)
except Exception as e:
return statement('Pin number not valid.')

GPIO.setup(pinNum, GPIO.OUT)

if pinNum == 5 or pinNum == 6 or pinNum == 26 or pinNum == 27:
if status in ['on', 'high']: GPIO.output(pinNum, GPIO.LOW) #reversed pins on relay
if status in ['off', 'low']: GPIO.output(pinNum, GPIO.HIGH)
else:
if status in ['on', 'high']: GPIO.output(pinNum, GPIO.HIGH)
if status in ['off', 'low']: GPIO.output(pinNum, GPIO.LOW)

return statement('Turning pin {} {}'.format(pin, status))

if __name__ == '__main__':
port = 5000 #the custom port you want, 5000 must be open/or port forward from the router

app.run(host='0.0.0.0', port=port)

Hi,
Thanks for such a wonderful and simple method. It really worked. But I have one question, When I say turn fan on , actually it turns off and Vice Versa...Hope there is something wrong in my relay or ??
Thanks,
Manoj

This really really sorted me out thanks

thanks man. that worked for me

this did the trick to get the gpio_control.py working.

I also had to run through some hoops to get flask up and running.

sudo apt-get install build-essential libssl-dev libffi-devython-dev

and also had to sudo pip install flask_ask as well

This helped me get it running.

Thanks