Python WebServer With Flask and Raspberry Pi

Let’s create a simple WebServer to control things in your home.

Marcelo Rovai
MJRoBot.org
12 min readJun 15, 2018

--

There are a lot of ways to do that. For example, on my tutorial at Hackster, IoT — Controlling a Raspberry Pi Robot Over Internet With HTML and Shell Scripts Only, we have explored how to control a robot over the local network using the LIGHTTPD WebServer. For this project here, we will use FLASK, a very simple and free microframework for Python. With Flask, will be very simple to control Raspberry GPIOs over the internet.

After you read this tutorial, please give a visit to its continuation: From Data to Graph: a Web Jorney With Flask and SQLite

1. Introduction

Flask is called a micro framework because it does not require particular tools or libraries. It has no database abstraction layer, form validation, or any other components where pre-existing third-party libraries provide common functions. However, Flask supports extensions that can add application features as if they were implemented in Flask itself.

On this tutorial, we will use a Raspberry Pi as a local Web Server, where we will control via a simple webpage, 3 of its GPIOs programmed as outputs (acting as actuators) and monitor 2 of its GPIOs, programmed as inputs (sensors).

The above block diagram shows what we want to accomplish

and the video below can give a hint about it:

2. Installing FLASK and Setting Your RPi WebServer

Flask Installation

The first thing to do is to install Flask on your Raspberry Pi. Go to Terminal and enter:

The best when you start a new project is to create a folder where to have your files organized. For example:

The above command will create a folder named “Server”. There we will save our python files (application):

On this folder, let’s create 2 other sub-folders: static for CSS and eventually JavaScript files and templates for HTML files (or more precisely, Jinja2 templates. But do not worry about that). Go to your newer created folder:

And create the 2 new sub-folders:

and

The final folder “tree”, will look like:

The Python WebServer Application

Now, let’s create our first python WebServer with Flask:

  • Open your Python3 IDE, Thonny or Geany.
  • Copy the “Hello Word” code below on your IDE and save it for example, as helloWorld.py

What the above code does is:

1. Load the Flask module into your Python script:

2. Create a Flask object called app:

3. Run the index() function when someone accesses the root URL (‘/’) of the server. In this case, only send the text “Hello World!” to the client’s web browser thru “return”

4. Once this script is running from the command line at the terminal, the server starts to “listen” on port 80, reporting any errors:

Raspberry PI IP Address:

If you are not sure about your RPi IP address, run on your terminal:

At wlan0: section you will find it. In my case:

Running the Application

Now, run the above application program:

On the first picture above you can see what will appear on your terminal. The application will be running unless you type [CTRL] + [C].

Now you must open any web browser that is connected to same wifi network as your Raspberry and type its IP address as shown in the second picture above. The “Hello World” should appear in your browser as shown in the picture above.

Note that there are 2 lines at bottom of the above picture. The lines show that the two different web browsers requested the root URL and our server returned HTTP status code 200 for “OK”. I entered with our RPi Server address on both, the RPI itself (10.1.0.27) and on my Mac (10.1.0.10). For each new request, a new line will appear on the terminal as far the application is running.

3. Creating a Proper Server Web Page

Let’s sophisticated our “Hello World” application, creating an HTML template and a CSS file for styling our page. This is, in fact, important, otherwise, you would complicate the Python Script putting all on it.

Templates

Creating an HTML file that will be located in the “template” sub-folder, we can use separate files with placeholders for spots where you want dynamic data to be inserted.

So, we will create a file named index.html, that will be saved on /templates. You can use any Text editor to create your HTML file. Can be Geany, “nano” at Terminal or the RPi Text Editor (LeafPad) that is located under “Accessories” Main Menu.

GEANY can be used to work with all project files at same time (.py; .html and .css) it’s a good option with bigger and more complex projects

OK, let’s create /templates/index.html:

Observe that anything in double curly braces within the HTML template is interpreted as a variable that would be passed to it from the Python script via the render_template function.

Now, let’s create a new Python script. We will name it helloWorldTemplate.py:

Note that we create a formatted string("timeString") using the date and time from the "now" object, that has the current time stored on it.

Next important thing on the above code, is that we created a dictionary of variables (a set of keys, such as the title that is associated with values, such as HELLO!) to pass into the template. On “return”, we will return the index.htmltemplate to the web browser using the variables in the templateData dictionary.

Execute the Python script:

Open any web browser and enter with your RPi IP address. The above picture shows the result.

Note that the page’s content changes dinamicly any time that you refresh it with the actual variable data passed by Python script. In our case, “title” is a fixed value, but “time” change it every second.

Now let’s include some styling on our page, creating a CSS file and stored it on /static/style.css:

You must also modify the index.html file to inform it to look for the style.css file. You do this inserting the “link” at “head”:

Remember that index.html is “under” /template and style.css is “under” /static, so, note that you must tell the HTML to go “up” and “down” again to look for the static subfolder: ../static/style.css.

The picture below shows the webpage with the new style!

For a more detailed Flask overview with Raspberry Pi, visit the Raspberry Pi Organization project : python-web-server-with-flask.

4. The Hardware

The hardware is very simple. Only follow the above electrical connections.

5. Reading GPIO Status

Let’s now read the status of our “sensors”, by monitoring their GPIOs.

The Python script

Let’s create a new Python script and named it app.py:

Look that what we are doing is only defining GIPOs 20 and 16 as input, reading its values and storing them on 2 variables: buttonSts and senPIRSts. inside the function index(), we will pass those values to our web page thru “button” ad “senPIR” variables that are part of our variable dictionary: templateData.

Once you create app.py, run it on your terminal:

The template

Let’s also create a new index.html to show the GPIO status of both sensors:

Do not forget to refresh the page to see the results.

Press the button or make a movement in front of PIR sensor and refresh the page.

The picture shows the webpage.

6. Controlling GPIOs

Now that we know how to “read” GPIO Status, let’s change them. What we will do will “command” via webpage the “actuators”. We have 3 LEDs connected to Raspberry GPIOs. Commanding them remotely we will change their status from LOW to HIGH and vice-versa. Instead of LEDs, we could have relays controlling your room lamp and/or fan for example.

The python script

Let’s create a new Python script and named it app.py:

What we have new on above code is the new “route”:

From the webpage, calls will be generated with the format:

or

For the above example, ledRed is the “deviceName” and on or off are examples of possible “action”.

Those routes will be identified and properly “worked”. The main steps are:

  • Convert the string “ledRED”, for example, on its equivalent GPIO pin. The integer variable ledRed is equivalent to GPIO13. We will store this value on variable “actuator”
  • For each actuator, we will analyze the “action”, or “command” and act properly. If “action = on” for example, we must use the command: GPIO.output(actuator, GPIO.HIGH)
  • Update the status of each actuator
  • Update the variable library
  • Return the data to index.html

The template

Let’s now create an index.html to show the GPIO status of each actuator and more important, create “buttons” to send the commands:

Only to give a better “fell”, I create a class “button”. You can only keep the normal link if you want.

Below the style.css file:

The picture shows the website for controlling our actuators.

7. Integrating Sensors and Actuators

Now, we must put together the 2 parts that we developed before. The final Python script is shown below:

And the final index.html:

The picture shows the final webpage.

8. Going Further With Templates

As we discussed briefly before, the render_template() function invokes the Jinja2 template engine that comes bundled with the Flask framework. Jinja2 substitutes {{ … }} blocks with the corresponding values, given by the arguments provided in the render_template() call.

But this is substitution is not only what Jinja2 can do. For example, templates also support control statements, given inside {% … %} blocks. We can change our index.html template in order to add conditional statements to deploy a specific button depending on actuator real value. In other words, “toggle” the actuator condition. Let’s rewrite the status and command part of index.html, using conditional statement :

The picture below shows the result:

This is only a small taste of what can be done with Python and Flask. If you really want to go deeper with Flask, you can follow the great tutorial from Miguel Grimberg: The Flask Mega Tutorial,

9. Conclusion

As always, I hope this project can help others find their way into the exciting world of electronics!

For details and final code, please visit my GitHub depository: RPi-Flask-WebServer

And to learn how to work with data, graphics, and databases, you can also see my tutorial: From Data to Graph. a Web Jorney With Flask and SQLite

For more projects, please visit my blog: MJRoBot.org

Saludos from the south of the world!

See you at my next tutorial!

Thank you,

Marcelo

--

--

Marcelo Rovai
MJRoBot.org

Engineer, MBA, Master in Data Science. Passionate to share knowledge about Data Science and Electronics with focus on Physical Computing, IoT and Robotics.