Remotely turning on my air conditioner through Google Assistant

Thai Pangsakulyanont
6 min readAug 1, 2018

--

I was trying to automate my apartment a bit. I want my room to be cool already by the time I arrive, so when I say to Google Assistant: “I’m arriving,” it should turn on my lights, my plugs, and the air conditioner (which can only be controlled using an infrared remote).

Note: I am writing this mostly for my own reference… This article assumes familiarity with setting up a Linux server, using Node.js, and Python.

For lights, I use Philips Hue, and for the plugs, I use TP-Link Kasa. Both are well-known brands and integrates with Google Assistant pretty well.

For controlling the air conditioner (AC), I have to use an infrared (IR) blaster. I’m not good at hardwares, and I don’t want to deal with DIY hardware stuff yet. I don’t know how to solder things or do GPIO.

I prefer USB ports and commercial consumer electronics.

That’s why I went ahead and bought a Broadlink RM mini 3 “Black Bean”, which is an affordable Wi-Fi and cloud controlled IR blaster.

The Broadlink RM mini 3 is designed to be used with through the Intellight Home Center (IHC) app. Unfortunately, its review is very poor. When I try to install, it requests for a lot of permissions, and that makes me very suspicious.

I am not alone in this. Quoting from the article “Home automation with a Broadlink RM Mini 3 and Google Home” by Kat Hempstalk:

I ended up deleting the Broadlink app as it had some weird permission requests and kept trying to install stuff on my phone. In short: I didn’t trust it.

Another blog post, “Broadlink smart home devices complete protocol hack” by Ipsum Domus, goes through Broadlink’s protocol in detail and highlights some of the security concerns. Quoting from that post:

All Broadlink devices have internet facing channel. It works over TCP and web sockets with the similar protocol like it does on your local network. We kindly recommend you NOT TO CONNECT those devices to your network and NOT TO EXPOSE it to Internet due to privacy and security concerns.

Because of this, I decided to do it the hard way and not let the Black Bean connect to the internet.

The Result

This is what I ended up with. Lots of components required to make it work.

  • Google Assistant takes a voice command. It is linked to IFTTT.
  • IFTTT takes the assistant command “the air conditioner is to be turned on” and performs the webhooks action. I hosted the webhook on webtask.
  • The webtask should tell the Raspberry Pi to issue an IR command. However, I don’t want to make the Raspberry Pi publicly accessible from the internet, so, having a message broker in between would be great. For IoT stuff, the obvious choice is MQTT. The webtask publishs an MQTT message to CloudMQTT.
  • CloudMQTT, a hosted MQTT broker, takes the message and publishes it to subscribers.
  • The Raspberry Pi subscribes to CloudMQTT, listens for AC controlling commands and sends the IR code to the Black Bean. It also runs a restricted Wi-Fi network for untrusted devices, including the Black Bean, which will not have access to the internet.
  • Finally, the Black Bean receives the IR code and transmits the infrared signal to the AC.

The steps I did to set them up are in reverse (labeled A, B, C, D, E, F in the diagram above).

A — Setting up a restricted Wi-Fi access point.

Ingredients: A router connected to the internet, a Raspberry Pi connected via LAN to that router, and a USB Wi-Fi adapter connected to the Pi.

I followed this guide to set up a wireless access point (using hostapd) and a DHCP server (using dnsmasq):

I skipped the part about routing (ip_forward, iptables), and network bridging, since I don’t want the restricted network to communicate with the outside world.

B1 — Setting up the Black Bean to connect to that network

It is possible to make the Black Bean connect to a Wi-Fi network without using the IHC app. I used the python-broadlink library to do it instead. Its documentation page shows you how to do it in the “Example use” section.

Once the Black Bean is connected, you can check its IP address and MAC address by checking the DHCP server’s leases file.

pi@raspberrypi:~ $ cat /var/lib/misc/dnsmasq.leases
1533999999 12:34:56:78:9a:bc 192.168.4.2 RMMINI-78-9a-bc *

B2 — Making the Black Bean emit an IR signal

BlackBeanControl is a Python CLI script that you can run to record (“learn”) an IR command and once learned, transmit the learned commands.

  • On the Raspberry Pi, clone the repository to ~/BlackBeanControl and install the dependencies as listed in the above documentation.
  • Configure the BlackBeanControl by editing its configuration file, BlackBeanControl.ini.
  • Make it learn a command by running python BlackBeanControl.py -c ac-off.
  • Most likely, it’s going to throw an error that says TypeError: init() takes exactly 4 arguments (3 given). This is because in a newer version of python-broadlink, a model number is required. Edit the script BlackBeanControl.py to add that model number:
0x2737 is for RM mini
  • Learn a command again: python BlackBeanControl.py -c ac-off. This time it should not crash.
  • Point the IR at the Black Bean and send the OFF signal. This will make the script learn the IR command and save it to the configuration file.
  • Run the same command: python BlackBeanControl.py -c ac-off.
  • Now, since the command is already learned, the script will now tell the Black Bean to emit an IR command. The AC should now be turned off.
  • Finally, make it learn the ac-on command.

Now, it should be possible to run these commands on the Pi to control the AC:

pi@raspberrypi:~/BlackBeanControl $ python BlackBeanControl.py -c ac-off
# (AC turns off)
pi@raspberrypi:~/BlackBeanControl $ python BlackBeanControl.py -c ac-on
# (AC turns on)

C — Set up CloudMQTT

  • Create a free CloudMQTT account and set up a free instance. This will give out the username and password.
  • Install Node.js.
pi@raspberrypi:~ $ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
  • Follow the instructions to also install Yarn.
  • Here is a simple script that connects to MQTT and listens to a message under the topic “ac”. I put it in ~/mqtt-ac/mqtt-ac.js. Note, I hardcoded the username and password into the script for simplicity.
  • Don’t forget to yarn add mqtt.
  • Try running the script… It should say “Connected.”
pi@raspberrypi:~/mqtt-ac $ node mqtt-ac.js
Connected.
  • In CloudMQTT’s WebSocket UI, try sending a message:
Sending the message “1” should turn the AC on, and sending the message “0” should turn it off.
  • Set up a systemd service so that this script always runs on startup and restarts itself when it crashes.

/etc/systemd/system/mqtt-ac.service:

  • To verify that everything has been set up correctly, reboot the Pi, and send an MQTT message and see if it triggers the AC.

D — Create a Webtask that sends an MQTT message

  • Under Secrets, set MQTT_URL to the CloudMQTT’s URL and set the API_KEY to a random string to protect this webtask from unauthorized access.
  • Under npm Modules, add mqtt.
  • The URL should be usable now.
$ curl "https://wt-name-0.sandbox.auth0-extend.com/mqtt-ac?key=$API_KEY&ac=1"
{} # AC should be turned on.

E — Set up IFTTT to link Google Assistant to Webtask

  • Trigger: Google Assistant — Say a simple phrase. e.g. “The air conditioner is to be turned on.”
  • Action: Webhooks — Make a web request. Put in the URL from previous step.

F — Set up a Google Assistant routine

  • In Google Assistant SettingsRoutine, set up a phrase, e.g. “I’m arriving” and have it control lights, plugs and run a custom command.

Now I can control my AC remotely. From this project, I learned about using Raspberry Pi to set up an access point, using MQTT, and integrating things together. It was fun :D

--

--

Thai Pangsakulyanont

(@dtinth) A software engineer and frontend enthusiast. A Christian. A JavaScript musician. A Ruby and Vim lover.