| 
 | 
|  | 
| 
 | 
| Dit document is beschikbaar in: English Castellano Deutsch Francais Nederlands Russian Turkce | 
| 
   door Stefan Blechschmidt <sb(at)sbsbavaria.de> Over de auteur: Doordat ik opgeleid ben als electriciën, zat ik in 1990 achter een CAD werkstation om een schakel en controlepost te ontwikkelen. Kennelijk ben ik toen besmet met een toen nog onbekend 'virus' en dat bevalt me prima. Vertaald naar het Nederlands door: Hendrik-Jan Heins <hjh/at/NOSPAM/dot/passys/dot/nl> Inhoud: 
 | 
| Temperatuurbewaking met Linux (Deel 2)  Kort: 
 In de November 2003 editie Temperatuurbewaking met Linux heb ik uitgelegd hoe een circuit werkte dat ons in staat stelde temperatuurinformatie via Linux te lezen. Om deze temperatuurinformatie te kunnen interpreteren, moeten we hem in een database bewaren. Om echt gebruik te kunnen maken van dit artikel, zullen we de gegevens via een webinterface grafisch weergeven. | 
Er moeten al enkele toepassingen werkend op je systeem aanwezig zijn
Let wel op, dit artikel is voor de wat verder gevorderde Linux gebruiker. Voor degenen die nog niet zover zijn, is dit een goede introductie in het lastiger werk ;-)
In MySQL is het programma mysql de interface naar de
    database. Met het commando 
    mysql -u root -p mysql leggen we verbinding met de MySQL
    bewaking.
Met de parameter -u kan de
    gebruiker worden opgegeven. De parameter 
    -u zal een wachtwoord vragen en daarna kan de database die gebruikt
    gaat worden, geopend worden. In ons geval kiezen we de MySQL database
    Manager.
 Je krijgt de  mysql
    > prompt om de SQL commando's op te geven. Allereerst
    moeten we uitvinden welk soort tabellen er in de database staan.
    Het commanod show tables;
    doet exact dat.
mysql> show tables; +-----------------+ | Tables_in_mysql | +-----------------+ | columns_priv | | db | | func | | host | | tables_priv | | user | +-----------------+ 6 rows in set (0.00 sec)
Nu moeten we de database voor onze temperatuurgegevens aanmaken.
    Met het commanod create database
    digidb genereren we onze database genaamd digidb en
    met het commando exit kunnen we
    de bewaking sluiten, aangezien we de aanvullende commando's op een
    andere manier zullen opgeven.
MySQL heeft een beheerder die meestal ook root
    heet. De standaard installatie heeft geen wachtwoord nodig.
    Met het commando 
    mysqladmin -u root -p password geheim veranderen we het wachtwoord
    voor de gebruiker  root in geheim.
Om deze verandering te activeren, moet de tabel van de beheerder
    opnieuw worden ingelezen, we doen dat met het commando
    mysqladmin -u root -p
    flush-privileges. Van nu af aan moet de gebruiker root
    iedere keer als hij toegang tot de database wil krijgen een
    wachtwoord opgeven.
Het opgeven van commando's via de bewaking is vrij gecompliceerd, maar MySQL biedt een andere mogelijkheid om commando's op te geven.
Om dit voor elkaar te krijgen, openen we een tekstbestand met SQL commando's en voegen een "<" toe aan het commando mysql.
Om dit te demonstreren, schrijven we een tekstbestand dat de eerste tabel voor sensor 0 genereert.
In dit bestand sensor0.sql schrijven we nu de commando's om de tabel op te bouwen. Het zal er ongeveer zo uitzien:
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;
Dit wordt met:
     mysql -u digitemp -p digitemp
    < sensor0.sql ingegeven.
Aangezien we 2 sensoren gebruiken, hoeven we het bestand alleen maar
    te kopiëren en de regel CREATE TABLE
    sensor0 te veranderen in  CREATE TABLE
    sensor1.
Op dit punt ben je er waarschijnlijk wel van overtuigd dat het geven van SQL commando's via een bestand echte voordelen biedt.
Om de nieuw gegenereerde tabellen te bekijken, gebruiken we het commando:
    echo 'show tables' | mysql -u
    root -p digidb. Natuurlijk werkt dit ook andersom.
Als we alles goed hebben gedaan, krijgen we de volgende output:
Enter password: Tables_in_digidb sensor0 sensor1
Een klein Perl programma zal de gegevens overbrengen naar de database. Hiervoor wordt onze eerste Perl module (DBI) gebruikt, deze zal ons voorzien van een methode voor databasetoegang.
#!/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;
    Het programma doet eigenlijk niet heel erg veel, het opent de database, leest de output die het ontvangt van digitemp, filtert alles uit wat we niet nodig hebben en schrijft de relevante gegevens in de juiste database tabel.
Continue gegevensvergaring kan worden geregeld via een goed geplaatste cron taak:
0-59/15 * * * * root /root/bin/digitemp -a | /root/bin/digipipe.pl
Dat is alles voor de gegevensvergaring, nu de web interface.
Perl geeft ons de juiste omgeving voor deze taak.
Allereerst moeten we weten in welke map Apache CGI
    programma's uitvoert. Dit kan worden gevonden in de
    configuratiebestanden van apache. Zoek naar een regel als
    deze: <Directory
    /usr/lib/cgi-bin>.
Voordat we beginnen met de grafische output, bouwen we eerst een programma dat ons voorziet van de laatst gemeten gegevens.
Het zou een groot voordeel zijn als je die gegevens kon opslaan
    in een submap; je moet je programma ook uitvoerbaar maken:
    chmod 755 
    programmanaam.
We moeten de output beperken tot de laatste gegevens en ze in een Perl-CGI programma invoeren. Dit gebeurt via de 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;
    Dit voorbeeld is niet het meest elegante, maar het toont wel aan hoe eenvoudig deze taak kan worden uitgevoerd met Perl.
Laten we nu eens kijken naar de grafische output. Het programma (download onderaan dit artikel) genereert krommen. Kijk voor meer grafische programma's naar de andere GD modules.
Het programma gebruikt tevens de CGI module die HTML output genereert met Perl. Ik verwijs hiervoor naar de vele beschrijvingen hierover op Internet.
Terug naar het programma. Het bestaat uit een hoofdbestanddeel en twee sub-programma's. Een sub-programma is verantwoordelijk voor de SQL query, het tweede voor het grafische werk.
Er worden slechts drie queries door het hoofdbestanddeel uitgevoerd en de gegevens worden daarna geparsed naar de sub-programma's.
Alleen de queries hoeven te worden veranderd om een andere grafische output te genereren.
Tenslotte wil ik je enkele SQL queries laten zien, aangezien ze het belangrijkste onderwerp van dit voorbeeld zijn.
    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)
     
Ik ben altijd weer verrast hoe eenvoudig programma's te schrijven zijn in Perl. Eigenlijk schrijf je ook niet echt, maar je kopieert en combineert verschillende delen; op de een of andere manier bestaat ieder stukje al in de een of andere vorm.
Ik hoop dat ik je een kleine inkijk heb kunnen bieden in de onderwerpen Perl, CGI en MySQL.
| 
 | 
| Site onderhouden door het LinuxFocus editors team © Stefan Blechschmidt, FDL LinuxFocus.org | Vertaling info: 
 | 
2004-09-17, generated by lfparser version 2.36