1-wire Wetterstation (Teil 3: Anzeige)

Nachdem man sich eine 1-wire Wetterstation nach dem Artikel 1-wire Wetterstation (Teil 1: Installation) gebaut und die Daten wie im Artikel 1-wire Wetterstation (Teil 2: Datenbank) beschrieben in einer MySQL Tabelle speichert möchte man die gesammelten Werte natürlich auch angezeigt bekommen.

Um möglichst einfach die gemessenen Werte der Wetterstation in einer Webseite anzuzeigen, habe ich die jpgraph verwendet. Diese Software darf für private Zwecke kostenlos verwendet werden. Da sie ansonsten Geld kostet ist sie nicht im Repository zu finden. Man kann sie aber unter der URL http://jpgraph.net/download runterladen. Ich habe mir von dort die aktuelle Version 3.07 geholt und in das Verzeichnis /usr/share/jpgraph3 entpackt. Danach benötigt man noch das Paket php5-gd. Diese ist im Repository enthalten und kann mit dem folgenden Befehl installiert werden.

apt-get install php5-gd

Um aus den gesammelten Wetterdaten eine Grafik mit den Werten des letzten Tages erstellen zu lassen, habe ich das Verzeichnis /var/www/grafiken angelegt und das folgenden PHP-Programm geschrieben, welches die Grafiken aus erzeugt.

<?php
//****************************************************************************
//Darstellung von Temperatur und Feuchtigkeit der letzten 24 Stunden als Graph
//14.02.2011 Kristian Purrucker
//****************************************************************************
 
include ("/usr/share/jpgraph3/jpgraph.php");
include ("/usr/share/jpgraph3/jpgraph_line.php");
include ("/usr/share/jpgraph3/jpgraph_mgraph.php");
include ("/usr/share/jpgraph3/jpgraph_date.php");
 
$DatabaseHost = "localhost";
$DatabaseUser = "root";
$DatabasePassword = "asdfgh";
$Database = "wetterstation";
$Table = "daten_min";
 
$fileName = "/var/www/grafiken/graph_daily.png";
 
//Datenbankanbindung
//******************
$DatabasePointer = mysql_connect($DatabaseHost, $DatabaseUser, $DatabasePassword) or die ("Keine Verbindung moeglich");
mysql_select_db($Database, $DatabasePointer) or die ("Die Datenbank existiert nicht");
 
 
//Auslesen der letzten 1440 Zeilen (= Tag) aus der Datenbank
//**********************************************************
$ResultPointer = mysql_query("SELECT zeitstempel, temp_clara, humidity_clara, temp_simon, humidity_simon FROM $Table ORDER BY zeitstempel DESC LIMIT 1440");
 
$temp_clara_average = "";
$temp_simon_average = "";
$humidity_clara_average = "";
$humidity_simon_average = "";
 
for($i = 0, $Export = ""; $i < mysql_num_rows($ResultPointer); $i++)
{
   $Daten = mysql_fetch_object($ResultPointer);
 
   $temp_clara[] = $Daten->temp_clara;
   $temp_clara_average = $temp_clara_average + $Daten->temp_clara;
   $temp_simon[] = $Daten->temp_simon;
   $temp_simon_average = $temp_simon_average + $Daten->temp_simon;
   $humidity_clara[] = $Daten->humidity_clara;
   $humidity_clara_average = $humidity_clara_average + $Daten->humidity_clara;
   $humidity_simon[] = $Daten->humidity_simon;
   $humidity_simon_average = $humidity_simon_average + $Daten->humidity_simon;
   $xdata[] = $Daten->zeitstempel;
}
 
$temp_clara_average = round(($temp_clara_average = $temp_clara_average / 1440), 4);
$humidity_clara_average = round(($humidity_clara_average = $humidity_clara_average / 1440), 4);
$temp_simon_average = round(($temp_simon_average = $temp_simon_average / 1440), 4);
$humidity_simon_average = round(($humidity_simon_average = $humidity_simon_average / 1440), 4);
 
 
//Funktion zur Konvertierung des TimeStamp in Minuten und Sekunden
//****************************************************************
function  TimeCallback( $aVal) {
    #return Date ('H:i:s d.m Y',$aVal);
    return Date ('H:i',$aVal);
}
 
 
//Erzeugung eines Graphen fuer Claras Zimmer
//******************************************
$graph = new Graph(700,200,"auto");
$graph->SetScale('datint',"auto","auto","auto","auto");
$graph->SetY2Scale('int',"auto","auto");
$lineplot_temp_clara=new LinePlot($temp_clara, $xdata);
$lineplot_humidity_clara=new LinePlot($humidity_clara, $xdata);
 
// Grafik Formatieren
$graph->img->SetMargin(50,50,20,60);
$graph->SetColor("#000000");
$graph->SetMarginColor("#333333");
$graph->SetShadow();
 
//Titel
$graph->title->Set("Claras Zimmer");
$graph->title->SetColor("#CCCCCC");
$graph->title->SetFont(FF_FONT2,FS_BOLD);
$graph->subtitle->Set("Aktuell: $temp_clara[0] C / $humidity_clara[0]%   Durchschnittlich: $temp_clara_average C / $humidity_clara_average%");
$graph->subtitle->SetColor("#CCCCCC");
 
//Legende
$graph->legend->Pos(0.50,0.95,"center","bottom");
$graph->legend->SetLayout(LEGEND_HOR);
$graph->legend->SetShadow(false);
$lineplot_temp_clara->SetLegend("Lufttemperatur (C) ");
$lineplot_humidity_clara->SetLegend("Luftfeuchtigkeit ");
 
//X-Achse
$graph->xaxis->SetColor("#CCCCCC");
$graph->xaxis->title->Set("Zeit");
$graph->xaxis->SetLabelFormatCallback('TimeCallback');
$graph->xaxis->title->SetColor("#CCCCCC");
$graph->xaxis->title->SetFont(FF_FONT1,FS_BOLD);
 
//Y-Achse
$graph->yaxis->SetColor("#FF7777");
$graph->y2axis->SetColor("#1111ee");
$graph->yaxis->title->Set("Grad Celsius");
$graph->y2axis->title->Set("% Luftfeuchtigkeit");
$graph->yaxis->title->SetColor("#CCCCCC");
$graph->y2axis->title->SetColor("#CCCCCC");
$graph->yaxis->title->SetFont(FF_FONT1,FS_BOLD);
$graph->y2axis->title->SetFont(FF_FONT1,FS_BOLD);
 
//Linie 1
$lineplot_temp_clara->SetColor("#FF8888");
$lineplot_temp_clara->SetFillColor("#EE0000@0.6");
$lineplot_temp_clara->SetWeight(1);
 
//Linie 2
$lineplot_humidity_clara->SetColor("#8888ff");
$lineplot_humidity_clara->SetFillColor("#2222DD@0.6");
$lineplot_humidity_clara->SetWeight(1);
 
// Die Linien zu der Grafik hinzufügen
$graph->Add($lineplot_temp_clara);
$graph->AddY2($lineplot_humidity_clara);
 
//Erzeugung eines Graphen fuer Simons Zimmer
//******************************************
$graph2 = new Graph(700,200,"auto");
$graph2->SetScale('datint',"auto","auto","auto","auto");
$graph2->SetY2Scale('int',"auto","auto");
$lineplot_temp_simon=new LinePlot($temp_simon, $xdata);
$lineplot_humidity_simon=new LinePlot($humidity_simon, $xdata);
 
// Grafik Formatieren
$graph2->img->SetMargin(50,50,20,60);
$graph2->SetColor("#000000");
$graph2->SetMarginColor("#333333");
$graph2->SetShadow();
 
//Titel
$graph2->title->Set("Simons Zimmer");
$graph2->title->SetColor("#CCCCCC");
$graph2->title->SetFont(FF_FONT2,FS_BOLD);
$graph2->subtitle->Set("Aktuell: $temp_simon[0] C / $humidity_simon[0]%   Durchschnittlich: $temp_simon_average C / $humidity_simon_average%");
$graph2->subtitle->SetColor("#CCCCCC");
 
//Legende
$graph2->legend->Pos(0.50,0.95,"center","bottom");
$graph2->legend->SetLayout(LEGEND_HOR);
$graph2->legend->SetShadow(false);
$lineplot_temp_simon->SetLegend("Lufttemperatur (C) ");
$lineplot_humidity_simon->SetLegend("Luftfeuchtigkeit ");
 
//X-Achse
$graph2->xaxis->SetColor("#CCCCCC");
$graph2->xaxis->title->Set("Zeit");
$graph2->xaxis->SetLabelFormatCallback('TimeCallback');
$graph2->xaxis->title->SetColor("#CCCCCC");
$graph2->xaxis->title->SetFont(FF_FONT1,FS_BOLD);
 
//Y-Achse
$graph2->yaxis->SetColor("#FF7777");
$graph2->y2axis->SetColor("#1111ee");
$graph2->yaxis->title->Set("Grad Celsius");
$graph2->y2axis->title->Set("% Luftfeuchtigkeit");
$graph2->yaxis->title->SetColor("#CCCCCC");
$graph2->y2axis->title->SetColor("#CCCCCC");
$graph2->yaxis->title->SetFont(FF_FONT1,FS_BOLD);
$graph2->y2axis->title->SetFont(FF_FONT1,FS_BOLD);
 
//Linie 1
$lineplot_temp_simon->SetColor("#FF8888");
$lineplot_temp_simon->SetFillColor("#EE0000@0.6");
$lineplot_temp_simon->SetWeight(1);
 
//Linie 2
$lineplot_humidity_simon->SetColor("#8888ff");
$lineplot_humidity_simon->SetFillColor("#2222DD@0.6");
$lineplot_humidity_simon->SetWeight(1);
 
// Die Linien zu der Grafik hinzufügen
$graph2->Add($lineplot_temp_simon);
$graph2->AddY2($lineplot_humidity_simon);
 
//Graphen zusammen bauen
//**********************
$mgraph = new MGraph(700,400,"auto");
$mgraph->SetMargin(2,2,2,2);
$mgraph->Add($graph,0,0);
$mgraph->Add($graph2,0,200);
$mgraph->Stroke($fileName);
?>

Anschließend habe ich zum anzeigen der Grafiken die folgende, einfache HTML-Seite geschrieben und in das Verzeichnis /var/www gelegt.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <title>Herzlich Willkommen bei preetz.dnsalias.net!</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <link rel="shortcut icon" href="/favicon.ico" />
    <meta name="robots" content="noindex" />
        <style type="text/css"><!--
    body {
        color: #444444;
        background-color: #EEEEEE;
        font-family: 'Trebuchet MS', sans-serif;
        font-size: 80%;
    }
    h1 {}
    h2 {
        font-size: 1.2em;
        text-align: center;
    }
    p.center { text-align: center; }
    #page{
        background-color: #FFFFFF;
        width: 60%;
        margin: 24px auto;
        padding: 12px;
    }
    #header{
        padding: 6px ;
        text-align: center;
    }
    .header{ background-color: #997; color: #FFFFFF; }
    #content {
        padding: 4px 0 24px 0;
    }
    #footer {
        color:#666666;
        background: #f9f9f9;
        padding: 10px 20px;
        border-top: 5px #efefef solid;
        font-size: 0.8em;
        text-align: center;
    }
    #footer a {
        color: #999999;
    }
    --></style>
</head>
<body>
    <div id="page">
        <div id="header" class="header">
            <h1>Herzlich Willkommen bei <!--ADRESSE//-->preetz.dnsalias.net!<!--ADRESSE//--></h1>
        </div>
        <div id="content">
            <h2>Hier finden Sie die aktuellen Wetterdaten aus Preetz</h2>
            <p class="center"><img src="grafiken/graph_daily.png" alt="Daily Graph"></p>
        </div>
        <div id="footer">
            <p>Powered by <a href="http://www.isilife.de">Isilife GbR</a></p>
        </div>
    </div>
</body>
</html>

Das Ergebnis sieht dann ungefähr so aus:

1-wire Wetterstation (Teil 2: Datenbank)

Nachdem man sich eine 1-wire Wetterstation nach dem Artikel 1-wire Wetterstation (Teil 1: Installation) gebaut hat, ist es sinnvoll die gesammelten Daten in einer Datenbank zu speichern. Dazu habe ich mir eine MySQL-Datenbank angelegt.

mysql -u root -p
CREATE DATABASE wetterstation;
quit

In der Datenbank wird danach noch eine Tabelle für die Werte der 1-wire Sensoren benötigt. Da ich pro Minute einen Wert festhalten will habe ich diese daten_min genannt.

mysql -u root -p
connect wetterstation; 
CREATE TABLE daten_min ( 
zeitstempel int UNSIGNED, 
temp_clara FLOAT(7,4) NOT NULL, 
humidity_clara FLOAT(7,4) NOT NULL, 
temp_simon FLOAT(7,4) NOT NULL, 
humidity_simon FLOAT(7,4) NOT NULL, 
PRIMARY KEY (`zeitstempel`));
quit

Zum Schluss habe ich mir dann noch ein PHP-Programm geschrieben, dass die Werte der Sensoren abfragt und in die Tabelle schreibt. Dieses habe ich in der Datei /usr/local/sbin/datensammeln.php gespeichert.

<?php
$DatabaseHost = "localhost";
$DatabaseUser = "root";
$DatabasePassword = "geheim";
$Database = "wetterstation";
$Table = "daten_min";
 
// Aktuelle UNIX-Zeit abfagen
date_default_timezone_set("Europe/Berlin");
$zeitstempel = date("U");
 
// ##### Werte der Sensoren abfragen #####
// Claras Zimmer
$temp_clara = file_get_contents("/var/1wire/26.7ECCCF000000/temperature");
$humidity_clara = file_get_contents("/var/1wire/26.7ECCCF000000/humidity");
 
// Simons Zimmer
$temp_simon = file_get_contents("/var/1wire/26.A0AECF000000/temperature");
$humidity_simon = file_get_contents("/var/1wire/26.A0AECF000000/humidity");
 
// ##### Daten in die Datenbank schreiben #####
$DatabasePointer = mysql_connect($DatabaseHost, $DatabaseUser, $DatabasePassword) or die ("Keine Verbindung moeglich");
mysql_select_db($Database, $DatabasePointer) or die ("Die Datenbank existiert nicht");
$ResultPointer = mysql_query("INSERT INTO $Table (
     zeitstempel, temp_clara, humidity_clara, temp_simon, humidity_simon
   ) VALUES (
     '$zeitstempel', '$temp_clara', '$humidity_clara', '$temp_simon', '$humidity_simon'
   )");
?>

Damit man php in der Shell laufen lassen kann wird übrigens das Paket php5-cli benötigt. Dieses kann man mit dem folgenden Befehl installieren

apt-get install php-cli

Zum Schluss habe ich einen Cronjob angelegt, der alle 60 Sekunden das PHP-Script ausführt.

Genaue Daten einer CPU unter Linux anzeigen

Wer kennt das nicht? Man möchte genaueres über die verwendete CPU wissen und ein

cat /proc/cpuinfo

liefert viele kryptische Daten. Danach stellen sich einem dann meist weitere Fragen wie z.B. „Was war jetzt doch gleich das Flag für 64 Bit?“. Bevor man jetzt lange im Internet nach dem richtigen Flag sucht sollte man den Befehl

lshw -class processor

ausprobieren. Er zeigt die CPU-Eigenschaften meist übersichtlicher an und gibt dabei auch immer an wie viel Bit die CPU hat.

1-wire Wetterstation (Teil 1: Installation)

In letzter Zeit wurde in den Medien vermehrt über den 1-wire Bus berichtet. Er bietet Kabellängen von bis zu 800 Metern und es gibt günstige Sensoren, die über den Bus mit Strom versorgt werden. Darüber hinaus kann man die Sensoren sowohl sternförmig als auch in einer Reihe anschließen. Höchste Zeit also, um mir den Bus mal näher anzusehen. Also beschloss ich mit meiner Tochter eine Wetterstation auf Basis des 1-wire Bus zu bauen. In der ersten Ausbaustufe haben wir uns dabei auf Temperatur- und Feuchtigkeitssensoren beschränkt. In der zweiten Ausbaustufe sollen dann weitere Sensoren folgen.

Als Hardwareplattform haben wir eine AMD Geode LX CPU und ein ALIX-Board verwendet, da uns der geringe Stromverbrauch und Preis überzeugten. Die Hardware hat insgesamt 249,69- € gekostet und der Stromverbrauch liegt bei unter 5 Watt.

Lieferant Hersteller/Model Preis
shop.varia-store.com Mainboard ALIX.1D, Bundle (Board, Netzteil,
CF, Gehäuse)
149,99- €
www.fuchs-shop.com 1-Wire Verteiler 8-fach 17,90- €
www.fuchs-shop.com LinkUSB 27,90- €
www.fuchs-shop.com MS-TH 51,90- €
www.fuchs-shop.com Patchkabel 10m 2,00- €

Als Softwareplattform haben wir ein Ubuntu Linux 10.04 Server verwendet, welches wir „minimal“ als „LAMP-Server“ (Linux, Apache, MySQL und PHP) installiert haben. Weitere Informationen über ALIX und Ubuntu findet man auf den Webseiten http://wiki.ubuntuusers.de/Alix und https://help.ubuntu.com/community/1wireSoftware.

Installation von Ubuntu
Zunächst haben wir Ubuntu 10.04 Server wie auf der Webseite http://wiki.ubuntuusers.de/Alix beschrieben installiert. Nach der „minimalen“ Installation mussten noch einige Softwarepakete nachinstalliert werden.

sudo apt-get install autoconf
sudo apt-get install automake
sudo apt-get install libtool
sudo apt-get install libfuse-dev
sudo apt-get install libusb-dev
sudo apt-get install libusb++-dev
sudo apt-get install swig
sudo apt-get install php5
sudo apt-get install php5-dev
sudo apt-get install python-dev
sudo apt-get install libperl-dev
sudo apt-get install tcl-dev

Danach haben wir die neuste Version des OWFS von der Webseite http://sourceforge.net/projects/owfs/files/ herunter geladen und kompiliert (man könnte natürlich auch ein Paket bauen). Dazu haben wir einfach das Archiv das wir herunter geladen haben entpackt und sind in das Verzeichnis owfs gewechselt. Danach braucht man nur die folgen befehle anwenden.

./bootstrap
./configure
make
sudo make install
modprobe fuse

Danach haben wir die Sensoren angeschlossen, ein Verzeichnis angelegt und das owfs gemountet.

mkdir /var/1wire
/opt/owfs/bin/owfs --link=/dev/ttyUSB0 -p 4304 /var/1wire

Danach sind die Sensoren einsatzbereit. In dem Verzeichnis /var/1wire findet man jetzt für jeden Sensor ein Unterverzeichnis das die ID-Nummer des Sensors als Namen trägt. Das könnte z.B. 26.7ECCCF000000 sein. In diesem Verzeichnis findet man wiederum die einzelnen Daten des Sensors. Bei einem Temperatursensor findet man die Temperatur dann z.B. in der Datei /var/1wire/26.7ECCCF000000/temperature.

Fortsetzung im Artikel 1-wire Wetterstation (Teil 2: Datenbank).