Switching off the lights the hard way


How many components does it take to switch on a light by voice? Here we look at what’s involved in using a Neopixel strip as a Google Home connected light bulb.

There are multiple ways of issuing commands to Google Assistant like via IFTTT or api.ai but only using Actions SDK directly lets us issue short commands like “Hey Google, lights on” rather than “Hey Google, tell house lights to switch on”. When registering as a ‘Light’, it also lets us use existing built in traits like ‘brightness and colour’ without having to write our own intents and re inventing the wheel.

Ignoring the initial OAuth handshake the flow of data is as follows:
Voice > CHIP/Phone > Google Assistant > https  > express > Mosca MQTT > ESP32 > NeoPixel

Connecting to Google Actions requires a publicly accessible https endpoint, but getting proper SSL working on embedded in a home network behind a router is not easy, to say the least. So I opted to create a Dockerized HTTPS to MQTT gateway which will run on a publicly available VPS which will forward the received https traffic via MQTT to connected devices and respond back to the request with the MQTT reply from the device.

Recently Google released the Assistant SDK which lets any arm-7 device act as a Google Home device. While this was for the Raspberry-Pi, I was also able to get it working on the $9 CHIP device I had lying around. (A raspberry pi clone with built in memory, mic in and wifi) This can also be achieved with most Android phones.

Hardware was relatively simple, just an old beats mic + headphone cable plugged into the CHIP, and one of the GPIO pins of the ESP32 connected to a NeoPixel.


There are two pre requisites for this project:

1. An O-Auth server, I created a simple docker container to set this up here or you can setup a real server like ory/hydra.

2. Since a publicly accessible https endpoint is required, a public server to accept https requests and forward them via MQTT to subscribed devices. I developed a  https to mqtt gateway using express and Mosca to do this.

This simply forwards the request body to all devices, subscribed to the MQTT channel matching the request URL. (e.g.: POST with the body OK to URL  /api/lights/kitchen will get forwarded to all MQTT clients subscribed to the /lights/kitchen channel). The gateway also allows the client to reply by appending a reply_id to which the client can reply back and this message will be returned as the https response.

The whole setup is dockerized, and this Docker image will start the http2mqtt server but since api.ai requires an SSL endpoint, follow these steps first to create an SSL certificate from letsencrypt and then update the FQDM in docker-compose.yml before starting the server with docker-compose up -d You should see something along these lines. 

Now we create a project in https://console.actions.google.com/ and pick Actions SDK. Rest of the settings does not matter except for the account linking section. Use the ngrok URL from the fake OAuth server or your OAuth server.

Next, create an action.json file with the mqtt2http server URL and run it as:

./gactions --verbose  test --action_package action.json --project neopixels-f4391

Follow the OAuth steps, now when you open the Google app > Menu > Settings > Google Assistant – Settings > Services – Home control > (+) Add device, you should see your project listed under Add new.

To link it, we need the device to respond to SYC action calls sent to the URL in the action.json we uploaded earlier. Since the URL is https://mqtt.chris.gunawardena.id.au/lights/kitchen we need to subscribe to/lights/kitchen channel and handle json requests.

Any MQTT capable device like an Arduino, ESP32 or a Raspberry-Pi can be used for this. Here I used an ESP32 which costs $20 and can be programmed using the Arduino IDE. A $5 ESP8622 also be used in place. The PubSub library was used for the MQTT client and ArduinoJson was used to parse JSON in the ESP32. All the source code can be found here.

The Final part is to link the service from Home control settings. Now you should be able to control the lights from Google Assistant.

Optionally to get Google Assistant working on the CHIP, follow these instructions but skip the two samba related steps and use this for the .asoundrc file to use in built sound card. Now when you ask something like “hey google, tell me a joke” and it should reply. *This bit is optional, or else you can use an Android phone to talk to Google Assistant and control the lights.



Leave a Reply

Your email address will not be published. Required fields are marked *