Home Automation with Raspberry Pi

One of the buzzwords you will have heard many times this decade is Home Automation. The idea is simple – control your home electronics (lights, fans, heaters, kettles...) from your phone or computer, and automate various tasks such as unlocking your door & turning on the lights when you come home. Exciting, right?

There are lots of ways to do this. In the interest of learning new things, I prefer to work at a low level (setting up and programming my own circuitry and code) rather than buying off-the-shelf solutions (like Amazon Alexa or WiFi-connected Philips Hue bulbs). Without further ado, here are some examples of what the finished product can do:

Lights turning on automatically when I come home
Double-clapping to toggle lights

The System

Home Automation setup with Raspberry Pi

The home of my system is a Raspberry Pi. This is a tiny, super-cheap (from ~£5) card-sized computer that runs Linux. It's perfect for use cases where it sits in a corner and does its thing. But the real beauty of it is the GPIO port, which lets it talk to the outside world. This means it is very easy to make it do things like "turn on the lights at 8AM". At 8AM, it will change one of the GPIO pins from LOW to HIGH output, and your circuitry can take it from there. (Of course, more complex behaviour is possible)

GPIO Pins on a Raspberry Pi

GPIO stands for General Purpose Input/Output. So, not only can you output something, you can also input measurements and readings from various sensors (such as motion detectors, temperature/humidity sensors, switches, etc)

My Raspberry Pi outputs to 4 Energenie sockets (communicating through an RF transmitter) and can turn them on or off at will. It can record inputs from a temperature/humidity sensor, a microphone and a motion sensor. Since the Pi is a computer, and is connected to my Wi-Fi router, it has 2 more abilities:

  1. I can control everything from my phone.
  2. It can detect when I'm home based on whether my phone is connected to the home Wi-Fi.

Amazing what it can do, right? So let's talk about the process of setting it up.


The Process

Preface: Tools

Software: I don't use Linux everyday, but I do have some experience with Python and web development. It's quite easy to program the Pi with Python if you know the basics of coding, so everything in my project was done in Python. I used Django (which allows you to make websites using Python), to set up a local server on the Pi. This allows me to access all the controls on my phone by visiting the Pi's local address from my phone.

Hardware: I have a set of 4 Energenie sockets which are controlled by a remote. This lets you plug in anything (lamps, kettles, etc.) into one of these Energenie sockets and turn it on and off at will. In addition, I used various sensors, transistors, resistors, a breadboard & a power supply for this project. All available online from sellers like Adafruit.

Part 1: Hacking the Energenie sockets

At the heart of everything sits the Raspberry Pi, connected to mains power and the Wi-Fi router. Since I already had Energenie sockets which are controlled by a wireless RF remote, it made sense to enable the Pi to talk to those. As it turns out, Energenie actually make a very handy circuit board called the Pi-mote, which can plug into your Pi and control these lights directly:

Energenie Pi-mote, which plugs into a Raspberry Pi

But that would be too easy! Let's make our own Pi-mote.

There are 2 ways to hack the communication between the remote and sockets.

  1. Connect the remote I have directly to the Raspberry Pi: The Pi can then "pretend" to be me pushing the buttons. However, this means I no longer have the remote at hand to override the sockets' states when I need to.
  2. Emulate the remote by using a new RF transmitter: "Sniff" the codes the remote transmits, and transmit those using an RF Transmitter module at will.

I've never sniffed or transmitted RF signals before, so I was keen to do this! Looking at the specs of these sockets, it turns out that they operate at 433MHz, which I learned is a popular frequency for these types of gadgets (car keys as well, although they use encryption unlike our sockets). It was pretty straightforward to find a 433MHz receiver/transmitter pair on Amazon (Prime shipping too!)

433MHz RF receivers and transmitters

Sniffing the signal

I found that the 433MHz receiver was not very good at picking up the remote's signals. So I took this excuse to buy an RTL-SDR (which is a radio receiver you can plug into your computer). This lets you listen to a large range of frequencies and not just 433MHz, meaning you can listen to radio and even airplane/police transmissions (though they might be encrypted).

RLT-Software Defined Radio

So now that we have everything we need, here's what the original Energenie RF remote transmits when you press the "On" key for all sockets:

Sniffing RF signals sent by the remote
Breaking down the sniffed signal

Ahh! It's just ones and zeros, like we used to read about in computers class at school. I clicked it a few times to make sure it's consistently the same signal (car keys use rolling codes that change with each press), and it is. So theoretically, all we need to do, is transmit the same sequence with our RF transmitter module and...

Turning the lights on by emulating the signal with the Raspberry Pi's 433MHz transmitter

Ok now I feel good enough to say it... Eureka!

Part 2: Allowing Pi to read various inputs

Wi-Fi awareness

Raspberry Pi sensing phone's presence on the home Wi-Fi network

I knew I definitely wanted the Pi to check if my phone is connected to the home Wi-Fi. It simply connects to the router's page (at 192.168.0.1) and scans the list for all connected devices. There are other ways to do this (e.g. by pinging devices over the network) but I found this much easier to implement.

Motion detection

PIR motion sensor

I wasn't quite sure how I would use this exactly, but it was easy enough to set up. The Pi can detect motion in a room using the same kind of sensor you see next to light switches in toilets. It is a Passive Infra-Red (PIR) sensor, which returns a HIGH output when something moves in the room.

Temperature/Humidity sensor

Temperature and Humidity sensor (DHT11)

This one is actually quite interesting. I don't yet use the temperature readings to trigger any outputs, but I thought it would be quite cool to see how the temperature changes in the apartment over the day. The sensor is quite small, and returns the current temperature (in Celsius) and relative humidity (in %) whenever pinged.

Microphone

Microphone sensor

I set this up to detect double claps, but it gets confused very easily. Maybe one day I'll make the recognition algorithm a bit more sophisticated...

Siri shortcuts

In iOS 12, Apple introduced the ability to add custom Siri shortcuts. By linking them to the right pages on my Django web app, I was able to connect the automation system with Siri.

Part 3: The Automation – putting it all together

A good system is user-friendly and easy to update. The quick and dirty route is to hardcode all my automation rules in a script (e.g. "turn on lights at 8AM on weekdays"). But what if I decide this should happen on all days of the week? I will need to go back to the code and program this manually. Surely we can do better!

A much more elegant solution would have everything easily extendable, with a clean UI for creating/deleting automation rules. This is where Django (our web server) comes in.

Just so we are clear, every automation rule contains a condition and an effect, just like a standard IF-THEN statement. For example, "IF the temperature is below 20 degrees (condition), THEN turn on the heater (effect)."

There are 2 parts to setting up this automation server –

  1. A user-facing system that sets up all the rules (and allows editing).
  2. A recurring script (runs every 5 sec) that checks all the rules to see if any conditions are met. If so, it actions the appropriate effect.

The User-Facing Rule System

I defined all the possible conditions and effects in a JSON file (rule_definitions.json), which is then used to produce a UI like below.

I can manually edit the JSON whenever I add a new sensor or output (that's okay because I don't expect that to be very often). The UI allows me to add more rules based on these conditions and effects. These rules are also stored in a separate JSON file (rules.json).

Rule adding system

The Recurring Script

This script has a recurring loop which goes through all the rules I have created. If the conditions for any rule are met, it will apply the desired effect. For example, at 8PM on a Monday, this rule's conditions are met, and the lights are turned on as a result.

The script will also log everything it does in a SQL database. I have defined 2 types of logs: 1) events such as "lights turned on", and 2) measurements such as "temperature = 27 degrees"

There is also a user-facing dashboard, which shows the current sensor measurements

Dashboard for viewing sensor measurements

And that's it! You've seen a sneak peek of what this system can do at the start of this article. Some other functionality examples are:

  • Turning on a heater & kettle/coffee-maker in the morning
  • Turning on room lights when you enter (by sensing motion)
  • Playing music for 10 minutes as you fall asleep, then turn it off
  • Unlocking the door when you come home
  • Motion sensing burglar alarm which emails you a picture if it detects something wrong

The possibilities are endless, and it is fairly easy to connect more devices and sensors. Let me know if you set up your own home automation system!