This summer we had a new Perl internship and a part of it consisted of building an environment monitoring system using Raspberry Pi. In this article I’ll walk you through one of the solutions that you can follow to build something similar.
Before getting ahead of myself I have to mention that, during the first week, the interns learned Perl basics, syntax, OOP, regex, they were introduced to Mojolicious, DBI and DBIx, through theory and practice, by doing various exercises. They also worked on an implementation of the “game of life”, a non-recursive and recursive version with pair programming of the Fibonacci sequence, and a Mojolicious app as well.
The second week was all about building the environmental monitoring system, meant to gauge the temperature, humidity, CO2 levels and other environmental factors in a room, using a Raspberry Pi microcontroller.
Now let’s take it step by step.
*
General requirements:
Building a system that monitors the temperature, humidity, CO2 levels and other environmental factors in a given room, using sensors connected to a Raspberry Pi microcontroller. For each room there will be a different microcontroller.
The system has to allow:
- Adding a new microcontroller from the interface to the database, with its own capabilities for a given room
- Viewing all the existent microcontrollers with their status (online or not)
- Monitoring the temperature and humidity in a given room in the interface through an instant request
- Monitoring the average temperature and humidity in a given room in a single day or a given time frame of that day
- Storing the temperature and humidity data in the database for each room
- Routine deletion of data older than one week from the database
- Creating diagrams to have a comparison view of the temperature and humidity in several rooms in a day or a specific time frame of that day
Software:
Framework: Catalyst
ORM: DBIx
Other: Cron jobs
Modules: RPi::PIGPIO::Device::DHT22 – metacpan module used to read temperature and humidity from a DHT22 sensor created by one of our senior developers, Horea Gligan.
Raspberry Pi uses a Raspbian Stretch operating system.
Aside from these technology requirements, there are no restrictions. You can use whatever you think fits. The interface especially is a matter of complete freedom regarding specifications. As such, some of the interns went with a basic bootstrap while others went with something more complex.
Hardware:
We have a Raspberry Pi 3 with a quad-core CPU and a gigabyte of RAM.
The architecture is quite simple: the user requests data from the server and the server requests data from the database and from the microcontrollers. A cron job transmits data from the microcontrollers to the database every 10 minutes.
.
System structure
There are 4 controllers:
- Statistic controller takes care of calculating and displaying average temperatures and humidity and selecting the values to be displayed in the chart sections.
- House controller is responsible for creating and selecting houses in the database.
- Room controller deals with creating and selecting rooms from database (either for a particular house or all).
- Microcontroller manages to create a microcontroller, select microcontrollers in a home, and display temperature and humidity for a room in real time.
.
Database
The database diagram is pretty basic: the House table stores data for each house, the Room table stores data for every room and is connected to the House table with a foreign key through a one to many relationship.
The Micro table stores data for every controller and is connected to the Room, Sensors and Statistic tables using foreign keys, a relationship of one to one for the Sensors and Statistic table and a relationship of one to many for the Room table.
The Sensors table stores data for every sensor and is connected to the Micro table through a relationship of one to one. The Statistic table stores data for each string of data registered by a cron job and is connected to the Micro table through a relationship of one to many.
.
Application interface
The interface is an open topic, so everyone had the chance to build their own version of it. This is just one example. You can basically build any version that you like.
*
As this is a system built in Perl, here’s a snippet of code, written by one of the interns, that deals with the selection of data for chart display according to a switch in the front-end.
If the lever is ‘on’, selects data from a certain day at a certain hour. If the lever is ‘off’, it selects data on a certain day, all day. Depending on the lever, it selects the data in the back-end and sends it to the interface.
sub chart_send :Chained('base') :Path('chart_send') { my ($self, $c) =@_; my $lever = $c->request->params->{lever} || "off"; my $micro = $c->request->params->{micro} || "0"; my $day = $c->request->params->{day} || "0"; my $hour_param = $c->request->params->{hour} || "0"; my @database = $c->model("DB::Statistic")->search({microid => $micro})->all; my $msg = "Chart on an day!"; my $number = 0; my (@result_humidity , @result_temp, @labels); if ( $lever eq "on" ) { $msg = "Chart on an hour!"; @labels = qw(10 20 30 40 50 60); } else { @labels = (1 ..24); } foreach my $i (@database) { my ($sec2, $min2, $hour2, $mday2, $mon2, $year2, $wday2, $yday2, $isdst2) = localtime($i->timestamp); if ( $lever eq "on") { #day/hour if ( $mday2 == $day && $hour2 == $hour_param ) { if ( $i->sensor eq "Humidity" ) { push @result_humidity, $i->data; } else { push @result_temp, $i->data; } } } else { #days if ( $mday2 == $day ) { if ( $i->sensor eq "Humidity" ) { push @result_humidity , $i->data; } else { push @result_temp , $i->data; } } } } $c->stash( result_humidity => \@result_humidity, result_temp => \@result_temp, labels => \@labels, msg => $msg, template => 'statistic/chart_send.tt2' ); }
As an experiment it was a great learning event for our interns and also quite a fun project to work on, covering several aspects of development. After just a week of training, they managed to build a working application in a language they never worked in before.
Learn more about our Perl development services!
– by Samuel Andras