Projects

Part 1: Google Assistant Controlled Devices

Mike Lewis & Rob Bell

Issue 21, April 2019

This article includes additional downloadable resources.
Please log in to access.

Log in

Now you can add the power of the Google Assistant to your own IoT devices!

BUILD TIME: 1 HOUR
DIFFICULTY RATING: Intermediate

Voice assistants such as Google Assistant, Alexa, and Siri are taking over our home automation, and it’s now opening up a host of opportunities for us makers. It’s all fun and games to buy a few smart lightbulbs and turn them on and off from the couch, but what about using this technology in your own creations?

THE BROAD OVERVIEW

The Google Assistant, and all voice assistants, provide an extremely convenient and powerful way to control loads of smart hardware now available at retailers. But we, as makers, want to do more. So much more!

Want to switch on the Air Conditioner (even if it’s not WiFi enabled) without getting out of bed? Easy. Want to power down your computer you accidentally left on? Simple. Want to activate the pet feeder? Done.

With this project, we’ll take you through how to control Raspberry Pi GPIO with a Google Home Mini. This will then enable you to voice-control the Raspberry Pi with your own custom commands, from any Google Assistant (Google Home device, Google Assistant on Android, and more). From there, you can control virtually anything!

GOOGLE HOME TOPOLOGY

Initially, when we embarked on this project we thought it would be relatively easy. Sure, the Google Home is talking to the cloud to perform processing tasks, but it’s inside your own network - so things should be pretty easy right? Wrong.

It seems a little tough to find documentation on some of the nuance of how the Google Assistant does its thing, but ultimately we determined there were no local actions from the Google Home device. That is, even though the Google Home sits on your WiFi, as does our Raspberry Pi, the Google Home won’t make any local-network requests to the Raspberry Pi. We may find that we’re actually incorrect here at some point, but we couldn’t find any reliable documentation.

In hindsight, this makes total sense - after all, Google Assistant is designed to help with broader applications outside of the network. However, this creates the perpetual challenge of punching safe holes in our firewall, or at least, finding practical and safe routes around our firewalls. This is becoming far more common as devices find ways to route traffic through the naturally open ports, left open for web browsing and such - setup of cloud-connected and remote-accessed devices has simplified dramatically for this reason.

The Build:

Parts Required:JaycarAltronicsCore Electronics
1 × Google Home Mini (or similar Google Assistant)---
1 × Raspberry Pi Zero W (or other WiFi Pi)-Z6303ACE04754
1 × Red 5mm LED*ZD0150Z0800CE05103
1 × 330Ω 1/4W Resistor*RR0560R7546PRT-14490

Parts Required:

* Quantity required, may only be sold in packs. Breadboard and prototyping hardware is also required.

Naturally, with a project like this, the physical build is fairly straightforward. It’s more about the software.

We have also decided to focus more on getting the software right, with simple GPIO activation of an LED so we know it has worked. Once this is complete, you can trigger all sorts of things - and we’ll tackle some more interesting outputs like that in Part 2.

We’re using a Raspberry Pi Zero. You’ll also need a 4GB microSD or larger. We’ve flashed our card with a fresh copy of Raspbian Stretch with desktop (without the recommended software is fine if you want to save some MB’s) or you could use Lite if you prefer command line only.

https://www.raspberrypi.org/downloads/raspbian/

We’ll assume you already have your Google Home setup. If not, follow the prompts - they make it straightforward to get going.

Once you’ve booted your Pi, connect to the internet via your local WiFi (or Ethernet will work just fine if you prefer).

As is always best practice, update your system so you have the latest repositories and apps. It seems like a small step but can save a lot of hassles later.

sudo apt-get update
sudo apt-get dist-upgrade

We need to create a web server to allow Google services to talk to our Raspberry Pi. For this, we’ll use Node.js, as it’s lightweight and fast. To install Node.js on an ARM based CPU (that is, our Raspberry Pi), we will need to download and extract the application

cd
wget https://nodejs.org/dist/v8.11.3/node-v8.11.3-linux-armv6l.tar.xz
tar -xvf node-v8.11.3-linux-armv6l.tar.xz
cd node-v8.11.3-linux-armv6l
sudo cp -R * /usr/local/

Now we create our symlinks using the code below:

sudo ln -s /usr/local/node-v8.11.3-linux-armv6l/bin/node /usr/bin/node
sudo ln -s /usr/local/node-v8.11.3-linux-armv6l/bin/npm /usr/bin/npm

Run the following command to check node has been installed correctly:

node -v
v8.11.3

Run the following code to create our server. You can press enter when prompted to accept all the default settings.

cd ~
mkdir google-home-project
cd google-home-project
npm init

We’ll install express.js, a lightweight and powerful web framework for Node.js. From the project’s directory, run:

npm install express --save

We need a file container for our code. To create a new file, type:

touch app.js

Now edit app.js and add the following code to create a very basic web server.

const express = require("express");
const app = express();
const port = 3000;
app.get("/", (req, res) => res.send ("Hello World!"));
app.listen(port, () => console.log ("app listening on port " + port));

With that in place let’s start our server! Run the following command:

node app.js

Then browse to http://localhost:3000 and you should see our Hello World message.

Congratulations - you have your Node web server running! If you didn’t see your ‘Hello World’ message, double check the previous steps.

Grab a breadboard and connect an LED to pin 7 (GPIO 4) with a 330Ω resistor, and then to Ground. Follow the fritzing provided if you need.

We now extend our application to access the GPIO and turn on/off our LED based on the HTTP request received. This is ultimately what our Google Home will control, but we need to tell our Node server to handle this also.

To gain access to the Pi’s GPIO we will use a library called onoff.

To install, run:

npm install onoff

Edit the app.js and import the onoff library, then define a LED constant to set up our pin on.

const express = require("express");
const Gpio = require("onoff").Gpio;
const app = express();
const port = 3000;
const LED = new Gpio(4, "out");

Add two routes; one for both on and off, and set the LED writeSync action. Make sure you add this above the app.listen line.

app.get("/on", (req, res) => {
  LED.writeSync(1);
  res.send("LED is on");
});
app.get("/off", (req, res) => {
  LED.writeSync(0);
  res.send("LED is off");
});

Save and head back to a browser to test. Also, ensure the server is running with node app.js.

http://localhost:3000/on

http://localhost:3000/off

If all went well your LED should be working as expected. Magic!

WORMHOLES WITH DATAPLICITY

Before we set up our Google Assistant commands, we need to allow the outside world to connect to our Raspberry Pi so that it can receive HTTP requests. There are many ways you can achieve this including setting up port-forwarding on your router/gateway. However, it’s not always the best idea, and you can easily create security holes without realising.

Instead, for this project, we’ll use a service called Dataplicity. Dataplicity allows us to create a “wormhole” to our Pi without requiring us to set up Port forwarding, firewall exceptions or Dynamic DNS.

Sign up for a free account at https://www.dataplicity.com

Follow the steps to install the Dataplicity package on your Raspberry Pi.

If you don’t have a static IP address on your internet connection, the software will update Dataplicity when your IP changes so that your Pi can still be reached. This takes the headache out of additional Dynamic DNS steps usually required too - amazing!

CONFIGURE YOUR PI ON DATAPLICITY

Once you’ve installed the software, open the device from Devices.

Next, enable the Wormhole and take note of your unique URL.

NOTES ON DATAPLICITY AND LIMITATIONS

The limitation with Dataplicity is that it will only listen on port 80, and our node application is using port 3000. Of course, we can change the port of our Node.js application to 80 (on line 4) but we would then need to run it as a root user since ports < 1024 require root access.

If you’d like to try your node app on port 80. Update line 4 of app.js to:

const port = 80;

Now start your server as root user:

sudo node app.js

Just keep in mind that this is for testing purposes and is not the recommended way to run node applications in production for security reasons.

If you open your Dataplicity Wormhole URL, you should see the ‘Hello World’ message.

PORT 3000 ON DATAPLICITY WITH THE HELP OF NGINX

If you’re happy to use port 80 for testing then you can skip this section.

We can install the nginx package as a reverse proxy and forward traffic on incoming port 80 to port 3000.

To install, type:

sudo apt-get install nginx

Then edit the nginx config file:

sudo nano /etc/nginx/sites-available/default

Delete everything within the file and add the following, replacing xxx.xxx.x.xxx with your Pi’s IP address

server {
  listen 80;
  location / {
    proxy_pass http://xxx.xxx.x.xxx:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection ‘upgrade’;
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }
}

Restart the nginx service.

sudo service nginx restart

Start your node server, and test your Wormhole URL. You should see the ‘Hello World’ test. You may have to change the port back to 3000 in app.js if you changed it previously.

This is just one of many approaches to overcome the port 3000 restrictions with Dataplicity. There are certainly areas of improvement here as we are essentially running two web server applications, but for demo purposes this is fine.

IFTTT (IF THIS THEN THAT)

The final piece of the puzzle is creating our Google Assistant commands. We will use a service called IFTTT, which stands for If This Then That.

If you’d like to go more advanced and dive deeper you could look into creating your own Google Assistant functions on the Google cloud platform, but IFTTT takes all the hard work away and is great for getting an Assistant reply up and running in minutes.

Head over to https://ifttt.com and signup for a free account.

Once you’ve logged in, head over to your account settings and link your Google account. Be sure to connect the same Google account that your Google Home is using. This is how it knows which commands to use.

CREATE YOUR VOICE COMMANDS

Now its time for the fun part. Let’s create our voice commands. Select My Applets, then New Applet.

Select +this.

Search and select Google Assistant.

For the trigger, select Say a simple phrase.

Enter the command you’d like to use.

Next, click +that

For the action service, select Webhooks, then select Make a web request.

Enter the following:

URL: https://<<your-wormhole-address>>/on
Method: Get
Content Type: text/plain
Body:   // that is, leave it blank

Click Create action, then Finish.

Repeat the same process and create an “off” command. Using https://<>/off in the webhook action, and replacing “on” with “off” in the command.

With all that in place, try out your commands on your Google Home or Google Assistant Device!

If it hasn’t worked as expected, work your way back through the system to see what steps you may have missed. Ensure your dataplicity address is accurate with no typos, and you have replaced our sample URL provided in our text here too.

The actions will take a second or two to take place. This seems fairly standard even for commercial devices controlled by Google Home, and not really a product of our approach.

NEXT MONTH: Part 2: PULLING AND PUSHING

In Part 2, we’re going to look at some more advanced webhooks, retrieving data from the Pi rather than just pushing, and more advanced controls. But don’t be afraid to play with what you already have and see what’s possible!

We’ll also implement a process manager to automatically start your Node.js server when your Pi boots. We recommend pm2, which you can investigate further too.