Anleitung zum Selbstbau Übersicht
- Teil 1 Projekt Info
- Teil 2 Einkaufsliste
- Teil 3 Funksender bauen
- Teil 4 Funkempfänger bauen
- Teil 5 Inbetriebnahme und Test
- Teil 6 Anzeige der Sensor Daten via Web und via App (Dieser Artikel)
- Zusatz – Sender PCB Version
- Abschluss des RasPi Projekts
Status
Aktuell arbeite ich noch an einer passenden Lösung zur Datenhaltung und Darstellung, diese werde ich sobald sie fertig ist hier vorstellen. Eventuell werde ich auch ein ausführliches Tutorial zu einem Home Automation Tool wie FHEM o.ä. erstellen, das habe ich noch nicht entschieden. Bis dahin wird euch sicherlich auch die Ausgabe auf einer einfacheren Webseite reichen, ihr könnt diese natürlich anpassen.
Update: Ich habe mich für das EmonCMS unter dem OpenEngeryMonitor Projekt entschieden, das System läuft schon länger stabil und zuverlässig. Die Visualisierung in Dashboards ist super! Hier der Artikel zum EmonCMS
Ausgabe der Daten auf einer Webseite
Update: Als Alternative zu dieser Anleitung können die Diagramme auch mit Google Charts generiert werden, Infos gibt es im Beitrag Temperatur Diagramme mit Google Charts erstellen.
Wir haben nun Sender gebaut, den Empfänger am Raspberry Pi angeschlossen und unser Setup via Minicom getestet. Die gesammelten Daten möchten wir natürlich nun noch schön anschaulich auf einer Webseite ausgeben.
Dafür benötigen wir folgendes auf dem Raspberry Pi:
- Eine Datenbank zum langfristigen Speichern der Temperatur und Feuchtigkeit-Daten, da es sich im wesentliche um nur eine Tabelle handeln wird eignet sich SqlLite (ich verzichte hier aufs Normalisieren)
- Einen Webserver der für uns die Ausgabe übernimmt. Zum Beispiel Apache oder Lighttpd
- Passende PHP Scripte / Libraries die für uns den Inhalt der Datenbank verarbeiten und ausgeben
- Eine Schnittstelle zum Auslesen der Daten bzw. zum Speichern der Daten in der Datenbank, das übernimmt ein Perl Script für uns.
- Einen Wachhund der prüft ob der Datensammler läuft und diesen ggf. startet
- Der RasPi muss ins Internet kommen um sich regelmäßig die aktuelle Uhrzeit abzuholen (konfiguriert eure Zeit Einstellungen via raspi-config).
Falls euer RasPi noch auf den Desktop bootet solltet ihr das via raspi-config wieder ändern, der Bootvorgang verzögert sich nur unnötig. Ebenfalls den Split Memory Wert für die Grafikkarte auf 16MB runterstellen.
Wir beginnen mit der Installation unseres Webservers und der Datenbank. In diesem Fall habe ich mich der Einfachheit halber für Apache entschieden, wer möchte kann auch den leichtgewichtigen Lighttpd verwenden. Apt Installiert in meinem Fall den Webserver Apache2, PHP5, die PHP Library GD zur Handhabung von Grafiken, SQLLite zum Speichern unserer Daten und das Tool screen um unseren Datensammler im Hintergrund laufen zu lassen.
1 |
Zusätzlich benötigen wir noch einige Perl Libraries für das Script welches die Daten des Empfängers via UART abholt und einen Neustart des Pi
1 2 | sudo apt-get install -y libdevice-serialport-perl libwww-mechanize-perl libproc-daemon-perl sudo reboot |
Um euch die Copy und Paste´s zu ersparen habe ich den unten stehenden Code für euch zusammengepackt, diesen könnt ihr jetzt wie folgt installieren. Enthalten ist folgendes:
- Die PHP Scripte und Style Sheets
- Die Library JpGraph 3.5.0b1 zum erstellen der Grafiken
1 2 3 4 5 6 | cd ~ wget http://raspberry.tips/wp-content/uploads/2014/11/www.tar.gz sudo mkdir -p /var/www/ sudo tar -zxf www.tar.gz -C /var/www/ sudo chown -R www-data:www-data /var/www/Sensor |
1 2 3 4 5 6 | sudo su sudo wget -O/root/Watchdog.sh http://raspberry.tips/wp-content/uploads/2014/11/Watchdog.txt sudo wget -O/root/Sensor.pl http://raspberry.tips/wp-content/uploads/2014/11/Sensor.txt sudo chmod +x /root/Sensor.pl && sudo chmod +x /root/Watchdog.sh |
1 2 | export EDITOR=nano sudo crontab -e |
1 | */5 * * * * /root/Watchdog.sh >/dev/null 2>&1 |
1 | sudo screen -dmS sensor /root/Sensor.pl |
1 | http://<ip-raspberry-pi>/Sensor/add.php?key=23338d373027ce83b1f81b9e9563b629&node=20&v=4578&t=1410&h=5410 |
Folgende Hinweiße:
- In der Daten config.php könnt ihr euren Node IDs Namen zuordnen, das solltet ihr für jede neue Node tun. Nodes 19,20, 21 sind schon mit Beispielnamen eingetragen.
- Ändert nachträglich den Security Key in der /root/Sensor.pl und in /var/www/Sensor/config.php das verhindert das jemand unbefugtes via add.php in die Datenbank schreiben kann
- In dieser Webserver Konfiguration sollte der RasPi aus dem Internet erreichbar sein
- In der Ursprünglichen Version liegt die Datenbank und das Verzeichnisse für die Grafiken in einer RAM Disk um den SD-Karte zu schonen, darauf habe ich hier zu Gunsten der Einfachheit verzichtet
Viel Spaß!
Die Webseite – Code
Unser Hauptseite zum Anzeigen der Temperatur und Luftfeuchtigkeit (index.php)
Dieses Script ist der Anlaufpunkt für unseren Browser. Es generiert zum einen die Grafiken für uns und zeigt uns zum anderen die letzten gemessenen Werte der einzelnen Sensoren an.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de"> <head> <title>http://raspberry.tips - Temperatur Ausgabe</title> <link href="style.css" rel="stylesheet" type="text/css" /> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <meta name="robots" content="DISALLOW"> </head> <body style="background-image:none"> <?php //------------------- Config und Funktionen einbinden -------------------------- require_once("config.php"); require_once("functions.php"); //------------------------ Libraries Einbinden --------------------------------- include("jpgraph-3.5.0b1/src/jpgraph.php"); include("jpgraph-3.5.0b1/src/jpgraph_line.php"); require_once("jpgraph-3.5.0b1/src/jpgraph_date.php"); error_reporting(E_ALL); //------------------------ PHP Settings ---------------------------------------- ini_set('track_errors', 1); ini_set('display_errors', 1); ini_set('log_errors', 1); ini_set("memory_limit","64M"); ini_set("max_execution_time","30"); @ob_implicit_flush(true); @ob_end_flush(); $_SELF=$_SERVER['PHP_SELF']; $s=" "; $DURATION_start = microtime(true); //------------------------------------------------------------------- if (!isset($GRAPH['SetImgFormat']) OR empty($GRAPH['SetImgFormat'])) { $GRAPH['SetImgFormat'] = "png"; } if ($GRAPH['SetImgFormat'] != "png" OR $GRAPH['SetImgFormat'] != "jpeg" OR $GRAPH['SetImgFormat'] != "gif") { $GRAPH['SetImgFormat'] = "png"; } if (!isset($GRAPH['DIR']) OR empty($GRAPH['DIR'])) { $GRAPH['DIR'] = "."; } //------------------------------------------------------------------------------ if (!file_exists($DBfile)) { echo "<center>need input! :)</center>n"; _exit(); } $now = time(); $Nunc = date('Y-m-d',$now); $SelectedNodes = isset($_POST["nodeID"]) ? $_POST["nodeID"] : ""; $GetDATE = isset($_POST["date"]) ? $_POST["date"] : $Nunc; //------------------------------------------------------------------------------ if ($GetDATE == $Nunc) { $DisplayDATE = "Today"; } else { $DisplayDATE = $GetDATE; } $DAYSBACK = "7"; //----------------- Aktuelle Werte Ausgeben ------------------------------------ echo "<center>n"; echo "<table border='0'>n<tr>"; $db = db_con($DBfile); $q = db_query("SELECT temp,place FROM werte WHERE id IN (SELECT MAX(id) FROM werte GROUP BY nodeID)"); while ($res = $q->fetch(PDO::FETCH_ASSOC)) { $temp = $res['temp'] / 100; $arrayTemp = explode(".", $temp); echo "<td>n<div align='center'>n"; echo " <h2>".$res['place']."</h2>n"; echo " <div class='container'>n"; echo " <div class='de'>n"; echo " <div class='den'>n"; echo " <div class='dene'>n"; echo " <div class='denem'>n"; echo " <div class='deneme'>n"; echo " ".$arrayTemp[0]."<span>".$arrayTemp[1]."</span>"; echo " </div>n"; echo " </div>n"; echo " </div>n"; echo " </div>n"; echo " </div>n"; echo " </div>n"; echo "</div>n</td>n" ; } unset($res); echo "</tr>n</table>n"; //----------------------------------------------------------------------------------- //----------------- Knoten zur Auswahl holen ------------------------------------ echo "<br/>n"; echo "<br/>n"; echo "<form action='' method='POST' name='NodesForm'>n"; echo "<table border='0'>n"; echo "<caption><b>Select Sensor to show:</b></caption>n"; $i=0; $MAXROW=5; $db = db_con($DBfile); $q = db_query("SELECT nodeID,place FROM werte WHERE 1 GROUP BY nodeID ORDER BY nodeID ASC"); while ($res = $q->fetch(PDO::FETCH_ASSOC)) { $CHECKED=""; if (!empty($SelectedNodes)) { $FoundChecked=0; foreach ($SelectedNodes AS $node_id) { if ($node_id == $res['nodeID']) { $FoundChecked=$node_id; } } if ($FoundChecked != 0) { $CHECKED="checked='checked'"; } } if ($i == 0) { echo "<tr>n"; } echo "<td><input type='checkbox' name='nodeID[]' value='".$res['nodeID']."' ".$CHECKED." />$s".$res['place']."$s</td>n"; $i++; if ($i == $MAXROW) { echo "</tr>n"; $i=0; } } unset($FoundChecked); unset($node_id); unset($res); echo "</table>n"; //----------------- Datumsauswahl generieren ------------------------------------ echo "<p>n"; echo "<select name='date'>n"; echo " <option value='".$Nunc."' selected='selected'>".$Nunc."</option>n"; for ($i = 1; $i <= $DAYSBACK; $i++) { $tmpday = date('d',$now) - 1; if ($tmpday <= "0") { $date = date('Y-m-d',mktime(0, 0, 0, date("m")-1, date("d")-$i, date("Y"))); } else { $date = date('Y-m-d',mktime(0, 0, 0, date("m"), date("d")-$i, date("Y"))); } echo " <option value='".$date."'>".$date."</option>n"; } echo "</select>n"; echo "</p>n"; echo "<p><input type='submit' value='Go' name='ShowNodes'/></p>n"; echo "</form>n"; if (empty($SelectedNodes)) { _exit(); } //----------------- Grafiken generieren ------------------------------------ $ShowNodeIDlist=array(); $SQL0="SELECT time,nodeID,place,supplyV,temp,hum,date(time,'unixepoch') AS Date FROM werte WHERE Date='".$GetDATE."' AND ("; $SQL1=""; foreach ($SelectedNodes AS $NID) { if (empty($SQL1)) { $SQL1 = "nodeID='".$NID."'"; } else { $SQL1 .= " OR nodeID='".$NID."'"; } GenerateGraph($NID); echo "<img src='".$GRAPH['DIR']."/".$NID.".".$GRAPH['SetImgFormat']."' /> <br/>n"; } $SQL2=") ORDER BY time DESC"; //----------------- Tabelle mit Werten ------------------------------------ echo "<div id='SensorDetails'>n"; echo "<table class='Sensors' border=1 cellpadding=2 cellspacing=0 bordercolorlight>n"; echo "<tr>n"; echo "<th class='tab'>Date</th>n"; echo "<th class='tab'>Sensor</th>n"; echo "<th class='tab'>Supply Voltage</th>n"; echo "<th class='tab'>Temperature</th>n"; echo "<th class='tab'>Humidity</th>n"; echo "</tr>n"; // get Added Entries $q = db_query("".$SQL0." ".$SQL1." ".$SQL2.""); while ($result = $q->fetch(PDO::FETCH_ASSOC)) { $datetime = date('H:i:s d.m.Y',$result['time']); $nodeID = $result['nodeID']; $place = $result['place']; $supplyV = $result['supplyV'] / 1000; $temp = $result['temp'] / 100; if (!empty($result['hum'])) { $humi = $result['hum'] / 100; } else { $humi = "$s"; } echo "<tr>n"; echo "<td class='tab1' align='CENTER'>$s ".$datetime." $s</td>n"; echo "<td class='tab1' align='CENTER'>$s ".$place." $s</td>n"; echo "<td class='tab1' align='CENTER'>$s ".$supplyV."V $s</td>n"; echo "<td class='tab1' align='CENTER'>$s ".$temp."°C $s</td>n"; if (!empty($humi)) { echo "<td class='tab1' align='CENTER'>$s ".$humi."% $s</td>n"; } else { echo "<td class='tab1' align='CENTER'> $s </td>n"; } echo "</tr>n"; } echo "</table></div>n"; echo "<br/><br/><br/>"; $DURATION_end = microtime(true); $DURATION = $DURATION_end - $DURATION_start; echo "<p><font size='0'>Page generated in ".round($DURATION, 3)." seconds</font></p>n"; ?> </body> </html> |
Perl Script zum Werte auslesen und in die Datenbank schreiben (Sensor.pl)
Dieses Script liest die Daten, welche der Empfänger erhalten hat, vom UART aus übergibt diese an die add.php welche die Daten wiederum in der SQLite Datenbank speichert. Wichtig ist das der Secret Key mit dem in der Config.php übereinstimmt da sonst keine Daten gespeichert werden.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | #!/usr/bin/perl -w # Reads data from serial port and posts to PHP #### CONFIG - START # Secret Key my $KEY = '23338d373027ce83b1f81b9e9563b629'; # set url to add.php my $url = "http://127.0.0.1/Sensor/add.php?key=". $KEY ."&node="; # set UART baudrate my $baudrate = 9600; my $PORT = "/dev/ttyAMA0"; #### CONFIG - END # Declare the subroutines sub trim($); BEGIN { push @INC,"/usr/lib/perl5/"; } use strict; use Device::SerialPort qw( :PARAM :STAT 0.07 ); use WWW::Mechanize; use Time::localtime; use Scalar::Util 'looks_like_number'; use Proc::Daemon; print "Serial to PHP gateway for RaspberryPi with RFM12Brn"; my $ob = Device::SerialPort->new($PORT); $ob->baudrate($baudrate); $ob->parity("none"); $ob->databits(8); $ob->stopbits(1); #$ob->handshake("xoff"); $ob->write_settings; open(SERIAL, "+>$PORT"); my $continue = 1; $SIG{TERM} = sub { $continue = 0 }; while ($continue) { my $line = trim(<SERIAL>); print $line; print "rn"; my @values = split(' ', $line); if(looks_like_number($values[0]) && $values[0] >=1) { post2php($values[0],$values[1]); sleep(2); } } sub post2php { my $ua = WWW::Mechanize->new(); my $URL = $url . $_[0] ."&" . $_[1]; #my $url = "http://127.0.0.1/Sensor/add.php?key=23338d373027ce83b1f81b9e9563b629&node=" . $_[0] ."&" . $_[1]; #print $url; print "rn"; my $response = $ua->get($URL); if ($response->is_success) { #print "Success!n"; my $c = $ua->content; print ("$c"); } else { print "Failed to open url!"; #die $response->status_line; } } # Perl trim function to remove whitespace from the start and end of the string sub trim($) { my $string = shift; $string =~ s/^s+//; $string =~ s/s+$//; return $string; } # |
Watchdog Script (Watchdog.sh)
Das Shell Script wird als Cronjob eingerichtet und prüft ob das Datensammler Script Sensor.pl läuft, falls nicht wird es gestartet.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #!/bin/bash # Sensor.pl watchdog ### CONFIG - START SCRIPT=/root/Sensor.pl ### CONFIG - END #SCRIPT gestartet ? PID="$(pgrep -x $(basename $SCRIPT))" if [[ ! -z "$PID" ]] ; then echo "$(date +"%Y-%m-%d %H:%M") Watchdog - $SCRIPT laeuft" else screen -dmS sensor $SCRIPT echo "$(date +"%Y-%m-%d %H:%M") Watchdog - $SCRIPT wurde neu gestartet" fi exit 0 |
Script zum Speichern der Daten in der Datenbank (add.php)
Dieses PHP Script ermöglicht uns zwei Funktionen:
1. Es Speichert WErte die es übergeben bekommt in der SQL Lite Datenbank
2. Es erstellt uns die einfache SQLight Datenbank falls sie noch nicht vorhanden ist mit folgender Struktur:
Tabellen Name: werte
Tabellen Zellen: id (int), time (int), nodeID (int), place (text), supplyV (text), temp (text), hum (text)
Dabei ist die ID immer eindeutig (Primary Key),
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <?php //------------------------------------------------------------------------------ error_reporting(E_ALL); ini_set('track_errors', 1); ini_set('display_errors', 1); ini_set('log_errors', 1); //------------------------------------------------------------------------------ require_once("config.php"); require_once("functions.php"); //------------------------------------------------------------------------------ // check if sqlite db file exists else create it.. if (!file_exists($DBfile)) { $db = db_con($DBfile); $SQL = "CREATE TABLE IF NOT EXISTS werte (id INTEGER PRIMARY KEY,time INT,nodeID INT,place TEXT,supplyV TEXT,temp TEXT,hum TEXT)"; $create = db_query($SQL); } if (!empty($_GET)) { $ValidKey = false; foreach ($_GET AS $arg => $var) { if ($arg == "key" AND $var == $SECURITYKEY) { $ValidKey=true; } if ($arg == "node") { $nodeID = $var; } if ($arg == "v") { $supplyV = $var; } if ($arg == "t") { $temp = $var; } if ($arg == "h") { $hum = $var; } } if (!$ValidKey) { echo "Invalid Key!"; exit(); } if ( isset($nodeID) AND isset($supplyV) AND (isset($temp) OR isset($hum)) ) { if (!isset($hum)) { $SQL = "INSERT INTO werte (time,nodeID,place,supplyV,temp) VALUES ('".time()."','".$nodeID."','".$Sensor[$nodeID]."','".$supplyV."','".$temp."')"; } else { $SQL = "INSERT INTO werte (time,nodeID,place,supplyV,temp,hum) VALUES ('".time()."','".$nodeID."','".$Sensor[$nodeID]."','".$supplyV."','".$temp."','".$hum."')"; } $db = db_con($DBfile); $insert = db_query($SQL); } } ?> |
Konfigurationsdatei (config.php)
In dieser Datei verwalten wir die Konfiguration unserer Webanwendung, der Security Key muss mit dem im Perl-Script übereinstimmen, sonst werden keine Daten in der Datenbank gespeichert. Ebenfalls wird hier der Pfad zur SQL-Lite Datenbank definiert.
1 2 3 4 5 6 7 8 9 10 11 12 | <?php //------------------------------------------------------------------------------ $DBfile = "/var/www/Sensor/.db.sensors"; $SECURITYKEY = "23338d373027ce83b1f81b9e9563b629"; $GRAPH['SetImgFormat'] = "png"; //valid: png, jpeg or gif $GRAPH['DIR'] = "graphs"; //------------------------------------------------------------------------------ // $Sensor[<nodeID>] = "<Place>"; $Sensor['19'] = "Wohnzimmer"; $Sensor['20'] = "Garage / Schuppen"; $Sensor['21'] = "Garten"; ?> |
Funktionen (functions.php)
Allgemeine Funktionen die wir in unseren anderen Skripten wiederverwenden, zum Beispiel den Aufbau der Datenbankverbindung und die Erstellung der Grafiken.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | <?php function _exit() { echo "</body>"; echo "</html>"; exit(); } //______________________________________________________________________________________ // sqlite // DB connect function db_con($DBfile) { if (!$db = new PDO("sqlite:$DBfile")) { $e="font-size:23px; text-align:left; color:firebrick; font-weight:bold;"; echo "<b style='".$e."'>Fehler beim öffnen der Datenbank:</b><br/>"; echo "<b style='".$e."'>".$db->errorInfo()."</b><br/>"; die; } $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); return $db; } // DB Query function db_query($sql) { global $db; $result = $db->query($sql) OR db_error($sql,$db->errorInfo()); return $result; } //Function to handle database errors function db_error($sql,$error) { die('<small><font color="#ff0000"><b>[DB ERROR]</b></font></small><br/><br/><font color="#800000"><b>'.$error.'</b><br/><br/>'.$sql.'</font>'); } //______________________________________________________________________________________ // generate graph's function GenerateGraph($nodeID) { global $DBfile,$GRAPH,$DisplayDATE,$GetDATE; $i=0; $db = db_con($DBfile); $query = $db->query("SELECT place,time,supplyV,temp,hum,date(time,'unixepoch') AS Date FROM werte WHERE Date='".$GetDATE."' AND nodeID='".$nodeID."'"); while($result = $query->fetch(PDO::FETCH_ASSOC)){ $place = $result['place']; $TIME[$i] = $result['time']; $TEMP[$i] = $result['temp'] / 100; $HUM[$i] = $result['hum'] / 100; $SUPPLYV[$i] = $result['supplyV'] / 1000; $i++; } if ($i == 0) { return; } // Create the graph. These two calls are always required $graph = new Graph(1100,350); $graph->SetScale("datlin"); $graph->SetShadow(); $graph->SetMargin(50,50,20,100); $graph->title->Set(''.$place.': '.$DisplayDATE.''); $graph->title->SetFont(FF_FONT1,FS_BOLD); //$graph->xaxis->title->Set("Zeit"); //$graph->xaxis->title->SetFont(FF_FONT1,FS_BOLD); $graph->yaxis->title->Set("Temperatur °C"); $graph->yaxis->SetTitlemargin(40); $graph->yaxis->title->SetFont(FF_FONT1,FS_BOLD); $graph->xaxis->SetLabelFormatCallback('TimeCallback'); $graph->xaxis->SetLabelAngle(90); $graph->xaxis->scale->SetTimeAlign(MINADJ_15); $lineplot = new LinePlot($TEMP,$TIME); $lineplot->SetColor("red"); $lineplot->SetLegend("Temperature "); $lineplotb = new LinePlot($HUM,$TIME); $lineplotb->SetColor("blue"); $lineplotb->SetWeight(2); $lineplotb->SetLegend("Humidity "); $graph->SetY2Scale("lin"); $graph->AddY2($lineplotb); $graph->y2axis->title->Set("Luftfeuchte % "); $graph->y2axis->title->SetColor("blue"); $graph->y2axis->SetTitlemargin(40); // Add the plot to the graph $graph->Add($lineplot); // Adjust the legend position $graph->legend->Pos(0.5,0.98,"center","bottom"); // Display the graph //$graph->Stroke(); // generate image file for HTML pages // Get the handler to prevent the library from sending the // image to the browser $gdImgHandler = $graph->Stroke(_IMG_HANDLER); $graph->img->SetImgFormat($GRAPH['SetImgFormat']); $fileName = "".$GRAPH['DIR']."/".$nodeID.".".$GRAPH['SetImgFormat'].""; $graph->img->Stream($fileName); unset($TIME); unset($TEMP); unset($HUM); unset($SUPPLYV); } function TimeCallback($aVal) { return Date('H:i ',$aVal); } //______________________________________________________________________________________ function showarray($array) { echo "<pre><b style='font-size:13px; text-align:left; color:#c8c8c8;'>n"; var_dump($array); echo "</b>n"; flush(); } // showvar(get_defined_vars(),_SELF); function showvar($systemDefinedVars,$varName) { echo "<b style='font-size:13px; text-align:left; color:#c8c8c8;'>n"; foreach ($systemDefinedVars as $var => $value) { if ($varName == $var) { echo "$var: $systemDefinedVars[$var]"; break; } } echo "</b><br/>n"; flush(); } function _debug_($systemDefinedVars,$VAR) { echo "<b style='font-size:13px; text-align:left; color:#c8c8c8;'>n"; if (is_array($VAR)) { var_dump($VAR); } else { foreach ($systemDefinedVars as $var => $value) { if ($varName == $var) { echo "$var: $systemDefinedVars[$var]"; } } } echo "</b><br/>n"; flush(); } ?> |
Das Style Sheet (style.css)
Formatierungen für die Webseiten sind hier zentral gespeichert.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | @import url(http://fonts.googleapis.com/css?family=Dosis:200,400,500,600); html, body { height: 100%; } body { background: #f2f2f2; font-size: 8pt; color: black; font-family: Verdana,arial,helvetica,serif; margin: 0 0 0 0; } .style1 { color: #999999; font-weight: bold; } .container { width: 200px; margin: 10px auto 0; } .de .den, .de .dene, .de .denem, .de .deneme { position: absolute; left: 50%; top: 50%; } .de { position: relative; width: 240px; height: 240px; border-radius: 100%; box-shadow: 0 0 10px rgba(0, 0, 0, .1); background-color: transparent; } .den { position: relative; width: 210px; height: 210px; margin: -105px 0 0 -105px; border-radius: 100%; box-shadow: inset 0 2px 10px rgba(0, 0, 0, .5), 0 2px 20px rgba(255, 255, 255, 1); background: #df3341; background: -moz-linear-gradient(left, #df3341 0%, #d4f355 50%, #61c0ec 100%); background: -webkit-gradient(linear, left top, right top, color-stop(0%,#df3341), color-stop(50%,#d4f355), color-stop(100%,#61c0ec)); background: -webkit-linear-gradient(left, #df3341 0%,#d4f355 50%,#61c0ec 100%); background: linear-gradient(to right, #df3341 0%,#d4f355 50%,#61c0ec 100%); position:relative; } .dene { width: 180px; height: 180px; margin: -90px 0 0 -90px; border-radius: 100%; box-shadow: inset 0 2px 2px rgba(255, 255, 255, .4), 0 3px 13px rgba(0, 0, 0, .85); background: #f2f6f5; background: -moz-linear-gradient(top, #f2f6f5 0%, #cbd5d6 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f2f6f5), color-stop(100%, #cbd5d6)); background: -webkit-linear-gradient(top, #f2f6f5 0%, #cbd5d6 100%); background: -o-linear-gradient(top, #f2f6f5 0%, #cbd5d6 100%); } .denem { width: 160px; height: 160px; margin: -80px 0 0 -80px; border-radius: 100%; background: #cbd5d6; background: -moz-linear-gradient(top, #cbd5d6 0%, #f2f6f5 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #cbd5d6), color-stop(100%, #f2f6f5)); background: -webkit-linear-gradient(top, #cbd5d6 0%, #f2f6f5 100%); } .deneme { padding: 3px 10px 0 10px; width: 120px; height: 137px; display: inline-block; margin: -70px 0 0 -70px; color: #555; text-shadow: 1px 1px 1px white; font-family: 'Dosis'; font-size: 100px; font-weight: 400; text-align: center; } .deneme span { font-size: 30px; font-weight: 200; } .deneme strong { position: absolute; right: 10px; top: 25px; font-size: 34px; } |