Chunliang Lyu

I am a developer and researcher from China. Love to make fun and useful stuff. Co-founded Hyperlink.

Control Air Conditioner with Raspberry Pi

Published: 2013-08-07

In our university, the air conditioner in the student hostel is pretty old. There is no built-in temperature sensor, so you need to control the ons and offs by toggling the switch.

It is a pain at the night, when you need to get off the bed, go to the switch and toggle the air conditioner.

The repository is hosted at https://github.com/cllu/PiCooler.

Necessary packages, we use Python 2.

Design

At first I want to use a motor or something to simulate the toggle of the switch. However, I found that would complicate things. A more brute way is to install a relay in the switch, so I can use a 5V signal to control 220V current. Since I only need to install the device once, this seems reasonable. What's more, a relay with 220V/5A only costs 2 RMB.

For the controller, I go to the Raspberry Pi without hesitation. Everybody is talking about it, so this little project is a nice way to get to know it. Raspberry has all the things I need, a few GPIO pins, an Internet connection, and my favorite system Linux.

Sensor

For the temperature sensor, I choose the DHT 22 chip. It also supports humidity sensor and has pretty good accuracy. What's more, there are existing libraries for communicating with DHT chip here.

To use the C driver, compile and run the DHT binary:

$ cd DHT && make
$ ./DHT 2322 25

Relay

For simplicity, I wire up the circuit on a breadboard,

 which looks like the following:

Breadboard
Breadboard

In the final design, I have included another set of relay used to control the humidifier. The DHT 22 already reports the humidity, so adding a humidifier is an easy piece.

Web interface

Terminal stuff is cool, but I cannot stand behind a computer always. The way I like is to expose an HTTP server, thus I can operate on mobile devices. I choose Flask since it is simple. For a interface like this, I use jQuery and Bootstrap. The final look-and-feel is like:

To start server on system boot, add to the cron:

@reboot python /home/pi/PiCooler/runserver.py

iOS Home Screen

With the following lines in the header, you can add the webpage to iOS home screen in Safari.

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, minimal-ui">
<meta name="apple-mobile-web-app-capable" content="yes">

Cron

It is better to use separate power supply for the relay, since a relay usually requires more current than the GPIO can provide. The GPIO can draw at most 10ms current.

To automatically toggle on and off the air conditioner, we need to check the temperature periodically, say every one minutes. I have exposed an API endpoint /cron, that will check the temperature and toggle switch accordingly when called. We need to continuously call the cron functions. Add the following line to crontab sudo crontab -e.

* * * * * wget -O - -q -t 1 http://localhost:31415/cron

I wrote a simple web interface to allow me toggle the switch with a browser.

Remote Control

The web server is started using Flask. Flask is not designed to run in a long time period. tornado is used to serve the requests.

To start the server automatically, we add it to the crontab with @reboot. A better way is to use supervisord which can restart the process if exception happens. But here cron is enough for us.

The Raspberry Pi connects to the Internet via the Ethernet connection. Thus I can open a port on my remote VPS server, and control the air conditioner from office. This means I need to expose the 31345 port to somewhere on the Internet. The way I use is SSH tunnel, expose the 31345 port on Raspberry Pi to a VPS server. The connection is made by ssh proxy, maintained by autossh. autossh can monitor the SSH connection, and when the connection is lost, automatically re-connect.

#!/usr/bin/env bash

# -f run in the background
autossh -f -M 52523 -nNTR 31415:localhost:31415 [email protected]

The requests are proxied by nginx, which provides a simple HTTP authentication.

server {
  listen       80;
  server_name  cooler.cllu.me;
  location / {
      proxy_pass http://localhost:31415;
      index  index.html;
      
      # authentication
      auth_basic "Restricted";
      auth_basic_user_file /etc/nginx/.htpasswd;  #For Basic Auth
  }
}

It is not secure to use basic authentication via HTTP. A simple way is to enable CloudFlare SSL. It encrypts the communication between you and CloudFlare, and the traffic between CloudFlare and your server is still plain text. Better that none. Of cause, you can buy a certificate, or self-sign a certificate.

Keep the Internet connection

The tricky part is to connect to the Internet. Why it is tricky? The university's network requires login via a Webpage, and the system requires authentication every eight hours. So here is a script, that checks the Internet connection every minute. If we have lost the connection, send the authentication information to the server.

#!/usr/bin/env python

import requests

def login():
    """Post the login info to the CUHK authentication server"""
    url = "https://securelogin.net.cuhk.edu.hk/cgi-bin/login"
    data = {
        'user': 'sXXXXXXXXXX',
        'password': 'YOUR_PASSWORD',
        'cmd': 'authenticate',
        'Login': 1
    }
    resp = requests.post(url, data=data)
    print(resp.url, resp.content)

def connected():
    """Check if we have Internet connection"""
    try:
        resp = requests.get('http://www.google.com.hk')
        return "securelogin.net.cuhk.edu.hk" not in resp.url:
    except Exception as err: 
        pass
    return False

if __name__ == "__main__":
    if not connected():
        login()
    print("Connection status:", connected())

See also this gist.

Add the following cron job:

* * * * * python /home/pi/stayconnected.py

Security

Since the Raspberry Pi is online now, it is better to make it safer. Several things I have done:

  • Change the password for the pi user
  • For SSH, disable root login, disable password login, change to another port
  • Block all other ports except for the SSH port
    1. References
  • For the drawing of the breadboard, I use the awesome Fritzing app, with Raspberry Pi library from here.