loading

Last month, Amazon released the Echo - a small cylinder capable of powerful voice recognition.

The Echo itself is closed source. But once you figure out the Echo's secrets, it becomes an incredibly powerful tool for voice control, enabling you to control anything in your home or apartment via voice without having to worry about the complexities of the human voice. (see: how to do voice control pre-Echo - hint: it's MUCH harder)

In this Instructable, I'll cover how to use the Amazon Echo to control any device via wifi or MQTT.

All you need is:

  1. An Amazon Echo that's set up with Amazon's instructions
  2. A Raspberry Pi or other computer running Linux
  3. The starter code

Difficulty: You'll need to know a little bit of Python programming to understand the examples.

Time required: 10 - 30 minutes from unboxing to Alexa.

Note: This Instructable is currently Linux-only. Let us know if you'd like it on other platforms - if there's enough interest, we'll look into it!

Step 1: Set Up Your Server

With your Echo up and running, let's talk hacking and home automation.

Specifically, we're about to create a server that pretends to be a WeMo device.

The Echo integrates with the WeMo home automation protocol - simply say "Alexa, discover my devices" and it'll search the local network for WeMo devices. So let's give it a device to discover!

1. Install the requirements: Python 2.7, pip and required Python modules

sudo apt-get install python-pip ; sudo pip install requests

2. Download a zip of the code from the GitHub repo

wget "https://github.com/toddmedema/echo/archive/master.zip"

3. Extract the zip file

unzip master.zip -d echo

4. Move to the newly created echo folder

cd echo/echo-master

5. Start the server - you should see some debugging text indicating the server has started polling.

python example-minimal.py

6. Say to your Echo "Alexa: discover my devices". She'll take a few seconds to find the new device. If she doesn't find it the first time, try killing and restarting the process and discovering devices again.

7. Now try it out! Say, "Alexa: turn off device", or "Alexa, device on". You'll see True or False for on/off, along with the Echo's IP address.


Footnote:

The Echo can also send commands via the Amazon cloud, using their new service called Lambda. This is a convenient way to get started with the Echo, but not great for home automation. It requires that every command include the name of the program, ie "Alexa, ask HOME to turn on the lights", and it also involves a network round trip to distant servers, which slows down the response time.

What we really want is to control local devices locally, without the prefix - ie "Alexa, turn on the lights" - which is why I'm using the WeMo protocol.

<p>exactly what I searched for!</p><p>I just want to execute a sudo command to execute a python script &quot;device-on.py&quot; or &quot;device-off.py&quot;.</p><p>How can I acchieve that? I really dont know. </p>
<p>Please read the comments below!</p><p>I write it her &quot;<a href="https://www.instructables.com/member/kevstone122" rel="nofollow">kevstone122</a> --&gt;<a href="https://www.instructables.com/member/NathanG99" rel="nofollow">NathanG99</a>&quot;<br>Total instruction!</p><p>Best regards</p><p>Kevin</p>
<p>Kannst du mir bitte ein Skript erstellen mit dem ich mehrere GPIO Pins &uuml;ber Alexa steuern kann denn der den du an Nathan geschrieben hast funktioniert irgendwie nicht und ausserdem versteh ich ih nicht xD danke LG Nico</p><p>PS: Wenn du willst kannst du mich &uuml;ber Eamil anschreiben: hihionio.mail@gmail.com</p>
<p>Many thanks for this - I found it excellent. As a newbie to both the Pi and to Python I managed to get it working relatively and executing a separate Python script for switching lights on and off.</p><p>What I'm struggling with is how I can add a level of granularity to turn specific lights or rooms on or off (similar challenge to LazerDave below). My light control program takes arguments for which room and what action. Any pointers or examples you can give that would help undestand how to get commands or arguments from Alex to become arguments to my executing Python program, would be much appreciated,</p><p>Many thanks</p>
<p>Would you be willing to share your code, please, RichardHP?</p>
<p>Sent you details LazerDave</p>
<p>Hi, Kevin! I'm also looking to execute an existing python script. The response to Geomi doesn't seem to specifically answer this question.</p><p>My specific need is that I have a ceiling fan that has 4 settings, each controlled by a separate .py script. If I say &quot;fan low&quot; it should run fanlow.py. If I say &quot;fan off&quot; it should run fanoff.py. Et cetera.</p><p>Any tips on that?</p>
<p>he tanks for this tutorial!!</p><p>But how can i start now an python programm on my raspi via voice control?</p><p>and how can i make that my rpi makes pin 22 on , when i say for example &quot; make device on&quot; ??</p><p>kind regards</p>
<p>Please read the comments below!<br>I write it her &quot;<a href="https://www.instructables.com/member/kevstone122" rel="nofollow">kevstone122</a> --&gt;<a href="https://www.instructables.com/member/NathanG99" rel="nofollow">NathanG99</a>&quot;<br>Total instruction!</p><p>Best regards</p><p>Kevin</p>
<p>I got my new echo and installed windows linux bash on ubuntu on windows. And followed all the steps. It is Responding to search for tv when i ask alexa to discover devices and there after alexa is not able to find the virtual device. There are no exceptions in the debug.</p><p>Configuration:</p><p>Amazon Echo Dot 2nd Generation</p><p>Linux on ubuntu on windows</p><p>wifi</p>
<p>Very well done. I am new to Pi and Python - but have made good use of this. It is possible to add more than one device in the TRIGGERS list. Echo sees the devices and responds to the commands (unique port number) Only issue is that the response, act(self, client_address, state) does not return the port. Not sure where the code for this is? Would it be possible add the port number in the response? I am using the response to send data to an Arduino port to control X10, etc. Thank you - and well done.</p>
<p>bump....</p>
<p>I find this very interesting. I have two Echo Dots. One has the microphones muted. When I run this script, the &quot;client_address&quot; for both Dots is returned.</p><p>192.168.11.25 is muted and in another part of the house. </p><p>DEBUG:root:Responding to ON for lamp<br>DEBUG:root:client_address 192.168.11.25<br>Published to kitchen<br>DEBUG:root:Responding to ON for lights<br>DEBUG:root:client_address 192.168.11.11<br>Published to kitchen<br>DEBUG:root:Respondings to OFF for lights<br>DEBUG:root:client_address 192.168.11.11<br>Published to kitchen<br>DEBUG:root:Respondings to OFF for lamp<br>DEBUG:root:client_address 192.168.11.25<br>Published to kitchen</p>
<p>Hello!<br></p><p>I have the same problem. I post it now again on the top. Do you find an solution already?<br><br>It doesn't matter with which i speak, i get sometimes this ip adress as feedback from the function and sometimes the other ip adress.<br>This function does not correctly work!</p><p>Thank you for your help!</p><p>Best regards</p><p>Kevin</p>
<p>I did manage to get it to return the 'name' or 'port' by changing lines 226 and 230 in fauxmo.py to:<br>success = self.action_handler.off(self.name)</p><p>or</p><p>success = self.action_handler.off(self.port)</p><p>Now example-mqtt.py returns the name or port as 'client_address' in the act()</p><p>Off to the races!</p>
<p>Many thanks <a href="https://www.instructables.com/member/breagan22" rel="nofollow">breagan22</a>, this was just what I needed as well - thanks very much for solving and sharing this.</p>
<p>Hi breagan22, looks like the author has updated the code, and now your nice little mod isn't needed anymore, as the code now includes the 'name' parameter which returns the name of the device being turned on/off. But I still thank you for your mod - it helped me at the time !</p>
<p>Thank you so much. I registered to reply just for you!</p>
<p>Hello all together!<br><br>I have an important question:</p><p>After the line &quot;def act(self, client_address, state, name):&quot; i should get back the client_adress (ip adress) of the Echo which hears the sound.<br>So now i buy the Echo and also the Echo dot. Both of them have different IP adress, but the client_adress is sometimes this and sometimes the other one.<br><br>The two Echos are in different levels in the house and so they don't here each other. The feedback of the client adress is not always correct. <br>Has somebody the same problem?<br>I want to add some general functions like &quot;light&quot;, &quot;Szene&quot; and &quot;Sound&quot; and automatically with the command &quot;light on&quot; the light in the room where the Echo is placed goes on. If i go in another room and say &quot;light on&quot; it will also switch on the correct room because i know the IP adress of this room/echo.<br><br>But this doesn't work. Has somebody an idea why this feedback is not working correct? If I switch off one off both immediatelly it will work correct and the room for this IP adress get controlled.<br>If both are online it is sometimes this ip adress and somethimes the other adress when i always speak with the same Echo. <br><br>Thank you!<br>Best regards<br>Kevin</p>
<p>Hi, I have this working - and really appreciate you sharing this. But I want to make sure the python code gets started after a reboot of the Pi, so I tried adding to crontab with the @boot command, but the python script fails. The same script work fine at the command line, and if I put it to background, but fails when invoked from cron: </p><p>crontab entry </p><blockquote>@reboot /usr/bin/python /home/pi/data/sunset/echo-master/alexa1.py &gt;&gt; /home/pi/data/sunset/cronlog.txt 2&gt;&amp;1</blockquote><p>error from cronlog.txt:</p><blockquote>Traceback (most recent call last):</blockquote><blockquote> File &quot;/home/pi/data/sunset/echo-master/alexa1.py&quot;, line 68, in &lt;module&gt;</blockquote><blockquote> u.init_socket()</blockquote><blockquote> File &quot;/home/pi/data/sunset/echo-master/fauxmo.py&quot;, line 300, in init_socket</blockquote><blockquote> dbg(&quot;Failed to initialize UPnP sockets:&quot;,e)</blockquote><blockquote>TypeError: dbg() takes exactly 1 argument (2 given)</blockquote><p>Any ideas?</p>
<p>I do it in an easy way and it is working without any problems. Immediatelly after booting the relais are ready to switch on or off:</p><p>I just add this script here with: (USERNAME change to you user=</p><p>nano /home/USERNAMER/.config/autostart/Echo.desktop</p><p>Then copy this lines inside:<br>[Desktop Entry]</p><p>Type=Application</p><p>Name=Run-echo-script</p><p>Exec=./Run-echo-script</p><p>StartupNotify=false</p><p>Save it with STRG+O<br>Close it with STRG+X<br><br>The file Run-echo-script is in the folder /home/USERNAME/<br><br>Inside I do the python script:</p><p>#!/bin/sh</p><p>#Rim-echo-script</p><p>#Startet das ECHO script</p><p>sudo python /home/kevin/echo/echo-master/example-minimal.py</p><p>I do it this way because now i am able to write an # before this start command and after the next reboot it will not start automatically.<br><br>Best regards<br>Kevin</p>
<p>I had the same problem and ended up putting the startup script in /etc/rc.local but I had to put a short sleep in before launching it for some reason. It would not launch without the sleep:</p><p>sleep 5</p><p>/home/pi/scripts/launch_example-minimal.py &amp;</p>
<p>Success ! I didn't need to move it to rc.local, but your idea of the sleep seemed to help ! I am using an older Pi Model B, so I went for 25 seconds sleep, and I am sure if I tested, I could find a lower interval, but I will probably leave it at 25. The other change I made was to go back to launching the wemo launcher script from cron which then calls the python script:</p><p>cron entry:</p><blockquote>@reboot /home/pi/data/sunset/wemo_launcher.sh &gt;&gt; /home/pi/data/sunset/cronlog.txt 2&gt;&amp;1 &amp;<br></blockquote><p>wemo_launcher.sh</p><blockquote>#!/bin/sh</blockquote><blockquote># wemo_launcher.sh</blockquote><blockquote># navigate to home directory, then to this directory, then execute python script, then back home</blockquote><blockquote>sleep 25</blockquote><blockquote>cd /</blockquote><blockquote>cd /home/pi/data/sunset/echo-master</blockquote><blockquote>python alexa1.py &amp;</blockquote><blockquote>cd /</blockquote><p>I don't know if the navigating back and forth is required, but it was in the original wemo script, and it works, so I will probably leave it alone now ;-)</p><p>Thanks for the help bruster999</p>
<p>Probably using an absolute path would do the same as changing dirs but whatever works right? LOL. I'm glad you got it working. :-)</p>
<p>Try this:</p><p>@reboot nohup /usr/bin/python /home/pi/data/sunset/echo-master/alexa1.py &gt;&gt; /home/pi/data/sunset/cronlog.txt 2&gt;&amp;1 &amp;</p>
<p>Thanks for the suggestion, but it still failed exactly the same way. Any other ideas ?</p>
<p>I don't know Linux. Can you translate this to Windows 7?</p>
<p>Hello. I think this software is special for Linux. Best way is raspberry.<br><br>What you want to do with windows. After you get the command, how you want to switch on some lights? You habe no digital outputs!?</p><p>Raspberry costs around 60&euro; with all stuff you need and that's it!</p><p><br>Best regards</p><p>Kevin</p>
<p>hello, how do you get GPIO working?</p>
<p>Hello NathanG99!<br></p><p>you need to change the file &quot;echo/echo-master/example-minimal.py&quot;<br></p><p>On the top add:<br>import RPi.GPIO as GPIO</p><p>Then set the Pin to the Output mode: Output numbers you find in google<br>GPIO.setmode(GPIO.BCM)</p><p>GPIO.setup(2,GPIO.OUT)</p><p>GPIO.setup(3,GPIO.OUT)</p><p>GPIO.setup(4,GPIO.OUT) and so on!<br><br>Then set all Outputs to off (I have the amazon 8-Relais board and there is the logic opposite. So true is off:<br>GPIO.output(2,True)</p><p>GPIO.output(3,True)</p><p>GPIO.output(4,True) and so on</p><p>After this i add 3 Funktions:<br>1) Trigger</p><p>def Trigger(Portnumber,Triggertime):</p><p> GPIO.output(Portnumber,False)</p><p> print &quot;Output&quot;, Portnumber,&quot;eingeschalten&quot;</p><p> time.sleep(Triggertime)</p><p> print &quot;Output&quot;, Portnumber,&quot;ausgeschalten&quot;</p><p> GPIO.output(Portnumber,True)</p><p>2) Switch on once</p><p>def ON(Portnumber):</p><p> GPIO.output(Portnumber,False)</p><p> print &quot;Output&quot;,Portnumber,&quot;eingeschalten&quot;</p><p>3) Switch off once</p><p>def OFF(Portnumber):</p><p> GPIO.output(Portnumber,True)</p><p> print &quot;Output&quot;, Portnumber, &quot;ausgeschalten&quot;</p><p>after this line:</p><p>def act(self, client_address, state, name):</p><p>you get back the name of your device. Start Trigger with this:</p><p> if name == &quot;YOUR DEVICE&quot;:</p><p> print &quot;Das YOUR DEVICE ist:&quot;, state, &quot;--&gt;Gesendet von Amazon Echo Dot&quot;, Clientname, &quot;:&quot;, client_address</p><p> Trigger(2,0.5)</p><p>Here the Pin two switch on for 0,5 seconds and after this off again!<br><br>Best regards <br>Kevin</p><p>(sorry I am from austria and so some text is german!)</p>
<p>Thanks so much for this great instructible. I have used your knowledge to create several ESP8266/mqtt based control nodes around my house based off one PiZero. One of the nodes is a motorized blinds control. The command to turn a light on is &quot;Alexa, <strong>turn </strong>_____ lights on/off&quot; but that's not intuitive for controlling blinds. For the blinds control I have to say &quot;Alexa, <strong>turn </strong>_____ blinds on/off&quot;. Not very natural sounding. Is there a way to change/add control wording so that I can give the command &quot;Alexa, <strong>open/close </strong>_____ blinds&quot;.</p><p>Thanks again. </p>
<p>how can i change devise on to some other name</p>
<p>Edit ~/echo/echo-master/example-minimal.py</p><p>Change the text in quotes:</p><p> TRIGGERS = {&quot;device&quot;: 52000}</p><p>to whatever you want. I used the following and it worked great</p><p> TRIGGERS = {&quot;living room lights&quot;: 52000}</p>
<p>ok. I have alexa-pi running fine on my pi-3.</p><p>seemed to get the code here running fine. But alexa fails to find any devices.</p><p>there are no errors. I can only assume scanning for devices fails to scan localhost :)</p><p>any clues?</p><p>ta</p>
<p>Hi RevJ1, do you have a firewall active on your Pi? I did, and had to update it to allow Alexa to discover the devices. Confusingly, even when the firewall was blocking, the debug output would show a query from Alexa, but crucially didn't show the 2nd message, which I think referred to an xml file. Once I updated the firewall, it worked. Try using <strong>sudo ufw status</strong> to display the rules</p>
<p>ok I have been having a little fun with this. With an Adafruit Huzzah 8266 I have Alexa-enabled my 10 year old Cuisinart coffee pot.</p><p>How I did it.</p><p>1) I modified this code to add an MQTT handler. I don't know Python, and have never used an object oriented language before (I cut my teeth on Fortran 77 and assembler on the IBM 360), so it might be a bit ugly. </p><p>#######################################################################################<br># MCW Added for MQTT Handling</p><p>import paho.mqtt.client as mqtt<br>import threading<br><br>MQTT_HOST = &quot;mqtt.home.private&quot;<br>MQTT_PORT = 1883</p><p>class mqtt_handler(object):<br> def __init__(self, topic, on_cmd, off_cmd):<br> self.topic = topic<br> self.on_cmd = on_cmd<br> self.off_cmd = off_cmd<br><br> def on(self):<br> client.publish(self.topic, self.on_cmd)<br> return True<br><br> def off(self):<br> client.publish(self.topic, self.off_cmd)<br> return True<br><br>def on_publish(client, userdata, mid):<br> if DEBUG:<br> print(&quot;mid: &quot; + str(mid))<br><br>def on_connect(mosq, obj, rc):<br> if DEBUG:<br> print(&quot;rc: &quot; + str(rc))<br>#######################################################################################</p><p>FAUXMOS = [<br> ['kitchen lights', mqtt_handler('home/lights/kitchen', 'on', 'off'), 52000],<br> ['bar lights', mqtt_handler('home/lights/bar', 'on', 'off'), 52001],<br> ['dining room lights', mqtt_handler('home/lights/dining', 'on', 'off'), 52002],<br> ['entry lights', mqtt_handler('home/lights/entry', 'on', 'off'), 52003],<br> ['office lights', mqtt_handler('home/lights/office', 'on', 'off'), 52004],<br> ['bedroom lights', mqtt_handler('home/lights/bedroom', 'on', 'off'), 52005],<br> ['living room lights', mqtt_handler('home/lights/living', 'on', 'off'), 52006],<br> ['coffee', mqtt_handler('home/coffee/brew_cmd', 'on', 'off'), 52101],<br> ['east blinds', mqtt_handler('home/blinds/east', 'on', 'off'), 52201],<br> ['south blinds', mqtt_handler('home/blinds/south', 'on', 'off'), 52202]<br>]</p><p>#######################################################################################<br># MCW Added for MQTT Handling<br>if __name__ == &quot;__main__&quot;:<br> # Startup the MQTT client in a separate thread<br> client = mqtt.Client()<br> client.connect(MQTT_HOST, MQTT_PORT, 60)<br> client.on_connect = on_connect<br> client.on_publish = on_publish<br> ct = threading.Thread(target=client.loop_forever)<br> ct.daemon = True<br> ct.start()<br>#######################################################################################</p><p>2) I run a Mosquitto MQTT server on my local CentOS system</p><p>3) I wrote C code for the Huzzah to join my wireless network, connect to the MQTT server, and subscribe to the appropriate topic.</p><p>Now I can turn my coffee on and off without getting out of bed, so lazy!</p>
<p>Hello, I really need help with getting GPIO set up?</p>
<p>Nathan what error are you getting? Is it on running the example-mqtt.py file?</p><p>Specifically socket.gaierror: Errno - 2?</p>
<p>can I make a script that waits for the line that reports state and client ip so I can say &quot;Alexa, turn on novnc&quot; and have it launch novnc and start tightvncserver at the same time. I am just learning python and do not know how to set up a script like this other thatn renaming the device to novnc</p>
<p>Is it posible to get the trigger variable that was requested sent to the mqtt example script? id like to use that to send to a differnt mqtt topic depending on the orignal device asked to be switched</p>
<p>Hi JasonF20. I had the same requirement as you, and found the answer in the reply below by <a href="https://www.instructables.com/member/breagan22" rel="nofollow">breagan22</a>. I have just made the changes to fauxmo.py and I now get the trigger value to use in my script.</p>
<p>Many thanks for this - it was just what I wanted.</p>
<p>You should also mention, that there are other gadgets which work totally offline and doesn't send everything to the cloud: https://igg.me/at/listen-to-me</p>
<p>Can i use this to run commands on the pi itself? start/stop a service?</p>
<p>This is great; thanks for doing this. I was able to bring back into service a bunch of x10 switches that had been gathering dust. I already had a way to control them using MQTT, so it was easy to add Alexa control using your code.</p>
<p>Can you please give instructions on how to make your garage doors open?</p>
<p>has anyone had trouble with the Echo recognizing the faux wemo device hosted on the pi? Echo won't detect it, neither will the companion app. Also tried an independent wemo app I found in the app store, doesn't see the device. Also not detected in Network view in Win7 (I see other UPnP devices there which work TV, PC, etc)</p><p>Not seeing any errors/exceptions being thrown in the console, python2.7 vs python3 makes no difference:</p><p> python2.7 fauxmo.py -d</p><p>Listening for UPnP broadcasts</p><p>got local address of 192.168.1.51</p><p>UPnP broadcast listener: new device registered</p><p>FauxMo device 'office lights' ready on 192.168.1.51:43089</p><p>UPnP broadcast listener: new device registered</p><p>FauxMo device 'kitchen lights' ready on 192.168.1.51:51183</p><p>Entering main loop</p>
<p>I found out the problem was I needed and actual echo device for this to discover my fauxmo devices.</p>
<p>I'm having the same issue as well even with the latest version of Fauxmo.py. Do we perhaps need to have a web server setup before we try to follow these instructions? </p>
<p>I'm experiencing the same behavior. full disclosure though, I'm running Alexa-Pi instead of using an actual Echo.</p>

About This Instructable

126,634views

469favorites

License:

More by FabricateIO:Home Automation with Amazon Echo voice control Cheap Arduino Controlled Light Sockets - Reverse Engineering RF Eye-Glowing Robotic Skull 
Add instructable to: