Home Automation systems are becoming increasingly popular for the level of convenience they offer. Imagine sitting on your couch and turning on/off lights or fans in the room without having to get up. You could also control blinds or even door locks.
This project is a simple example of what a Home Automation System looks like with the Raspberry Pi. For this project, I shall use Flask, a microframework available with Python.
Contents
- What is Flask?
- Components required
- Installing Flask on Raspberry Pi
- Creating a simple webserver
- Hardware Connections
- DHT11 Sensor Library
- Creating A Web Page Template
- Creating our Home Automation System
- Video Demonstration
- Future Scope
What is Flask?
Flask is a simple microframework available with Python. The word “micro” can be misleading here. It does not mean that your entire application will fit into a single python file (small applications can), but it means that the Flask core is simple yet extensible. Flask does not make decisions for you. You are given the freedom to include relevant functionality in your projects without following strict rules. Flask includes a powerful templating engine called Jinja, which is modeled on Django’s templates. You need basic knowledge in HTML and CSS for your projects. Although not a must as you can find many free templates online, a basic knowledge of HTML and CSS would enable you to add greater functionality to your projects.
In this project, we shall see how to use Flask to turn our Raspberry Pi into a web server through which we can control its GPIO pins.
Components Required
- Raspberry Pi ( I have used a Raspberry Pi 4 Model B)
- 2x LED’s (Different colors for better clarity)
- 1xDHT11 Temperature and Humidity Sensor
- USB C Power Cable
Installing Flask on Raspberry Pi
Installing Flask on your Raspberry Pi is extremely easy.
Open a terminal (Ctrl + Alt + T) and type the following:
sudo apt-get install python3-flask
That’s it. Flask is installed in your Raspberry Pi. Although Flask does recommend the use of virtual environments, for our small application we shall skip that part. Now type the following.
cd Documents
In the Documents folder, create a folder that will contain all the files in our application. Let us name this folder as RpiFlaskServer.
mkdir RpiFlaskServer
cd RpiFlaskServer
Now, this is how the folder structure will look.
RpiFlaskServer
-static
-templates
run.py
The two folders static and templates can be created using:
mkdir static
mkdir templates
Even dynamic web applications contain static files such as CSS or javascript files. These files will be stored in the static folder. The HTML templates (jinja2 templates as well) are stored in the templates folder. These templates will form the backbone of our application.
Creating a simple webserver
Now that we have installed Flask, let us create a simple web server on the Raspberry Pi.
Open a text editor on your Raspberry Pi. I prefer Geany Programming IDE (can be accessed from the Programming Menu). You can use Thonny IDE or even Nano.
In the IDE, paste the following code:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
Save this file as hello.py (any name you want) in the RpiFlaskServer folder. Congratulations! You have created a basic Flask application on the Raspberry Pi.
The code is simple to understand.
- First, we imported the flask library.
- app = Flask(__name__) creates an instance of this class. __name__ is used to start it as an application. If we were using it as a module we shall be using __main__ versus the actual import name. This tells Flask where to look for templates or static files.
- We use the route() decorator to enable a particular URL to trigger the hello_world() function.
- The hello_world function will simply return ‘Hello, World!’ on our screen.
To start our application, open a terminal and navigate to the RpiFlaskServer directory where the hello.py application is saved.
$ export FLASK_APP=hello.py
$ flask run
The above code should get our application up and running. However, we can run this application only locally (on the same computer).
To make the server listen on all public IP’s we type the following:
flask run --host=0.0.0.0
Now any computer/device connected on the same network can access this application.
Open a browser on any computer/device and type the IP address of your Raspberry Pi in the address bar.
(Type ifconfig in a terminal window, the address in from of wlan0 will be the IP address of your Raspberry Pi)
Hardware Connections
Make the hardware connections as shown in the picture below:
In Raspberry Pi 3 and 4, the Board numbers for the Red and Blue LEDs are 32 and 36 respectively. Use GPIO.BOARD numbering preferably. The DHT11 sensor that I used has 3 pins (Vcc, Data, and GND). In the sensor shown above, the 3rd pin has no connection. We have Vcc, Data, and GND from left to right.
Check out the Raspberry Pi pin diagram and the difference between BOARD and BCM numbering here.
DHT11 Sensor Library
To install the DHT11 library for Raspberry Pi, open a terminal and type the following code:
$ sudo apt update
$ sudo apt install git
$ git clone https://github.com/adafruit/Adafruit_Python_DHT.git
$ cd Adafruit_Python_DHT
$ sudo python setup.py install
The DHT11 library from Adafruit is now installed in your Raspberry Pi.
Creating A Web Page Template
We shall now create our first template that will go in the templates folder. Open Geany IDE or nano and create a file called hello.html.
<!doctype html>
<title>Hello from Flask</title>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello, World!</h1>
{% endif %}
Note that anything enclosed in double curly braces will be treated as a variable that will be passed to our python script. Now let us write a simple python script app.py and save it in the RpiFlaskServer directory.
from flask import render_template,Flask
app=Flask(__name__)
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)
The render_template function makes it very easy to use HTML with python. We just need to pass hello.html that we created earlier as an argument along with the name variable.
Now after we run this application, we can call it using two ways.
If we type “127.0.0.1:500/hello” in the address bar we get the following output
If we type “127.0.0.1/hello/Aditya” in the address bar, we get:
We can create a style.css file and store it in the static folder
body {
background: black;
color: yellow;
}
We just have to add the following line in hello.html:
<!doctype html>
<head>
<title>Hello from Flask</title>
<link rel="stylesheet" href='../static/style.css'/>
</head>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello, World!</h1>
{% endif %}
The link attribute will help the HTML file to indetify the style.css file from the static folder. Now our webpage looks like this.
Now that we have understood the basic application and template, let us make our home automation system.
Creating our home automation system
Python Application Script
Let us first look at the application python script, run.py :
#/home/pi/Documents/RpiFlaskServer/run.py
import sys
import Adafruit_DHT
import time
import RPi.GPIO as GPIO
from flask import Flask, render_template
app = Flask(__name__)
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
ledRed = 32
ledbl = 36
# Define led pins as output
GPIO.setup(ledRed, GPIO.OUT)
GPIO.setup(ledbl, GPIO.OUT)
# Keep LEDs off in the beginning
GPIO.output(ledRed, GPIO.LOW)
GPIO.output(ledbl, GPIO.LOW)
@app.route("/")
def index():
# Check the current status of lights in the room
ledRedSts = GPIO.input(ledRed)
ledblSts = GPIO.input(ledbl)
# Check the humidity and temperature
humidity, temperature = Adafruit_DHT.read_retry(11, 21)
templateData = {
'ledRed' : ledRedSts,
'ledbl' : ledblSts,
'humidity': humidity
'temperature' : temperature
}
return render_template('index.html', **templateData)
@app.route("/<deviceName>/<action>")
def action(deviceName, action):
if deviceName == 'ledRed':
actuator = ledRed
if deviceName == 'ledbl':
actuator = ledbl
if action == "on":
GPIO.output(actuator, GPIO.HIGH)
if action == "off":
GPIO.output(actuator, GPIO.LOW)
ledRedSts = GPIO.input(ledRed)
ledblSts = GPIO.input(ledbl)
templateData = {
'ledRed' : ledRedSts,
'ledbl' : leblSts,
'humidity': humidity
'temperature' : temperature
}
return render_template('index.html', **templateData)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True)
The code is pretty straightforward. The key points to be noted are listed below:
- We have to import additional libraries.
- As stated earlier we shall be using the BOARD numbering.
- In our default route function, we first check the status (high or low) of the lights in the room.
- We retrieve the temperature and humidity data using the in-built function of the Adafruit_DHT library. 11 is the sensor that we are using. A weird thing to note here is that 21 is the BCM number (GPIO.21) of the BOARD pin 40. We use this as the library uses the BCM numbering by default.
- Store the status and the sensor values in a dictionary called templateData.
- We pass this dictionary as a kwarg (note the double asterisk). The kwarg allows us to pass keyworded variable length arguments.
- The if statement, in the end, allows us to run our application as a module.
- To run our application all we have to do is navigate to the RpiFlaskServer directory type:
python run.py
HTML Template
Now let us look at our HTML template file, index.html:
<!-- /home/pi/Documents/RpiFlaskServer/templates/index.html -->
<!DOCTYPE html>
<head>
<title>My Home</title>
<link rel="stylesheet" href='../static/style.css'/>
</head>
<body>
<h1 align=center>Home Control</h1>
<h2> Room Temperature Monitor </h2>
<h3> Temperature : {{ temperature }} C</h3>
<h3> Humidity : {{ humidity }} %</h3>
<br>
<h2> Room Light Control </h2>
<h3> RED LED --- {{ ledRed }} ---
{% if ledRed == 1 %}
<a href="/ledRed/off"class="button">TURN OFF</a>
{% else %}
<a href="/ledRed/on" class="button">TURN ON</a>
{% endif %}
</h3>
<h3> BLUE LED --- {{ ledbl }} ---
{% if ledbl == 1 %}
<a href="/ledbl/off"class="button">TURN OFF</a>
{% else %}
<a href="/ledbl/on" class="button">TURN ON</a>
{% endif %}
</h3>
</body>
</html>
The template file is also pretty easy to understand:
- The temperature and humidity variables enclosed in double curly braces are passed to run.py where they get their value from the dictionary templateData.
- The full potential of Jinja templates can be seen in the if statements here.
- To make our application use a toggle switch, we use the status of the LEDs from templateData. If the status is 1 (LED On) we display the TURN OFF button and vice versa. The link passed in the href attribute is what the application app.py sees as <devicename> and <action>. Through these arguments we know which LED to turn on/off.
- To simply view the updated temperature and humidity data, keep refreshing the page.
Static CSS File
Now we have our application script and the template ready. The final bit is the css file, style.css:
/* /home/pi/Documents/RpiFlaskServer/static/style.css */
body {
background: black;
color: yellow;
}
.button {
font: bold 20px Arial;
text-decoration: none;
background-color: #E74C3C;
color: #ECF0F1;
padding: 3px 5px 3px 5px;
border-top: 1px solid #FDFEFE;
border-right: 1px solid #FDFEFE;
border-bottom: 1px solid #FDFEFE;
border-left: 1px solid #FDFEFE;
}
Just copy the above code to the style.css file. If you know HTML and CSS, you can play around with the fonts and colors. I have gone for a high contrast look in my code.
Let us look at the final application folder structure:
/Documents/RpiFlaskServer
run.py
templates
- index.html
static
- style.css
As mentioned before, to run our application, go to /home/pi//Documents/RpiFlaskServer in a terminal and type:
python run.py
Our home automation system is up and running. Any computer/device connected to the same network as the Raspberry Pi can access this system. Just open a browser and type the IP address (wlan0) of your Raspberry Pi followed by a colon (:) and the port number (5000 in this project). Press Enter and you will see the final web page of the home automation system as shown above.
Video Demonstration
Future Scope
This simple project can be scaled up easily by using relays and actual lamps. We can use it at home where all family members connected to the same network can access it. The potential of Flask is immense. To prevent guests in your home network from accessing this system, we can create a login page using Flask and SQLAlchemy database. Only authorized users can use the home automation system. By connecting a camera module to the Pi, we can pull up a live video feed. Like this, many sensors can be connected to the Raspberry Pi to monitor various parameters and we can view their values on the web page.
Hopefully, this tutorial inspires you to unleash the power of your creativity and imagination to build more advanced systems.