Google Home + Raspberry Pi Power Strip

18,277

39

54

Posted

Introduction: Google Home + Raspberry Pi Power Strip

UPDATE #2: IFTTT changes:

My existing IFTTT commands through the maker channel are still working, but they've changed the naming structure since I made this guide. New commands still use the Google Assistant trigger, but the web requests are now handled by the "Webhooks" action.

UPDATE #1: Starter Application Now Available!

Hello World!

Now that the Google Home is out, there are lots of people wondering how to use it to control their existing Arduino or Raspberry Pi smart devices. Now that I've got my setup working, I thought I would share my fairly simple setup with you.

While I am currently using a Raspberry Pi Zero to control a five outlet power strip, This guide is more general. It will walk you through how to use any Raspberry Pi device to control an electronic relay, using Node.js and the IFTTT web services.

Check out a video of the device in action, or scroll to the final step, where I have it embedded!

https://www.youtube.com/watch?v=mCTjZTCaTzM

Step 1: What You'll Need

At the very least, you will need:

And the rest is software. If you are totally new to Raspberry Pi, be aware that you may need some additional hardware like usb cables or wifi chips in order to get up and running.

Step 2: On-Board Software Setup

So, to make this guide as user-friendly as possible, I'm going to include some links that you power-users might find excessive.

TLDR in advance: set up your raspberry pi on WiFi or Ethernet (preferably WiFi) and configure your router so that you have a server available externally. You'll use raspberry-gpio-python to control the relay.

For newer hobbyists, you will start out by setting up your raspberry pi.

You will want to get your raspberry pi set up on your local WiFi.

I'll be working in Node.js, so you will want to upgrade to the latest version of Node.

Configure the router so that port 80 redirects to your raspberry Pi's MAC address. (Sorry, this will depend on what router you're using, and there isn't really a universal guide)

I prefer using SSH to connect to my raspberry pi.

Plenty of things can go wrong in this process while you're starting out. Stay patient, and google things. The community is very supportive, and the odds are someone else has had your problem before!

Step 3: Make a Circuit

So, there are lots of guides on getting started with relays on the Rasberry Pi. I mostly used Youtube tutorials like this one to get started.

Basically, you will need to provide power from your Raspberry Pi's 5v out pin, and choose which control pins you want to use to send the on/off signal to trigger the relay.

Using the above image, I recommend using the yellow pins for whichever model you use.

Step 4: Create Your Server

Starter application now available!

Vist https://github.com/krpeacock/google_home_starter to download a starter application for this project, and follow the README to get it configured and running on your own device.

You can also check out my more-fleshed-out React project at https://github.com/krpeacock/power_strip/tree/strip if you are interested in seeing a slightly more complex version of the project

The main step is to build an Node + Express server that is able to handle POST requests.

In my code, it looks like this:

app.post('/api/switches/:id', function(req, res){  

  var foundSwitch = getSwitch(req.params.id);  

  foundSwitch.toggle();  

  saveState();  

  console.log("postSwitch "+JSON.stringify(foundSwitch));  

  res.json(foundSwitch);

})

I make a post request to /api/switches/:id, where id is written as sw1, sw2, and so on. After identifying the switch, I call a toggle() method to run my Python script and change the state of my relay.

I wrote individual python scripts for off and on functions, specifying which GPIO pin was tied to each switch. for example, sw1_on.py looks like:

import RPi.GPIO as GPIO<br>GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.OUT)

Then, by requiring the Python-shell node module, I can execute the script, using:

<p>const PythonShell = require('python-shell');</p><p>PythonShell.run('./public/python/scripts/sw1_on.py')</p>

Looking back, this is a little bit tricky for a non-developer. I probably will need to throw in some starter code down the road.

Step 5: Connecting to the Google Home

If you've managed to get this far, this information is probably the only reason that you're here. That's fine! this is the cool bit.

You have your server running, and it can control a relay. It is structured so that a POST request can change the state of the relay. Now all you need is to get your Google Home to deliver a POST request to your device. Eventually, you will want to add some authorization so that strangers can't control your devices, but now we just want the request to work.

  1. Go to https://ifttt.com and connect it to your Google account.
  2. Go to https://ifttt.com/create, and click on the +this link.
  3. Search for Google Assistant
  4. Select Google Assistant
  5. Choose "Say a simple phrase" as your trigger
  6. Tell Google what should trigger the action.
    • I prefer to name use the device I want to control, so I said "turn my lamp on"
  7. Designate a response
    • "Turning your lamp on"
  8. Click "Create Trigger" and proceed
  9. Click the +that link
  10. Search for "Webhooks"
  11. Select "Make a web request"

Now, here is the important bit. Identify your IP address (or domain, if you set up that level of abstraction), and enter it into the URL portion. If you followed my the structure in my starter project, it will look like

http://ipaddressgoeshere/API/switches/sw1?password=yourpasswordhere

Set Method to POST

Content Type should be text/plain

Body can be left blank

Create your action and choose Finish.

Step 6: Congrats!

You've done it! Your Google Home now knows how to communicate over HTTP with your smart device.

Since this does a toggle, you can technically keep saying "Turn the lamp on" to turn it on and off. I preferred to add duplicate on and off commands for each of my switches to make everything feel more comfortable.

If you would like to contribute to this guide, or to work with me on building out a starter application, you can also feel free to get in touch! I want to make this process as easy as possible for new hackers.

Share

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

49 Comments

Hi Kyle

thanks for putting this up. I'm able to get the starter app running and when I type npm start i get the following (which I assume means its running normally)

pi@raspberry:~/google_home_starter $ npm start

> google_home_controller@1.0.0 start /home/pi/google_home_starter

> node app.js

Listening on port 8000

However ,when I try your actual code which is in power strip i get the following error :

pi@raspberry:~/power_strip $ npm start

> strip@1.0.0 start /home/pi/power_strip

> node app.js

Listening on port 8000

events.js:182

throw er; // Unhandled 'error' event

^

Error: ENOENT: no such file or directory, open 'saveState.json'

npm ERR! code ELIFECYCLE

npm ERR! errno 1

npm ERR! strip@1.0.0 start: `node app.js`

npm ERR! Exit status 1

npm ERR!

npm ERR! Failed at the strip@1.0.0 start script.

npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:

npm ERR! /home/pi/.npm/_logs/2017-07-02T20_41_00_338Z-debug.log

Any idea what could be going on here. Im very new to node and have very limited experience so pardon my ignorance !

thanks

That will be an easy fix. The raspberry pi doesn't have a copy of the saveState.json file, because I disabled git tracking for it. It gets annoying when normal app functioning creates changes to the app.

In retrospect, I should have used a default state to start the app, but it's easy enough to copy the file over.

Copy the text from your computer's saveState. Run `touch saveState.json` in the root directory of your raspberry pi app and paste the contents in. That should do it for you!

Thanks for the quick reply! I realized after I wrote the comment that I was missing the file so I downloaded the zip file and it does run successfully now. Only problem is I can't get it to run on port 80 my router complains of a conflict with another virtual sever. Port 8080 works. Can I just edit the URL on the ifft applet to do the following?
http://ipaddressgoeshere/API/switches/sw1?password=yourpasswordhere:8080
Thanks

Did you ever get a response on this? I want to start this project, but unfortunately have a router that's set up through my apartment complex. I don't have administrative permissions on it to open up port 80, but it does have other ports that are "LISTENING" and I'm wondering if I could just use one of those instead. I'm a super beginner, but I love the struggle so I'm hoping to be able to do this project.

The solution that NielsK8 posted a little while ago using Dataplicity's wormhole feature ought to work for your use case. I've also experimented with using a tailable MongoDb instance that allows me to detect when a change to the data store occurs, so that I can have my server listen to an external data source when changing state.

Hi there!

Nice instructable! It immediately (web)hooked me up. ;)

I just succesfully implemented a slightly varied version, where I use my raspberry pi together with a 433 mhz sender
to switch a power outlet using pilight. It's very flexible (pilight can switch all kind of devices) and your raspberry
can be far away from your lamp as well. However when I came to the point, that I could sussesfully send a post web request
within my home network, I struggled with the publicly available webserver, because my router does not have the option for
port forwarding. Gladly after some digging, I stumbled upon the service provided by Dataplicity (https://www.dataplicity.com/, also mentioned
on https://www.raspberrypi.org/documentation/remote-access/access-over-Internet/),
which has the "Wormhole" feature, that provides you with a publicly available URL. I could send then succesfully pull a post web request from outside
my own home network, by just replacing my raspberry's ip adress with this URL. Prerequisite was of course, that the Node + Express server mentioned
in the instructable was running and listening to port 80. Some tips for the beginner (like me) concerning web server stuff: Before you
actually get to step 5, I would test if the post web request is working. Under windows there is a nice add-on for Chrome (Restlet client) with which
you can test if your post web request works. To check if it worked outside my home network, I used my phone as a hot spot.

Also, in case node.js is complaining about port 80 already occupied: Check with sudo netstat -apn | grep tcp | grep LISTEN, if something else might
be already listening to port 80. You might "accidentally" already have an apache web server up and running.

In the end I had one silly problem: My google home didn't trigger (though it worked before a couple of times), because I had changed the trigger sentences and put a period "." at the end.

Hope this tips can be of use for someone else.

I'm glad you were able to use this guide as a starting point for your own project! Your workaround with Dataplicity will probably help out a bunch of people who don't have port-forwarding control over the router that the server will be running on. Thanks for contributing!

Hi there! Great project you've got there. I followed you're steps and managed to get to the point where i'm getting:

{"id":"sw1","state":"off","name":"Lamp"}

from

http://ipaddressgoeshere/API/switches/sw1?password=yourpasswordhere

I also getting the right answer from google home when i'm asking to turn the lamp on, but no relay is clicking. So what am i doing wrong here?

I also tried to edit sw1_on.py and added GPIO.output(17, 1), when i run it from my terminal the light is turning on but still cant activate it through Google Home.

Maybe i did put the wrong address in IFTTT Configuration, i used

http://ipaddressgoeshere/API/switches/sw1?password=yourpasswordhere

as URL with my ip and password ofc.

I don't get it, where did i go wrong?

Sorry for the delayed response. It sounds like you've gotten all of the software working correctly, but that the hardware isn't working. Does the light turn on when you execute the python script directly from command line on the raspberry pi?