How I got my Google Home To Send Texts

Michael Habib
9 min readJan 24, 2018

--

Whenever I’m on my laptop and don’t have access to my phone I have a habit of asking my Google Home Mini to send texts for me. Unfortunately the only reply I ever get is “I can’t send texts yet”. I finally decided to try and create a simple solution to get my Google Home to send texts. It is not a robust solution but it was fun and I learned a lot from it. In this post I’m going to be showing you how I went about getting my Google Home Mini to send texts and guiding you on how you can implement the solution I created to get your Google Home to send texts as well. Since there are many ways to do this I won’t go into too much implementation details so that you can implement it how you want, if you choose to. In order to follow along you should have Docker installed, a Google account, and have a Twilio account SID and auth token. You can learn how to install Docker here and you can sign up for Twilio here.

Project Overview

The way I went about getting my Google Home Mini to send texts was a three part process. First I created a server which takes a POST request of the message to text, who the text should be sent to, and a from field for the Twilio given number. The server is in charge of sending the text by using the Twilio API. The second thing I did was create a Dockerfile that starts the server in a container and from there I deployed the container in a Google Compute Engine instance. The last step was to create the Google Action that acts as an interface to the server. The Google Action will ask who the text should be sent to and what the message is, then sends a POST request to the server with that data. All the commands that are run in this post will be through a command line / terminal.

Note:

It is completely possible to just have the Google Action be responsible for gathering the data and sending the SMS.

Pulling the Docker Image and Starting the Server

Running the next command will also pull the image so you do not have to explicitly pull the image. To run the container and start the server, run:

docker container run -d --name google-home-sms -p 8081:8081 \
-e "TWILIO_SID=XXXX" \
-e "TWILIO_TOKEN=XXX" \
itshabib/google-home-sms

The docker command starts a container and uses the itshabib/google-home-sms image, maps the host port 8081 to the container port 8081, and sets the proper environment variables used by the server. You will need to replace the Xs with your own Twilio credentials. To test this out we can send a POST request with curl like so:

curl -H "Content-Type: application/json" -d \
'{"From":"YOUR_TWILIO_NUMBER", "To":"NUMBER_TO", "Body": "Hello"}' \
http://DOCKER-MACHINE-IP:8081/api/google-home-sms

If everything worked out you should have received a response of:

{
"sent": true,
"time_stamp":"2018-01-21T07:08:25.861803959Z"
}

Keep in mind that if you are just using the Twilio free trial you can only send text messages to numbers that have been verified on the Twilio console. To send texts to anyone you need to use their paid service which is very generous for the use case of a Google Home.

Deploying the Container to a Google Compute Engine Instance

This section is optional, if you are not interested in deploying the container to the Google Cloud Platform skip on to the section of creating the Google Action. In order to complete this section you will need a Google Cloud Platform account and the cloud SDK installed on your machine. You can sign up here for an account and learn how to install the SDK here. Before launching the instance you need to create firewall rules to allow HTTP traffic and allow traffic through to the port to where the server will listen on. To create both these rules run these commands:
gcloud compute firewall-rules create allow-80 --allow tcp:80
gcloud compute firewall-rules create allow-8081 --allow tcp:8081
The next thing that is needed is the startup script that is run when the instance starts running. Create a directory and create a startup.sh file with the code below. Like before you will have to replace the Xs with your credentials.

#! /bin/bash
docker container run -d --name google-home-sms -p 8081:8081 \
-e "TWILIO_SID=XXXX" \
-e "TWILIO_TOKEN=XXX" \
itshabib/google-home-sms

Navigate to that directory and run this command to create the instance:

gcloud compute instances create sms-server \
--image cos-stable-63-10032-88-0 \
--image-project cos-cloud \
--zone us-east1-d \
--machine-type g1-small \
--metadata-from-file startup-script=startup.sh

To see if everything worked out properly use the same curl command used earlier to test the server on your local machine. The only difference is that instead of using the Docker machine IP you will need to get the external IP address of the instance. This is easily found from the Google Cloud console in the Compute Engine page. Or you can use your terminal / command line and run: gcloud compute instances describe sms-server | grep "natIP"
The output will give you the external IP you can use to test with curl.

Creating the Google Action

The first step is to create a Google Action project. To do that navigate here and then click on Actions Console. From there you will need to create a project, once created simply click on it. The page you will see at this point should like like the image below.

Select Add Actions and then in the DialogFlow card select Build, and finally Create Actions on DialogFlow. This should take you to a new window that looks like the image below. DialogFlow is a really great service and what we will be doing with it does not really do it much justice so I definitely recommend playing around and creating bigger Google Actions and / or chat bots with it.

Select Default Welcome Intent, scroll to the bottom and change the default text response to something like, “Hey! Welcome to the Google Home SMS action. You can start by saying, send a text ”, then click Save. That is really all that is needed for the welcome intent. Go back to the Intents page and at the top select Create Intent. On the new page give the intent a name such as ‘Send Text’. For the utterances fill them out to look like the images below. Utterances are the things a user can say to invoke a specific intent. Once complete click Save.

In the Action field type in text.send, and fill in the parameters so that it matches the image. The name parameter should have been filled out for you based on the utterances but you will have to create the message parameter manually. To get the highlighting for the message parameter you will need to highlight the “message” portion in your utterances. For both parameters mark them as required and fill in a couple prompts like shown. The prompts are what the Google Assistant will say to get the user to try to fill in the required parameters. If there are no prompts filled then you would have to prompt the user for the parameters through code. The reason why there is only a name parameter specified as opposed to name and number parameters is because I really only text a handful of people so I don’t see myself texting an unknown number from my Google Home. As an exercise try to get the Google Action to work for both name and numbers. Once all filled out make sure you Save.

Now you need to create the cloud function that will be responsible for sending the POST request to the server. To write cloud functions the firebase-tools library needs to be installed globally on your machine. Check out the firebase-tools GitHub page for instructions on how to install it. Once installed initialize a project by:

  1. Authenticating the firebase tool with your Google account
    firebase login
  2. Creating a directory and initializing the project
mkdir google-home-sms
cd google-home-sms
firebase init

The firebase init command will present you with different options, select Functions. Once initialized navigate to the functions directory created by the firebase tool and run:
npm install actions-on-google axios -S

This will install the necessary library to create actions on Google and axios which will be used to make the POST request. Once installed make sure your index.js file looks similar to the one bellow. I hard coded the contacts because I really only text a handful of people, so pulling from a database isn’t really necessary for me. Using Firestore to hold your contacts would be a good idea and would mean you don’t have to hard code any contacts. You can even create a small mobile app that has a sole purpose of grabbing your contacts and putting them in a database of your choosing. Then your Google Action can pull from there for its contacts. Heres the index.js:

const functions = require('firebase-functions')
const { DialogflowApp } = require('actions-on-google')
const axios = require('axios')
const SEND_TEXT = 'text.send'
const NAME_ARGUMENT = 'name'
const MESSAGE_ARGUMENT = 'message'
var contacts = {
"Michael": "18888888888",
"Kierstyn": "18888888888",
"Josh": "18888888888",
"Wilber": "18888888888"
}
var From = "8888888888"
var actualNum = "88888888888"
function sendText(app) {
const homePrefix = "Hey this is Michael texting from my Google Home: "
const homeSuffix = `. Text me back at: ${actualNum}`
const Body = homePrefix + app.getArgument(MESSAGE_ARGUMENT) + homeSuffix
const toWho = app.getArgument(NAME_ARGUMENT)
if (!(toWho in contacts)) {
app.ask(`Sorry I couldn't find ${To} in your contacts, who would you like to send a text to?`,
['Who do you want to send a text to?','Who should I send this text to?',
'Goodbye!'])
}
const To = contacts[toWho]
let instance = axios.create({
baseURL: 'http://EXTERNAL_IP:8081/api/',
headers: {'Content-Type': 'application/json'}
})
instance.post('google-home-sms', { To, Body, From, })
.then(function(response) {
app.tell(`Text sent succesfully to ${toWho}`)
})
.catch(function(err) {
console.log(err)
app.tell(`Unable to send text to ${toWho}`)
})
}
const actionMap = new Map()
actionMap.set(SEND_TEXT, sendText)
exports.googleHomeSMS = functions.https.onRequest((request, response) => {
const app = new DialogflowApp({ request, response })
console.log(`Request Headers: ${JSON.stringify(request.headers)}`)
console.log(`Request Body: ${JSON.stringify(request.body)}`)
app.handleRequest(actionMap)
})

The final steps are deploying the cloud function and changing a few settings in the DialogFlow console. To deploy the function run npm run deploy in your terminal inside the functions directory. Once the function deploys it will output a function URL, copy this URL. In the DialogFlow console click Fulfillment, enable webhooks then paste the URL, and finally at the bottom click Save. Next, click on the Send Text intent and all the way at the bottom click on Fulfillment and enable the Use Webhook setting. The last thing to do is click on Integrations then integrations settings for the Google Assistant, and add the Send Text intent to the list. Now you can test out the action in the simulator in the Actions Console. By default the invokation name for the action will be “My Test App”, you can change the name to something more appropriate like “Home SMS” from the App information in the Actions console. If everything worked out you should now be able to send texts from your Google Home. I hope you enjoyed this post and like always please feel free to comment, ask questions, or suggest a topic I can write about next.

P.S. Here is the repository holding all the code I used

--

--