In this week assignment I will try to configure a local webserver on a Raspberry Pi in order to display the data acquired by my final project’s sensors. I don’t have much idea about how to do this, but through the help of the Raspberry Pi’s documentation and some documentation review online, I got some insights on the process. In the Raspberry Pi’s docs, one of the ways to do this is via the Apache Web Server, which is the way I will be using.
Configure the Server
So now, that we got some information about what we are doing, let’s set up the Raspberry Pi to host the server via Apache. In order to install Apache:
For us to find the Raspberry Pi’s address from a computer in the same network, we can run this command in the terminal (seen in the previous assignment):
Apache will then be hosting a test HTML in the web folder. If we navigate to the Pi’s IP address in whichever browser we like we should see something like this:
Enable CGI (Common Gateway Interface)
In order to run external content-generating programs, CGI programs / scripts define a way for the web server to do so. It is a simple way to put dynamic content on a web site, using whatever programming language we want, for example Python, Perl… I will be using Python in order to interact with the sensors’ I2C protocol of my installation and then try to create a dynamic plot with this data.
The way Apache looks for the CGI content is through the 000-default.conf file located under /etc/apache2/sites-enabled:
A bit more into detail, we need to:
Set up a ScriptAlias which will look into /usr/lib/cgi-bin/ for Scripts defined. This is done through the command below in the .conf file:
Configure the <Directory "/usr/lib/cgi-bin">... </Directory> to run CGI, allowing everyone to do so and to allow python scripts to run:
There is a particularity for Apache 2.4.7 that is mentioned in this website, which concerns the permissions to run the code.
Altogether, the .conf file looks like:
With this file, we should be able to place Python scripts in the /usr/lib/cgi-bin and be able to see them from another computer in the same network.
Finally, in order to allow CGI, we need to do:
And then restart apache:
Test Python Script
In the Directory of our choice (the same as above), we should now set up a Python Script with some particularities. First, a shebang marker needs to be put at the beginning of the file for it to be executed by Python:
Note: In order to find where python is installed in the Raspberry Pi:
Next, we need to tell the contents of the file are going to be set as HTML. This won’t be shown in the actual website, but are needed for the CGI to undertand what we are printing:
With this, and with some additions to print something (in HTML mode), my test file looks like:
Finally, the Python file needs to be set as an executable and we need to check it’s able to print stuff in HTML:
It also helps to have a look a the error.log from Apache:
Creating plots
Using Matplotlib
In order to create a basic plot, I first set up a python script using matplotlib, which is a broadly used library for generating plots. The set-up however, changed a bit, by following this tutorial.
Create a python script that outputs a matplotlib graph as a png
Embed that as an image in the html code of our page
The python script could look like this:
And the HTML (calling the python application that outputs the image):
This generates the following site (accesible via: $PI_ADDRESS/cgi-bin):
Which is okayish! A nice success, but not a very nice graph.
Using Interactive content
I decided then to explore further options with some other plotting libraries. One of the most interesting ones I found is called plot.ly. It is an open source service, which can simply provide with plotting tools offline, or for a very reasonable price (only 9,000$… meh!) provide support and data hosting. Of course I didn’t pay that much, but I dig into their API in order to see what they can do as Live Streamming of data:
Ups! Not discouraged by this, I went further into the exploration of the other API called dash. This again, can be paid at a similar price, or one could try to explore it’s on way into it. To get started, I pressed on the get started button and began with the installation process (all on the Pi):
I then followed the simple tutorial below that (which I won’t detail here because it’s on the site), plotting a set of numpy vectors in a bar chart, in order to understand how they generate the content on the site. Basicly, to remember is that (I have no relationship with Dash or Plotly, but the plots are nice):
The application is written in Python and can import python libraries such as pandas, numpy or any other we like
Dash provides with two main components: HTMLand Core components: HTML created html-elements and the core creates higher level object such as graphs, dropdowns, buttons and so on, based on javascript and react.js.
It supports Markdown as part of the core components content generation and it does it through the same way it does the graphs and other higher level components
Now, it’s time to get the hands on the plot!
Plotting actual data
For the shake of clarity, let’s try to make a sketch of what the plotting / sensor acquisition will look like. I based this on this site and built on top of it the rest of items I have related above:
The Pi will be reading via I2C a pressure sensor I used on the Input devices week, using a python code to output the data via print, with a timestamp
A crontab job will be running this script and redirecting it to a log.dat file (more on this below)
The apache server will use a python application via mod_wsgi (more on this below) to read the log.dat file and plot it using Dash
The Python-I2C code
This code can be wherever we want it to be. I have it in a personal folder on the Pi and looks like this (with a shebang! at the beginning):
We have to change the script settings for it to be executable:
And the, when running this script, we should get something like:
The crontab job
This is a way to create a scheduled job in linux, by setting a shell command with a certain timing that we define and we write in a certain format in a text file. The line definition looks like:
Where each star means:
m: interval in minutes
h: interval in hours
dow: day of the week
mon: month
dom: day of the month
And in order to execute it:
Which opens up a file (edited with nano text editor):
My line there means: every minute (minimum timing), run the sensorRead.py and redirect it’s standart output to a .dat file in the same directory.
This log.dat file, after a while, will look like:
The apache server
Here, we will be using a different mode of operating the python code. Instead of using CGI, as above, I will be using Flask mod_wsgi, in order to interact with the python application. WSGI sets an specification of a generic API for mapping between an underlying web server and a Python web application. This sets up a more compatible way of using the python packages and the dash application mentioned above. In this site, it is explained how to create as similar concept as the ScriptAlias in CGI, but with some internal WSGI particularities. I detail below the result of my research and the result on the apache conf file:
To highlight from there:
We need to create a DaemonProcess to put an eye on the application (in my case plotApp)
The ScriptAlias are now called WSGIScriptAlias. If we want the alias to be executed in the root directory of the server, we can just put / in the first part of the alias
We need a * .wsgi file that I will detail below, interacting with the actual python application
The permissions are granted as in the CGI ScriptAlias for apache 2.4.7
Now, this mod_wsgi configuration will be interfacing with the python code via a * .wsgi file that we have declared. This file is indeed a python file that in my case looks like this (inherited from Dash forum):
Which basicly is looking for the real-python application that will be plotting the data read from the log.dat file above and is setting it as an application in the mod_wsgi framework. This application needs to be called as such, and cannot be changed. Note that we need to create this file as an executable:
The dash application
Finally, the fun part! After all this set up, we get to plot some of the data with dash. For this, we create a python code in the folder we specified in the .wsgi above that reads the data and creates the plots.
In order to read the data, I will be using pandas and numpy. For now, I did not manage to install pandas via pip on the Pi, but it’ll be a matter of time and I’ll stick to numpy for the moment (although I won’t be able to import the strings from the datestamp of the log.dat file):
For the data plotting, using dash and some of the examples from this site as a reference, the basic chart looks like this:
In order to add some text, I added some Markdown:
And formatted it with generic styles:
Finally, in order to make it refresh, I followed this site in order to create a callback based on a timer (from dash API itself):
This calls every 1000ms the app callback, which uses as input the n_intervals:
Summing up, the whole application, with some changes, sets up a callback every 1000ms, reads the log.dat data and updates the plot. Additionally it puts some nice css’ed text based on Markdown:
And the plot, finally, after all this boring stuff looks like:
As a bonus, for those who like old-styled-times-new-roman:
Note on live updates
I notices that this method updates the whole graph, and provokes the interactivity to be reset every second, not allowing to zoom in or pan, among others. The callback above can be better changed into: