 
 
    original in de Stefan Blechschmidt
de to en Jürgen Pohl
Being a trained electrician, I found myself in 1990 in front of a CAD workstation to develop a switch and control station. Obviously, I got infected by a then unknown 'virus', and that's just fine.
In the November 2003 edition Temperature Monitoring With Linux I explained a circuit which enables us to collect temperature data through Linux. To evaluate the temperature data we should store them in a database.
To get the full benefit of this article we will graphically display the data through a web interface.

Some working applications should already be installed on your computer
As we are noticing, this article is for the somewhat advanced Linux user. For those which are not there yet it will be a good introduction ;-)
In MySQL the program mysql provides the interface to
    the database. With the command 
    mysql -u root -p mysql we connect to the MySQL
    monitor.
With the switch -u the
    user will be entered. The 
    -u switch will request the password, and finally the
    database to be used needs to be entered. In our case we are
    selecting the MySQL database Manager.
 You will get the mysql
    > prompt to enter the SQL commands. At first we we
    need to find out which kind of tables are in the database. The 
    command show tables;
    does this.
mysql> show tables; +-----------------+ | Tables_in_mysql | +-----------------+ | columns_priv | | db | | func | | host | | tables_priv | | user | +-----------------+ 6 rows in set (0.00 sec)
Now we have to build the database for our temperature data.
    With the command create database
    digidb we generate our database named digidb and
    with the command exit we
    may exit the monitor since additional commands will be entered
    in a different way.
MySQL has an administrator which in general is also
    named root. The default installation does not require a
    password. With the command 
    mysqladmin -u root -p password geheim we are changing
    the password for the user  root to geheim.
To make this modification active, the table of the
    administrator has to be read again, we are doing that with the
    command mysqladmin -u root -p
    flush-privileges. From now on the user root has
    to provide the password for each access to the database.
Entering commands through the monitor is very complicated, however MySQL offers another possibility to enter commands.
To do this we are entering a text file with the SQL commands by adding a "<" to the command mysql.
To demonstrate this, we are writing a text file to generate the first table for sensor 0.
In this file sensor0.sql we are now writing the commands to build the table, that might look like this.
CREATE TABLE sensor0 ( id int(11) NOT NULL auto_increment, monat char(3) NOT NULL default '', tag char(2) NOT NULL default '', dbtime timestamp(14) NOT NULL, zeit time NOT NULL default '00:00:00', messung decimal(4,2) NOT NULL default '0.00', PRIMARY KEY (id) ) TYPE=MyISAM;
This will be entered with:
     mysql -u digitemp -p digitemp
    < sensor0.sql
Since we are using 2 sensors we need only to copy the file
    and modify the line CREATE TABLE
    sensor0 to  CREATE TABLE
    sensor1.
At this point it may be convincing that entering the SQL commands by the means of a file has real advantages.
To show the newly generated tables we are using the command:
    echo 'show tables' | mysql -u
    root -p digidb, of course it also works the other way
    around.
If we did everything correctly we will get the output:
Enter password: Tables_in_digidb sensor0 sensor1
A small Perl program will do the transfer of data into the database. For this our first Perl module (DBI) will be utilized, it will provide us with methods of database access.
#!/usr/bin/perl -w
#
# Digitemp preparing of  log file and saving in database
# sbs 2003-08-09
#
use DBI;
use strict;
# Initialize database
my $datasource = "dbi:mysql:database=digidb";
my $user = "root";
my $pass = "geheim";
my $db = DBI->connect($datasource, $user, $pass)
   or  "Verbindung zur Datenbank nicht möglich: " . $DBI::errstr;
# Filtering of Digitemp
while(<STDIN>) {
  chomp;
  # Skip output program name 
  next if (m/Digi.*/);
  # Skip output blank line
  next if (m/^$/);
  # Skip all to Fahrenheit
  m/(.*).F.*/;
  my $templine = $1;
  # Divide temp line and save in variables
  my ($monat, $tag, $zeit, $sensor_txt, $sensor_nr, $grad_txt, $grad_wert)
  = split(/ /,$tempzeile);
  # Fill database
  $db->do( "insert into sensor$sensor_nr (monat, tag, zeit, messung)
  values ('$monat', '$tag', '$zeit','$grad_wert')")
    or die "do nicht möglich:  " . $db->errstr();
}# END- Digitemp filter
# close database
$db->disconnect;
    The program does actually not do very much, it opens the database, reads the output it received from digitemp, filters everything we do not need and writes the relevant data into the correct database table.
The continuous collection of data is done with the well proven cron job:
0-59/15 * * * * root /root/bin/digitemp -a | /root/bin/digipipe.pl
That's all for the data collection, now to the web interface.
Perl offers us the proper environment for this task.
First we need to know the directory where Apache is
    processing its CGI programs. They can be found in the
    configurations file of Apache. Look for an entry like this
    <Directory
    /usr/lib/cgi-bin>.
Before we begin with the graphical output we will first build a program which provides us with the last messurement data.
It would be advantageous if you store those in a separate
    subdirectory; you also have to make your program 
    executeable: chmod 755 
    programmname.
We need to limit the output to the last data and to entering them into a Perl-CGI program. This will be done with the SQL query.
#!/usr/bin/perl
use DBI;
use strict;
# Initialize database
my $datasource = "dbi:mysql:database=digidb";
my $user = "root";
my $pass = "geheim";
my $db = DBI->connect($datasource, $user, $pass)
   or  "Verbindung zur Datenbank nicht möglich: " . $DBI::errstr;
# database work parameter
my $sql;
my $sth;
# Sensor work parameter
my $temp;
my $zeit;
#Prepare HTML output 
print "Content-type: text/html\n\n";
# Output of individual sensors measurements
  $sql = "select messung, zeit from sensor$i order by id desc limit 1;";
  $sth = $db->prepare($sql)
    or die "prepare nicht möglich";
  $sth->execute()
    or die "execute nicht möglich";
  ($temp, $zeit) = $sth->fetchrow_array();
  $sth->finish();
  print "<p>Temperatur Sensor$i: <b>[$temp]</b> $zeit</p>";
}
# Close database
$db->disconnect;
    This example is not the most elegant, it shall only demonstrate how simple this job can be accomplished with Perl.
Now let's tackle the graphic output. The program (download at the end of the article) generates curve graphics, for more graphics look at the other GD moduls.
What is more, the program is using the CGI modul which enables HTML output with Perl. I am refering here to the numerous descriptions on this in the Internet.
Back to the program. It comprises a main part and two subprograms. One subprogram is responsible for the SQL query, the second is for the graphics.
Only three queries are carried out by the main part and the data are pased on to the subprograms.
Only the queries need to be changed to generate different graphical output.
Finally, I want to show you some SQL queries since they are the main subject of this example.
    select tag, monat, zeit,
     DATE_FORMAT(dbtime,'%Y-%c-%d %H:%i:%s') as dbtime, messung
       from sensor0
       order by id desc
         limit 5;
    
    select tag, monat, zeit,
     DATE_FORMAT(dbtime,'%Y-%c-%d %H:%i:%s') as dbtime, messung
       from sensor1
       where YEAR(dbtime) = YEAR(NOW())
         order by messung asc
         limit 1
    
    select tag, monat, zeit,
     DATE_FORMAT(dbtime,'%Y-%c-%d %H:%i:%s') as dbtime, messung
       from sensor1
       where YEAR(dbtime) = YEAR(NOW())
         order by messung desc
         limit 1
    
   select day, month, YEAR(dbtime) as Jahr,
     sum(messung)/count(*) as Durchschnitt
        from sensor1
       where YEAR(dbtime) = YEAR(NOW())
       and DAYOFMONTH(dbtime)= DAYOFMONTH(NOW())
       and MONTHNAME(dbtime) = MONTHNAME(NOW())
         group by DAYOFMONTH(dbtime)
    I am always surprised how simple it is to write programs in Perl. Actually, they are not really written but copied and the sections combined; somehow all that is already existing somewhere in one form or another.
I hope, I was able to provide you with a small glimpse into the topics of Perl, CGI and MySQL.