Wouldn’t it be cool to create and run your own website on a Raspberry Pi? You could connect sensors to the Raspberry Pi and have the readings displayed on a webpage that you could access from any device with an internet connection.

In part one of this two part tutorial, we will see how to set up a simple web server on the Raspberry Pi that you can access across the internet. As an example, we will display the temperature and humidity readings from a DHT22 sensor on a web page so that users can view the readings from a different computer.

Components of the Internet

Install the Bottle Python Library

The Bottle framework is a simple, yet powerful Python micro-framework that is perfect for small web applications like the one we are going to build. It has no dependencies other than Python, and it works on most versions of Python.

Installing the Bottle server on your Raspberry Pi is quite easy. First, update the available packages on your Raspberry Pi by typing the following command: sudo apt update. Then, install the Bottle framework into a virtual environment by typing this command: pip install bottle.

Bottle Webserver “Hello World”

To run a webserver on your Raspberry Pi, you will need to connect the Raspberry Pi to your network. Here is what you need:

Connect all of the devices like this:

Local network

To build a basic web server, create a Python file and give it any name. I have called mine myServer.py. Then copy the code below into your file and hit Ctrl-X, Y, then press the Enter key to save and exit. Run the command: sudo python myServer.py.

from bottle import route, run

@route('/hello')
def hello():
    return "Hello there..."

run(host='192.168.8.39', port=80, debug=True, reloader=True)

Code Description

A web application cannot work without routes. To create a route, follow the following steps:

  1. First, import route and run from the bottle library: from bottle import route, run.
  2. Use the decorator @route followed by the actual location of the route. In this case, it’s going to be '/hello', but it can be anything you want to call it.
  3. Then, define a function that will be executed when the route is called: def hello():.
  4. Next, return "Hello there..." This function will simply return a text which says “Hello there…” in your web browser.
  5. Finally, tell the Python interpreter to run the built-in development server: run(host='137.158.131.117', port=8080, debug=True). Specify the host and the port (it can be the local host, or the IP address if you know it).

Next, open your preferred browser, then enter the IP address, port number, and route name as shown below and you will see “Hello there” in the browser. You can also try doing the same procedure on a different computer but make sure that it is on the same network with the Raspberry Pi.

Hello world from the web browser of a different computer

On the Raspberry Pi terminal, you will see status messages when users access your web page.

Raspberry Pi Terminal messages.

From this we can see that our server is up and running and three devices from the same network have successfully accessed our website.

These devices have the IP addresses 192.168.8.100, 192.168.8.102 and finally the localhost: 192.168.8.39.

The next step is to start the server in your terminal. You can do this by running this command from the Raspberry Pi terminal:

sudo python myServer.py

Now open your browser and type 192.168.8.39/hello. Note that if the website is running on a different port, you need to include it in the URL as follows: 192.168.8.39:80/hello.

Port Forwarding

At this point, our web page can only be accessed by computers that are on the same network as the Raspberry Pi. For external users to access our webserver from the internet, we will need to change a few settings on our router. One particular procedure that we can do is called Port Forwarding.

This is a procedure that allows computers on the internet to connect to a specific service within our private network. Basically, we are telling our router to forward any requests that come to port 80 and send the requests to the Raspberry Pi.

To do this, we need to log into the router’s configuration page by typing the router’s internal IP address in our browser. For my router, I am using the Huawei 4G B315 Router and its internal IP address is 192.168.8.1. This will take you to the configuration page.

Again, I am not going to discuss how to set up an account on your router. There are different brands of routers and they have different configuration page layouts but the end goal is the same. We need to tell the router where to forward any incoming requests. To access the port forwarding page on a similar router, here are the steps you need to follow:

How to Enable Port Forwarding

On the home page, click “Settings” then enter your username and password.

On the settings page:

  1. Click on “Virtual Server”
  2. Then click the “Add” button and fill in the entry fields.
  • Name – Rpi: Name of the computer
  • WAN Port – 80: port for web connections
  • LAN IP Address – 192.168.8.39 (Static IP address of the Raspberry Pi)
  • Protocol (TCP/UDP)
  • Status ON

3. Click “OK”
4. Finally, click “Apply”

Port Forwarding is now successfully configured for the Raspberry Pi.

Port forwarding configuration page

The router’s internal IP address is no longer necessary at this point. Instead, we will use its external IP address. If you do not know the external IP of your router, you can open the “Device Information” page, and check the WAN IP address. Now, when an external computer sends a request to this IP address with port 80, the router will know where to forward that request to.

Device information page to view the router’s external IP address

Example Project

The last task for this exercise is to display the date, time, temperature and humidity readings from a DHT22 on a web page that you can access from the internet.

We have already seen how to access a simple page from the web, so this task will only show you how to display the DHT22 readings on a webpage. I am not going to discuss how to interface the DHT22 sensor with the Raspberry Pi. If you are not familiar with that step, I highly recommend you to read this tutorial first.

These are the parts you will need:

Once you have the parts together, connect the Raspberry Pi and DHT22 sensor following this wiring diagram:

The HTML Code

We will use HTML to write the code for the webpage. Create a new file and name it main.tpl. Copy the following HTML code and paste it into the main.tpl file.

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Tempetature and Humidity</title>
    <link rel="stylesheet" type="text/css" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">
</head>
<body>
    <h1>Raspberry Pi DHT22 Webserver Demo</h1>
    <p>The values below show the date, time, temperature and humidity readings from a DHT22 sensor</p>
    <p><img src="/home/pi/webserver1/temp_humidity.jpg"></p>

    <br /><br />
    <h3> Temperature ==> {{tempVal}} <sup>o</sup>C</h3>
    <h3> Humidity    ==> {{humidVal}} %</h3>
    <hr>
    <h3> Last Sensor Reading: {{myTime}} <a
href="/"class="button">Refresh</a></h3>
    <hr>
</body>
</html>

The Python Code

Next, create a new Python file where you will define your webserver. I have called mine main.py. Copy the following code into it, save and exit, then run the command sudo python main.py in your terminal.

from bottle import route, run, static_file, template
import time
from datetime import datetime
import Adafruit_DHT

DHT_SENSOR = Adafruit_DHT.DHT22
DHT_PIN = 4

HOST = '192.168.8.39'

@route('/')
def serve_homepage():
    humidity,temperature = Adafruit_DHT.read_retry(DHT_SENSOR, DHT_PIN)
    humidity = '{0:0.1f}'.format(humidity)
    temperature = '{0:0.1f}'.format(temperature)
    time = datetime.today().strftime('%Y-%m-%d %H:%M:%S')
    myData = {
      'tempVal' : temperature,
      'humidVal' : humidity,
      'myTime' : time
     }
    return template('main.tpl', **myData)

run(host=HOST, port=80, debug=True, reloader=True)

How the Python Program Works

  • The route() decorator binds a piece of code to the route. In this case, we link the "/" path to the serve_homepage() function. This is called a route (hence the decorator name). Whenever a browser requests a URL, the associated function is called and the return value is sent back to the browser.
  • The run() call in the last line starts a built-in development server. It runs on host IP 192.168.8.39 port 80 and serves requests until the server is stopped from the terminal.
  • The template loads the HTML from a different file. If we have variables that we need to pass to the HTML, we use the following line to call the main.tpl file: return template('main.tpl', **myData).
  • def serve_homepage(): This is a function that will read the temperature, humidity, and time readings and pass the variables to the HTML file.
  • From this point, it is as easy as adding new @route-decorated functions to create new pages.

Accessing the Webpage

The webpage can be viewed from any web browser on any computer within your home network or on the global internet. Just open your preferred web browser and enter the IP address of the Raspberry Pi. If you are using a computer in the same network as the Raspberry Pi, use the local IP address (192.168.8.39 in my case). If you are using a computer that is on a different network, use the external address of the router (10.250.xxx.xx).

Timestamped temperature and humidity readings of a DHT22 sensor

Thanks for reading and be sure to leave a comment below if you have questions about anything! To continue this project, visit the next tutorial – How to Build a Raspberry Pi Web Server – Part 2.