Basteleien

Temperaturlogging mit dem rrdtool

1. Einleitung

Im folgenden wird beschrieben wie Temperaturen mit

1.) kabelgebundenen Temperatursensoren Dallas DS81B20, dem Net-IO-Board von Pollin, dem RasperiPi und dem rrdtool
und
2.) mit den an die WLAN-Funkmodule angschlossenen Temperatursensoren Dallas DS18B20, dem RaspberryPi und dem rrdtool

aufgezeichnet werden.

An den Anfang der Seite

2. Kabelgebundene Temperatursensoren Dallas DS18b20 mit AVR-Net-IO von Pollin, Raspberry Pi mit Raspian, Ethersex

2.1 Ethersex Firmware für AVR-NET-IO erzeugen (ethersex.hex)

Dazu ist das AVR-Net-IO von Pollin erforderlich, es kann bei Pollin (www.pollin.de) als Fertigmodul oder als Bausatz bezogen werden (AVR-Fertigmodul 28,95 € Stand Dez. 2016). Empfohlen wird ein Austausch des Prozessors Atmega 32 –> Atmega 644 (fuses atmega 644: ef: FF ,hf 99 oder D9, lf:FF). Zum flashen der ethersex-Firmware ist ein ISP Programmer erforderlich (z.Bsp der Smart USB Light oder der USBasp).
Wer keine Linux-Maschine hat, kann sich unter Windows mit Hilfe des kostenlosen VMWARE eine virtuelle Ubuntu Maschine installieren /z.Bsp Ubuntu 10.04).
In einem Terminalfenster wird mit den ogligatorischen Befehlen
 

apt-get update
apt-get upgrade

 

das Ubuntu system auf den neuesten Stand gebracht.
Es empfiehlt sich mit mkdir ein Verzeichnis z.B. ethersexinstall zu erstellen , in das Verzeichnis zu wechseln und dann die Ethersexsoftware von dem repostiory zu holen:
 

git clone git://github.com/ethersex/ethersex.git

 

Damit das make menuconfig funktioniert müssen vorher noch einige Pakete installiert werden:
 

sudo apt-get install gcc-avr avr-libc binutils-avr m4 gawk libncurses5-dev
make dialog git-core avrdude

 

Jetzt in das Verzeichnis ethersex wechseln und make menuconfig ausführen:

make menuconfig

Auf dem Bildschirm erscheint:

Load a Default Configuration → Pollin AVR Net IO
General Setup: Prompt for Experimental Code markieren, Target Architecture: AVR, TARGET MCU: Atmega 644, MCU Frequency:16000000, Hardware/periphery Class: NetIO VFS(Virtual File System Support): markieren, Control6 Skripts: markieren
Network: [*] Ethernet (ENC28J60) support → Etherrape IP address: „xxx.xxx.xxx“, Netmask: „255.255.255.0“
Network: [*]Default gateway: Das eigene Gateway, d.h. die IP Adresse des Routers eintragen.
Network: [*] TCP support
Network: [*] UDP support
IO: [*] Named and logic state I/O │ │ │ │ (default) Named pin configuration
IO: [*] TTY Layer (EXPERIMENTAL) → (X) Simple
IO: [*] ADC input → (ARef) ADC Reference
IO: [*] Onewire support → [*] Onewire device detection support
Protocols:[*] ECMD (Ethersex Command) support → [*] TCP/Telnet, [*] UDP
Applications: [*] System clock support → [*] Date and Time support , [*] Use 32 kHz crystal to tick the clock, [*] Synchronize using NTP protocol, [*] Uptime (whm in unix format like: d days, hh:mm)
Applications: [*] http Server

Wenn unter Protocols [*] Use 32 kHz crystal to tick the clock aktiviert wird, muss an den PINs TOSC1(PC6) resp. TOSC2(PC7) ein 32 kHz Uhrenquarz angeschlossen werden.

Danach mit make die Datei ethersex.hex erzeugen. Mit dieser Datei wird der Atmega 644 im Net IO Board geflasht.

make

An den Anfang der Seite

2.2 Ethersex Firmware auf AVR-NET-IO flashen (ethersex.hex)

In das Verzeichnis ethersex mit cd ethersex wechseln und mit:

cd ethersex
sudo avrdude -p m644 -P lpt1 -c usbasp -U flash:w:ethersex.hex

den atmega 644 flashen.

usbasp isp avr programmer

An den Anfang der Seite

2.3 Anschluß der Temperatursensoren Dallas DS18B20 an das Pollin Board

 

AVR-Net-IO von Pollin Sub D platine von Pollin (3,95 € Stand 12.16)

 

An den Anfang der Seite

2.4 Anzeige der Temperaturwerte der Dallas DS18B20 am AVR-NET-IO im Webbrowser

Wird das Pollin Board nun per Netzwerkkabel an das lokale Netzwerk angeschlossen, so kann über die IP-Adresse des Pollin Boardes die Oberfläche von Ethersex angezeigt werden:

Wird die IP-Adresse des Pollin Boards im Browser eingeben, es erscheint ähnliches wie:

Durch folgende Eingabe: IP-Adresse/ow.ht erscheint:

Unter Address stehen die IDs der Temperatursensoren unter Data die jeweiligen Temperaturen.

 

An den Anfang der Seite

2.5 Tempeaturlogging mit dem RaspberryPI

Mit einem RaspberryPI können die Temperaturwerte sowohl in einer Textdatei, als auch in einer MySql Datenbank geloggt werden. Eine weitere Möglichkeit ist das Temperaturlogging per rrdtool.

Auf dem Raspi kann das Betriebssystem Raspian installiert werden, indem ein entsprechendes Image heruntergeladen wird und mit der Software win32diskimager auf die SD-Karte des Raspi
übertragen wird.Nach dem ersten Start des Raspi und dem ssh-Zugang z.Bsp über Mobaxterm empfiehlt es sich foglende Befehle auszuführen:

apt-get update
apt-get upgrade

Weiterhin müssen folgende Pakete installiert werden:

apt-get install rrdtool
apt-get install php5
apt-get install netcat
apt-get install librrds-perl

Voraussetzung für das logging der Temperaturen ist, daß eine Datenbank für das rrdtool erzeugt werden muß.

Nach der Installation des Raspi und der Installation der obigen Pakete kann das mit folgendem Befehlen in der Datei rrd_db_erzeug_ds_1820_kabel.sh erreicht werden:

rrd_db_erzeug_ds_1820_kabel.sh

#!/bin/bash
rrdtool create hometemp_ds1820_kabel.rrd –step 300 \
DS:temp_wz:GAUGE:600:U:U \
DS:temp_k:GAUGE:600:U:U \
RRA:AVERAGE:0.5:1:12 \
RRA:AVERAGE:0.5:1:288 \
RRA:AVERAGE:0.5:12:168 \
RRA:AVERAGE:0.5:12:720 \
RRA:AVERAGE:0.5:288:365

In der ersten Zeile wird die rrd-Datenbank hometemp_ds1820_kabel.rrd erzeugt. Das –step 300 besagt, daß alle 300 sek=5min ein Wert abgespeichert werden kann.
temp_wz und temp_k sind die Namen der Temperaturwerte in der rrd-Datenbank. In dieser Datenbank werdn also zwei Temperaturwerte aufgezeichnet. Weitere Werte zur
Erzeugung der rrd-Datenbank bitte im Internet zum Thema rrdtool nachlesen.

Wird also die Datei hometemp_ds1820_kabel.rrd ausgeführt, findet man im aktuellen Verzeichnis die rrd-Datenbank hometemp_ds1820_kabel.rrd.

An den Anfang der Seite

2.6 Erfassen der Temperaturen und speichern in der rrd-Datenbank mit einem shellskript rrd_temp_kabel_db_update.sh:

#!/bin/bash
AVRNETIO_IP=“192.168.178.10″
AVRNETIO_PORT=2701
TEMP_ID=“28ff0cb0a1150354″ #tempfühler vorne
TEMP_ID_ter=“28607e7406000065″ #tempfühler terrasse
temp_vorne_datei=“/ethersex/rfm12/`date ‚+%Y’`/`date ‚+%m’`/`date ‚+%d’`/temp_vorne_`date ‚+%Y’`_`date ‚+%m’`_`date ‚+%d’`neu_test.txt“
temp_zaehler=0
temp_zaehler_vorne=0
tag=`date ‚+%d’`
jahr=`date ‚+%y’`
monat=`date ‚+%m’`
stunde=`date ‚+%H’`
minute=`date ‚+%M’`
sekunde=`date ‚+%S’`
while [ -z „$temp_ter“ ] #falls variable leer, while schleife
do
temp_zaehler_ter=`expr $temp_zaehler_ter + 1` #anzahl der Durchläufe in der Schleife
echo „tempzaehlerterrasse=$temp_zaehler_ter“
if [ $temp_zaehler_ter -gt 5 ] ; then # ist die anzahl der Durchläufe grösser als 5, dann Abbruch
break
fi
`echo 1w convert $TEMP_ID_ter | nc -u -n $AVRNETIO_IP $AVRNETIO_PORT -q 1 | grep -v OK || exit 1` # Temperaturmessung
temp_ter=`echo „1w get $TEMP_ID_ter“ | nc -u -v -n $AVRNETIO_IP $AVRNETIO_PORT -q 1` #speichern der Temperatur in der Variable temp_ter
temp_ter=`echo $temp_ter | sed ’s/^ //’` #löscht Leerzeichen
echo „tempterrasse=$temp_ter“
done
sleep 10
while [ -z „$temp_vorne“ ]
do
temp_zaehler_vorne=`expr $temp_zaehler_vorne + 1`
echo „tempzaehlervorne=$temp_zaehler_vorne“
if [ $temp_zaehler_vorne -gt 5 ] ; then
break
fi
`echo 1w convert $TEMP_ID | nc -u -n $AVRNETIO_IP $AVRNETIO_PORT -q 1 | grep -v OK || exit 1`
temp_vorne=`echo „1w get $TEMP_ID“ | nc -u -v -n $AVRNETIO_IP $AVRNETIO_PORT -q 1`
temp_vorne=`echo $temp_vorne | sed ’s/^ //’`
echo „tempvorne=$temp_vorne“
done
echo „temperaturvorne=$temp_vorne“
echo „temperaturterrasse=$temp_ter“
datum_stunde_minute=`date +’%Y-%m-%d %H:%M:00’`
u_zeit=`date –date=“$datum_stunde_minute“ +%s` #unixzeit
temp_vorne1=`echo $temp_vorne | sed ’s/^ //’` #löscht leerzeichen
echo „temperaturvorne=$temp_vorne“
zeile_ter=`echo $jahr $monat $tag $stunde $minute $sekunde $temp_ter1`
echo „zeileterrasse=$zeile_ter“
if [ $var1w_ter != „1w“ ] ; then
echo $zeile_ter >> /ethersex/rfm12/`date ‚+%Y’`/`date ‚+%m’`/`date ‚+%d’`/temp_ter_`date ‚+%Y’`_`date ‚+%m’`_`date ‚+%d’`temp_terrasse.txt #Abspeichern der zeileterrasse in der Datei, im Verzeichnis /ethersex/rfm12/2016/
#Beispieldaeiname=temp_ter_2016_12_04temp_terrasse.txt
fi
echo „temperatur=$temp_vorne1“
echo „unixzeit=$u_zeit“
rrdtool update /ethersex/rrdtool/hometemp_ds1820_kabel.rrd $u_zeit:$temp_wz1:$temp_vorne1 #speichert die Temperaturwerte mit der unixzeit in der rrd-Datenbank

Diese Shellskript lasse ich mit Hilfe von crontab alle 5 min ausführen. Dazu ist folgender Eintrag in der crontab erforderlich:

*/5 * * * * /ethersex/rrdtool/rrd_temp_kabel_db_update.sh

An den Anfang der Seite

2.7 Anzeige der Temperaturwerte in einer Graphik

Damit die Temperaturwerte über den Tag benutzerfreundlich angezeigt werden können ist eine Grafik erforderlich z.B. so:

Diese graphische Anzeige erfordert php, perl und javaskript. Mit javaskript wird der Kalender erzeugt mit perl die Graphik innerhalb von cgi-bin.

Die Graphik kann angezeigt werden indem im Browser folgendes eingegeben wird:

IP-Adresse des Webservers/temperatur.php

An den Anfang der Seite

2.8 Einrichtung des apache2 Webservers für cgi-bin

Im Verzeichnis

/etc/apache2/sites-available die Datei default anpassen:
 

cd /etc/apache2/sites-available
nano ./default

An den Anfang der Seite

2.9 Perl Skript zur Erzeugung der Temperaturgraphik

<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www/>
Options Indexes FollowSymLinks MultiViews ExecCGI
AllowOverride None
Order allow,deny
allow from all
</Directory>
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory „/usr/lib/cgi-bin“>
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
AddHandler cgi-script .cgi .pl
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

In dieser perl Datei können Graphiken für 5 Temperaturfühler erzeugt werden.

value
in
temperatur.php
rrd-DatenbankTemperatur-
Bezeichnung
in
rrd-Datenbank
shellskript
Erzeugung
Datenbank
rfm12temp/ethersex/rrdtool/hometemp.rrdrfm12temp/ethersex/rrdtool/rrd_db_erzeug.sh
temp_vorne/ethersex/rrdtool/hometemp_ds1820_kabel.rrdtemp_k/ethersex/rrdtool/rrd_db_erzeug_ds_1820_kabel.sh
temp/ethersex/rrdtool/hometemp_neu_1.rrdrfm12temp_ter/ethersex/rrdtool/rrd_db_erzeug_hometemp_neu_1.sh
temp_wz/ethersex/rrdtool/hometemp_ds1820_kabel.rrdtemp_wz/ethersex/rrdtool/rrd_db_erzeug_ds_1820_kabel.sh
temp_k/ethersex/rrdtool/hometemp_ds1820_kabel.rrdtemp_k/ethersex/rrdtool/rrd_db_erzeug_ds_1820_kabel.sh

In diesen if bzw. elsif Ausdrücken sind die jeweiligen value-werte der Datei temperatur.php:

elsif (($x[0] eq „rfm12temp“) && ($x[1] eq „temp_vorne“) && ($x[2] eq „“)) # 1. und 2. bedeutet in der Datei temperatur.php diese beiden sind angehakt:

 

An den Anfang der Seite

2.10 Die php-Datei temperatur.php zur Anzeige der Temperaturgraphik im Web-Browser

Die php-Datei temperatur.php sieht folgendermaßen aus:

<!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=“en“ xml:lang=“en“>
<head>
<title>Temperaturen rrdtool</title>
<script type=“text/javascript“>
// <!– webdarstellung frei nach http://www.kompf.de/weather/pionewire.html –>
var date = new Date();
var monthNames = new Array(„Januar“, „Februar“, „M&auml;rz“, „April“, „Mai“, „Juni“,
„Juli“, „August“, „September“, „Oktober“, „November“, „Dezember“);
var daysInMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
function lenOfMonth() {
var month = date.getMonth();
var year = date.getFullYear();
if (1 == month) {
return ((0 == year % 4) && (0 != (year % 100))) ||
(0 == year % 400) ? 29 : 28;
}
else {
return daysInMonth[month];
}
}
function drawCalendar() {
var d1 = new Date(date.getFullYear(), date.getMonth(), 1);
var wday1 = d1.getDay() – 1;
if (wday1 < 0) wday1 = 6;
var mlen = lenOfMonth();
document.getElementById(„tyear“).innerHTML = date.getFullYear();
document.getElementById(„tmonth“).innerHTML = monthNames[date.getMonth()];
for (var i = 0; i < 42; ++i) {
var el = document.getElementById(„td“ + i);
var d = i – wday1 + 1;
if (d <= 0 || d > mlen) {
el.innerHTML = ‚&nbsp;‘;
} else {
el.innerHTML = “;
var a = document.createElement(‚a‘);
a.href=“javascript:sd(“ + d + „)“;
a.innerHTML = d.toString();
el.appendChild(a);
}
if (d == date.getDate()) {
el.className = ’selected‘;
} else {
el.className = “;
}
}
}
function setDateParams() {
var month = date.getMonth() + 1;
document.forms[0].start.value = „00:00 “ + date.getDate() + „.“ + month + „.“ + date.getFullYear();
var endDate = new Date(date.getTime());
if (document.forms[0].range[0].checked == true) {
endDate.setDate(endDate.getDate() + 1);
} else if (document.forms[0].range[1].checked == true) {
endDate.setDate(endDate.getDate() + 7);
} else if (document.forms[0].range[2].checked == true) {
endDate.setMonth(endDate.getMonth() + 1);
} else if (document.forms[0].range[3].checked == true) {
endDate.setFullYear(endDate.getFullYear() + 1);
}
month = endDate.getMonth() + 1;
document.forms[0].end.value = „00:00 “ + endDate.getDate() + „.“ + month + „.“ + endDate.getFullYear();
}
function dy(delta) {
date.setFullYear(date.getFullYear() + delta);
drawCalendar();
setDateParams();
}
function dm(delta) {
date.setMonth(date.getMonth() + delta);
drawCalendar();
setDateParams();
}
function sd(d) {
date.setDate(d);
drawCalendar();
setDateParams();
}
function init() {
drawCalendar();
setDateParams();
document.forms[0].submit();
}
// –>
</script>
<style media=“all“ type=“text/css“>
@import „../style/kompf.css“;
</style>
<style type=“text/css“>
body, table, form {
font: 10px/16px open_sans, arial, helvetica, sans-serif;
background-color: white;
margin:0px;
width:100%;
}
form table, form table td {
background-color: #F8F475;
}
td {
font: 18px/24px open_sans, arial, helvetica, sans-serif;
border-width: 0px 0px 1px 0px;
border-style: solid;
border-color: #998DB3;
}
td.selected {
background-color: #EE5512;
}
fieldset {
float: left;
}
#td6 a, #td13 a, #td20 a, #td27 a, #td34 a, #td41 a {
color: red !important;
}
form a:link {
color: blue;
text-decoration: none;
}
form a:visited {
color: blue;
text-decoration: none;
}
form a:hover {
text-decoration: none;
background-color: #f90;
}
#druck{position:absolute;top:550px;left:800px;}
#temp_vorne{position:absolute;top:550px;left:1200px;}
#temp_ter{position:absolute;top:620px;left:1400px;}
#divselect{position:absolute;width:100%;top:450px;left:50px;}
</style>
</head>
<body onload=“init()“>
<div id=“Header“> &gt; Wetteraufzeichnung (einstellbarer Zeitraum)
</div>
<div id=“divimage“><iframe frameborder=“1″ height=“400″ id=“graph2″ marginheight=“0″ marginwidth=“0″ name=“graph2″ scrolling=“auto“ width=“1600″></iframe></div>
<div id=“divselect“>
<form action=“http://192.168.178.87/cgi-bin/graph2.pl“ enctype=“application/x-www-form-urlencoded“ id=“formselect“ method=“get“ target=“graph2″ name=“formselect“>
<fieldset><legend>Messgr&ouml&szlige</legend>
<table>
<tr>
<td colspan=“1″ rowspan=“1″><input checked=“checked“ id=“var“ name=“var“ type=“checkbox“ value=“rfm12temp“><label for=“vartemp0″>Temperatur rfm12 Garten &#176C (rfm12temp)</label></td>
</tr>
<tr>
<td colspan=“1″ rowspan=“1″><input checked=“checked“ id=“vartemp1″ name=“var“ type=“checkbox“ value=“temp_vorne“><label for=“vartemp1″>Temperatur vorne &#176C (temp_vorne)</label></td>
</tr>
<tr>
<td colspan=“1″ rowspan=“1″><input id=“vartemps5″ name=“var“ type=“checkbox“ value=“temp“><label for=“vartemps5″>Temperatur Terrasse &#176C (temp)</label></td>
</tr>
<tr>
<td colspan=“1″ rowspan=“1″><input id=“vartemps7″ name=“var“ type=“checkbox“ value=“temp_wz“><label for=“vartemps7″>Temperatur Wohnzimmer &#176C (temp_wz)</label></td>
</tr>
<tr>
<td colspan=“1″ rowspan=“1″><input id=“vartemps9″ name=“var“ type=“checkbox“ value=“temp_k“><label for=“vartemps9″>Temperatur Keller &#176C (temp_k)</label></td>
</tr>
</table>
</fieldset>
<!–<fieldset><legend>MinMax</legend>
<table>
<tr>
<td colspan=“1″ rowspan=“1″><input id=“minmax“ name=“minmax“ type=“checkbox“ value=“true“><label for=“minmax“>Minimum/Maximum anzeigen</label></td>
</tr>
</table> –>
</fieldset>
<fieldset><legend>Zeitraum</legend>
<table>
<tr>
<td colspan=“1″ rowspan=“1″><input checked=“checked“ id=“rangeday“ name=“range“ onchange=“javascript:setDateParams()“ type=“radio“ value=“day“><label for=“rangeday“>Tag</label></td>
</tr>
<tr>
<td colspan=“1″ rowspan=“1″><input id=“rangeweek“ name=“range“ onchange=“javascript:setDateParams()“ type=“radio“ value=“week“><label for=“rangeweek“>Woche</label></td>
</tr>
<tr>
<td colspan=“1″ rowspan=“1″><input id=“rangemonth“ name=“range“ onchange=“javascript:setDateParams()“ type=“radio“ value=“month“><label for=“rangemonth“>Monat</label></td>
</tr>
<tr>
<td colspan=“1″ rowspan=“1″><input id=“rangeyear“ name=“range“ onchange=“javascript:setDateParams()“ type=“radio“ value=“year“><label for=“rangeyear“>Jahr</label></td>
</tr>
</table>
</fieldset>
<fieldset><legend>Startzeitpunkt</legend>
<table class=“calendar“>
<tr>
<td colspan=“1″ rowspan=“1″><a href=“javascript:dy(-1)“>&lt;</a></td>
<td colspan=“5″ id=“tyear“ rowspan=“1″>
<td colspan=“1″ rowspan=“1″><a href=“javascript:dy(+1)“>&gt;</a></td>
</tr>
<tr>
<td colspan=“1″ rowspan=“1″><a href=“javascript:dm(-1)“>&lt;</a></td>
<td colspan=“5″ id=“tmonth“ rowspan=“1″>
<td colspan=“1″ rowspan=“1″><a href=“javascript:dm(+1)“>&gt;</a></td>
</tr>
<tr>
<td colspan=“1″ id=“td0″ rowspan=“1″>
<td colspan=“1″ id=“td1″ rowspan=“1″>
<td colspan=“1″ id=“td2″ rowspan=“1″>
<td colspan=“1″ id=“td3″ rowspan=“1″>
<td colspan=“1″ id=“td4″ rowspan=“1″>
<td colspan=“1″ id=“td5″ rowspan=“1″>
<td colspan=“1″ id=“td6″ rowspan=“1″></tr>
<tr>
<td colspan=“1″ id=“td7″ rowspan=“1″>
<td colspan=“1″ id=“td8″ rowspan=“1″>
<td colspan=“1″ id=“td9″ rowspan=“1″>
<td colspan=“1″ id=“td10″ rowspan=“1″>
<td colspan=“1″ id=“td11″ rowspan=“1″>
<td colspan=“1″ id=“td12″ rowspan=“1″>
<td colspan=“1″ id=“td13″ rowspan=“1″></tr>
<tr>
<td colspan=“1″ id=“td14″ rowspan=“1″>
<td colspan=“1″ id=“td15″ rowspan=“1″>
<td colspan=“1″ id=“td16″ rowspan=“1″>
<td colspan=“1″ id=“td17″ rowspan=“1″>
<td colspan=“1″ id=“td18″ rowspan=“1″>
<td colspan=“1″ id=“td19″ rowspan=“1″>
<td colspan=“1″ id=“td20″ rowspan=“1″></tr>
<tr>
<td colspan=“1″ id=“td21″ rowspan=“1″>
<td colspan=“1″ id=“td22″ rowspan=“1″>
<td colspan=“1″ id=“td23″ rowspan=“1″>
<td colspan=“1″ id=“td24″ rowspan=“1″>
<td colspan=“1″ id=“td25″ rowspan=“1″>
<td colspan=“1″ id=“td26″ rowspan=“1″>
<td colspan=“1″ id=“td27″ rowspan=“1″></tr>
<tr>
<td colspan=“1″ id=“td28″ rowspan=“1″>
<td colspan=“1″ id=“td29″ rowspan=“1″>
<td colspan=“1″ id=“td30″ rowspan=“1″>
<td colspan=“1″ id=“td31″ rowspan=“1″>
<td colspan=“1″ id=“td32″ rowspan=“1″>
<td colspan=“1″ id=“td33″ rowspan=“1″>
<td colspan=“1″ id=“td34″ rowspan=“1″></tr>
<tr>
<td colspan=“1″ id=“td35″ rowspan=“1″>
<td colspan=“1″ id=“td36″ rowspan=“1″>
<td colspan=“1″ id=“td37″ rowspan=“1″>
<td colspan=“1″ id=“td38″ rowspan=“1″>
<td colspan=“1″ id=“td39″ rowspan=“1″>
<td colspan=“1″ id=“td40″ rowspan=“1″>
<td colspan=“1″ id=“td41″ rowspan=“1″></tr>
</table>
</fieldset>
<fieldset><legend>Grafik</legend> <input name=“size“ type=“text“ value=“Zeitraum“> <input name=“start“ type=“text“ value=“now – 1 day“> <input name=“end“ type=“text“ value=“now“> <input type=“submit“ value=“Anzeigen“></fieldset>
</form>
</div>
<!– Der folgende php-Abschnitt ist für die anzeige der Temperaturwerte aus den Textdateien –>
<?php
echo „<div id = ‚druck‘>“;
$timestamp = time();
$jahr = date(„Y“,$timestamp);
$monat = date(„m“,$timestamp);
$tag = date(„d“,$timestamp);
$file=“/ethersex/rfm12/“.$jahr.“/“.$monat.“/“.$tag.“/rfm_12_temp_“.$jahr.“_“.$monat.“_“.$tag.“.txt“ ;
$inhalt_file=file($file);
$anz_zeilen=count($inhalt_file);
echo „<br>“;
echo „anzahlzeilen=“.$anz_zeilen;
echo „<br>“;
echo $file;
echo „<br>“;
echo $inhalt_file[$anz_zeilen-1];
$zeile=$inhalt_file[$anz_zeilen-1];
$zeile_ar=explode(“ „,$zeile);
$temp_10_a=$zeile_ar[4];
// echo „temp10_a=$temp_10_a“;
$temp_1_a=$zeile_ar[5];
// echo „temp1_a=$temp_1_a“;
// echo „<br>“;
$temp=$temp_10_a.“.“.$temp_1_a ;
$vz_gart=$zeile_ar[3] ;
// echo „vz_gart=$vz_gart“ ;
if ($vz_gart ==“1″) {
// echo „plus“;
// echo „temp10_a=$temp_10_a“;
echo „<p style=’font-size:20px;‘>Temperatur Garten</p>“;
echo „<p style=’font-size:20px;‘>“.$temp.“ &deg;C</p>“;
} else {
echo „minus“;
$temp=$temp * -1;
echo „<p style=’font-size:20px;‘>Temperatur Garten</p>“;
echo „<p style=’font-size:20px;‘>“.$temp.“ &deg;C</p>“;
}
//echo „temp10_v_2=$temp_10_a“;
echo „</div>“;
?>
<?php
// Temp_vorne
echo „<div id = ‚temp_vorne‘>“;
//rfm_12_temp_2014_10_22
$file_v=“/ethersex/rfm12/“.$jahr.“/“.$monat.“/“.$tag.“/temp_vorne_“.$jahr.“_“.$monat.“_“.$tag.“neu_test.txt“ ;
$inhalt_file_v=file($file_v);
$anz_zeilen_v=count($inhalt_file_v);
echo „<br>“;
echo „anzahlzeilen_v=“.$anz_zeilen_v;
echo „<br>“;
echo $file_v;
echo „<br>“;
echo $inhalt_file_v[$anz_zeilen_v-1];
$zeile_v=$inhalt_file_v[$anz_zeilen_v-1];
$temp_v_ar=explode(“ „,$zeile_v);
// $temp_10_v=$temp_v_ar[4];
// $temp_1_v=$temp_v_ar[5] ;
$temp_vorne=$temp_v_ar[6];
echo „tempvorne=$temp_vorne „;
// $vz=$temp_v_ar[3] ;
//echo „vz=$vz“ ;
// if ($vz ==“1″) {
//echo „plus“;
// echo „temp10_v_2=$temp_10_v“;
// echo „temp10_v=$temp_10_v“;
// echo „<p style=’font-size:20px;‘>Temperatur Vorne</p>“;
// $temp_v=$temp_10_v.“.“.$temp_1_v ;
// echo „<p style=’font-size:20px;‘>“.$temp_v.“ °C</p>“;
//} else if ($vz ==“0″) {
// echo „minus“;
// $temp_v=$temp_10_v.“.“.$temp_1_v ;
// $temp_v=$temp_v * -1;
echo „<br>“;
// echo „temp1_v=$temp_1_v“;
// echo „temp10_v=$temp_10_v“;
echo „<p style=’font-size:20px;‘>Temperatur Vorne</p>“;
//$temp_v=$temp_10_v.“,“.$temp_1_v ;
echo „<p style=’font-size:20px;‘>“.$temp_vorne.“ &deg;C</p>“;
//}
// echo „temp10_v_2=$temp_10_v“;
?>
<?php
//HIER ID ANPASSEN!!!!
// echo „<b> Letzte Änderung: „.date(„d.m.Y,H:i“,
// filemtime(basename(„/temperatur/temp_daily.png“)));
// echo “ Uhr </b>“;
// $file = ‚/sys/bus/w1/devices/28-000004f8c7a4/w1_slave‘;
// $lines = file($file);
// $temp = explode(‚=‘, $lines[1]);
// $temp = number_format($temp[1] / 1000, 1, ‚,‘, “);
// $temps = explode(„,“, $temp);
// $temp_terrasse=$temps[0].“,“.$temps[1].“°C“;
$file_terr=“/ethersex/rfm12/“.$jahr.“/“.$monat.“/“.$tag.“/temp_ter_“.$jahr.“_“.$monat.“_“.$tag.“temp_terrasse.txt“ ;
$inhalt_file_terr=file($file_terr);
$anz_zeilen_terr=count($inhalt_file_terr);
echo „<br>“;
echo „anzahlzeilen_terr=“.$anz_zeilen_terr;
echo „<br>“;
echo $file_terr;
echo „<br>“;
echo $inhalt_file_terr[$anz_zeilen_terr-1];
$zeile_terr=$inhalt_file_terr[$anz_zeilen_terr-1];
$temp_terr_ar=explode(“ „,$zeile_terr);
// $plus_minus= $temp_terr_ar[11];
$temp_terrasse=$temp_terr_ar[6];
echo „</div>“;
echo „<div id = ‚temp_ter‘>“;
echo „<p style=’font-size:20px;‘>Temperatur Terrasse</p>“;
echo „<p style=’font-size:20px;‘>“.$temp_terrasse.“ &deg;C</p>“; ;
echo „</div>“;
$timestamp = time();
$jahr = date(„Y“,$timestamp);
$monat = date(„m“,$timestamp);
$tag = date(„d“,$timestamp);
?>
</body>
</html>

Der javaskript Abschnitt der Datei erzeugt diesen Kalender, der variabel beliebig zum Einstellen des Datums ist:

 

In dem Bild steht der Kalender auf dem 4.12. 2016 und in der Graphik werden dann nachdem der Button Anzeigen angeklickt wurde die Temperaturen vom 4.12.16 00:00 Uhr bis 5.12.00 Uhr also für 24 Stunden angezeigt.
Selbstverständlich kann man auch den Zeitraum verlängern, oder verkürzen.

 

Graph für die Anzeige der Wochenwerte

usw.

Damit der Graph angezeigt wird muß in der php-Datei temperatur.php der Verweis auf die Perl Datei stehen.
 

<form action=“http://192.168.178.87/cgi-bin/graph2.pl“ enctype=“application/x-www-form-urlencoded“ id=“formselect“ method=“get“ target=“graph2″ name=“formselect“>


Der php-Abschnitt in der Datei temperatur.php führt zu dieser Anzeige:

An den Anfang der Seite

3. Temperaturmessung – und Temperaturlogging mit dem WLAN Funkmodul ESP8266, RaspberryPI mit Raspian, RRDtool und Dallas DS18B20

Das WLAN-Funkmodul ESP8266 ist ein preisgünstiges Funkmodul es ist sehr klein und eignet sich deshalb zur Übertragung von Temperaturwerten gemessen mit dem Dallas Temperatursensor DS  18B20 per WLAN.

 

ESP8266-12E Schaltbild

Mit den folgenden Dateien wird der esp8266-01 programmiert:

ds.lua:

t = require(„ds18b20“)
— GPIO0 is pin 4 esp8226-01,GPI4 0=pin 2
pin = 4
lasttemp = 0
t.setup(pin)
temperature=t.read()
lasttemp = temperature
t1 = lasttemp / 10000
t2 = (lasttemp >= 0 and lasttemp % 10000) or (10000 – lasttemp % 10000)
tempout=(string.format(„%d“, t1) .. „.“ .. string.sub(t2, 1, 1))
print(„Temperature: „..tempout..“‚C“)

ds18b20.lua:

——————————————————————————–
— DS18B20 one wire module for NODEMCU
— NODEMCU TEAM
— LICENCE: http://opensource.org/licenses/MIT
— Vowstar <vowstar@nodemcu.com>
— 2015/02/14 sza2 <sza2trash@gmail.com> Fix for negative values
——————————————————————————–

— Set module name as parameter of require
local modname = …
local M = {}
_G[modname] = M
——————————————————————————–
— Local used variables
——————————————————————————–
— DS18B20 dq pin
local pin = nil
— DS18B20 default pin
local defaultPin = 9
——————————————————————————–
— Local used modules
——————————————————————————–
— Table module
local table = table
— String module
local string = string
— One wire module
local ow = ow
— Timer module
local tmr = tmr
— Limited to local environment
setfenv(1,M)
——————————————————————————–
— Implementation
——————————————————————————–
C = ‚C‘
F = ‚F‘
K = ‚K‘
function setup(dq)
pin = dq
if(pin == nil) then
pin = defaultPin
end
ow.setup(pin)
end

function addrs()
setup(pin)
tbl = {}
ow.reset_search(pin)
repeat
addr = ow.search(pin)
if(addr ~= nil) then
table.insert(tbl, addr)
end
tmr.wdclr()
until (addr == nil)
ow.reset_search(pin)
return tbl
end

function readNumber(addr, unit)
result = nil
setup(pin)
flag = false
if(addr == nil) then
ow.reset_search(pin)
count = 0
repeat
count = count + 1
addr = ow.search(pin)
tmr.wdclr()
until((addr ~= nil) or (count > 100))
ow.reset_search(pin)
end
if(addr == nil) then
return result
end
crc = ow.crc8(string.sub(addr,1,7))
if (crc == addr:byte(8)) then
if ((addr:byte(1) == 0x10) or (addr:byte(1) == 0x28)) then
— print(„Device is a DS18S20 family device.“)
ow.reset(pin)
ow.select(pin, addr)
ow.write(pin, 0x44, 1)
— tmr.delay(1000000)
present = ow.reset(pin)
ow.select(pin, addr)
ow.write(pin,0xBE,1)
— print(„P=“..present)
data = nil
data = string.char(ow.read(pin))
for i = 1, 8 do
data = data .. string.char(ow.read(pin))
end
— print(data:byte(1,9))
crc = ow.crc8(string.sub(data,1,8))
— print(„CRC=“..crc)
if (crc == data:byte(9)) then
t = (data:byte(1) + data:byte(2) * 256)
if (t > 32767) then
t = t – 65536
end

if (addr:byte(1) == 0x28) then
t = t * 625 — DS18B20, 4 fractional bits
else
t = t * 5000 — DS18S20, 1 fractional bit
end

if(unit == nil or unit == ‚C‘) then
— do nothing
elseif(unit == ‚K‘) then
t = t + 2731500
else
return nil
end
–t = t / 10000
return t
end
tmr.wdclr()
else
— print(„Device family is not recognized.“)
end
else
— print(„CRC is not valid!“)
end
return result
end

function read(addr, unit)
t = readNumber(addr, unit)
if (t == nil) then
return nil
else
return t
end
end

— Return module table
return M

send.lua:

function sendData(tempout)
print(tempout)
conn = nil
conn = net.createConnection(net.TCP, 0)
conn=net.createConnection(net.TCP, false)
conn:on(„receive“, function(conn, payload) print(„Get done.“, payload) end )
conn:connect(80,“192.168.178.87″)
conn:send(„GET /temp_esp8266.php?tempout=“..tempout..“ HTTP/1.1\r\nHost: 192.168.178.87\r\n“ .. „Connection: keep-alive\r\nAccept: */*\r\n\r\n“)
end
sendData(tempout)

und zum Schluß init.lua:

–init.lua
— Check every 600000 10 minutes – 15000 – 15sec -900.000 15 min
–tempout = 0 — Initialize value that holds temp
wifi.setmode(wifi.STATION)
–modify according your wireless router settings
wifi.sta.config(„wlan-id“,“passwort“)
wifi.sta.connect()
tmr.alarm(1, 1000, 1, function()
if wifi.sta.getip()== nil then
print(„IP unavaiable, Waiting…“)
print(„Setting up WIFI…“)
else
tmr.stop(1)
print(„Config done, IP is „..wifi.sta.getip())
tempout = 0
ipadress = wifi.sta.getip()
dofile(‚ds.lua‘)
dofile(’send.lua‘)
tmr.alarm(2, 300000, 1, function() — Do every 15 minutes
print(„Config done, IP is „..wifi.sta.getip())
tempout = 0
dofile(‚ds.lua‘)
dofile(’send.lua‘)
— node.dsleep(400000000)
tmr.wdclr(2)
end)
end
end)
srv = net.createServer(net.TCP)srv:listen(80, function(conn)
conn:on(„receive“, function(conn, payload)
print(payload)
conn:send(‚HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nCache-Control: private, no-store\r\n\r\n‘)
conn:send(‚<!DOCTYPE HTML>‘)
conn:send(‚<html lang=“en“>‘)
conn:send(‚<head>‘)
conn:send(‚<meta http-equiv=“Content-Type“ content=“text/html; charset=utf-8″>‘)
conn:send(‚<meta http-equiv=“refresh“ content=“60″>‘)
conn:send(‚<meta name=“viewport“ content=“width=device-width, initial-scale=1″>‘)
conn:send(‚<title>(2_ESP8266 & DS18B20)</title>‘)
conn:send(‚</head>‘)
conn:send(‚<body>‘)
conn:send(‚<h1>(2_ESP8266 & DS18B20)</h1>‘)
conn:send(‚<h2>‘)
conn:send(‚<input style=“text-align: center“ type=“text“ size=4 name=“p“ value=“‚.. tempout ..'“> C <br><br>‘)
conn:send(‚IP-Adresse=‘)
conn:send(‚<input style=“text-align: center“ type=“text“ size=20 name=“x“ value=“‚.. ipadress .. ‚“> <br><br>‘)
conn:send(‚</h2>‘)
conn:send(‚</body></html>‘)
conn:close()
collectgarbage()
end)
conn:on(„sent“, function(conn) conn:close() end)
end)

An den Anfang der Seite

3.1 Bemerkungen zu den Dateien init.lua, send.lua

Die Datei init.lua wird beim booten des Moduls automatisch ausgeführt.

mit dem Abschnitt:

tmr.alarm(2, 300000, 1, function() — Do every 5 minutes
print(„Config done, IP is „..wifi.sta.getip())
tempout = 0
dofile(‚ds.lua‘)
dofile(’send.lua‘)
— node.dsleep(400000000)
tmr.wdclr(2)
end)

in init.lua werden alle 5 Minuten die Dateien ds.lua und send.lua ausgeführt.

mit dem Abschnitt

srv:listen(80, function(conn)

bis

conn:on(„sent“, function(conn) conn:close() end)
end)

in init.lua wird eine html-Seite unter der Ip-Adresse des ESP8266 erzeugt. Die html-Seite sieht dann so aus:

In der Datei send.lua befindet sich die Zeile:

conn:send(„GET /temp_esp8266_12E.php?tempout=“..tempout..“ HTTP/1.1\r\nHost: 192.168.178.87\r\n“ .. „Connection: keep-alive\r\nAccept:

Diese Zeile führt die Datei temp_esp8266_12E.php aus, der Temperaturwert der in tempout gespeichert ist, wird übergeben.
Die Datei speichert weiterhin den Temperaturwert in einer Textdatei mit Namen temp_terrasse_2016_12_04.txt im Verzeichnis des aktuellen Jahres, Monats, Tages ab. Asußerdem wird der Temperaturwert
zusammen mit der aktuellen Uhrzeit und Datum in der Form der unixzeit in der rrd-Datenbank /ethersex/rrdtool/esp_8266_temp_terrasse.rrd abgespeichert.

temp_esp8266_12E.php:

//$temp=10.5;
$pfad_jahr=“/var/www/“.$now->format(‚Y‘);
$pfad_monat=“/var/www/“.$now->format(‚Y‘).“/“.$now->format(‚m‘).“/“;
$pfad_tag=“/var/www/“.$now->format(‚Y‘).“/“.$now->format(‚m‘).“/“.$now->format(‚d‘).“/“;
$pfad=“/var/www/“.$now->format(‚Y‘).“/“.$now->format(‚m‘).“/“.$now->format(‚d‘).“/“;
if (is_dir($pfad_jahr)) {
} else {
mkdir ($pfad_jahr);
}
if (is_dir($pfad_monat)) {
} else {
mkdir ($pfad_monat);
}
if (is_dir($pfad_tag)) {
} else {
mkdir ($pfad_tag);
}
$file= „temp_terrasse_“.$now->format(‚Y_m_d‘).“.txt“;
$pfad=“/var/www/“.$now->format(‚Y‘).“/“.$now->format(‚m‘).“/“.$now->format(‚d‘).“/“;
$datei = fopen($pfad.$file,“a+“);
$temp1=“\n“.$temp.“ „;
echo fwrite($datei, $temp1);
echo fwrite($datei, $datenow);
fclose($datei);
$datenow = $now->format(‚Y-m-d H:i:s‘);
//$datenow=$datenow.“:00″;
$conn->close();
$u_zeit=strtotime($datenow) ;
// $uzeit=strtotime($datenow) ;
if ($temp != 85) {
exec(„/usr/bin/rrdtool update /ethersex/rrdtool/esp_8266_temp_terrasse.rrd $u_zeit:$temp“);
}
?>

An den Anfang der Seite

4. Dateien zum Download

rrd_db_erzeug_ds_1820_kabel.sh

rrd_temp_kabel_db_update.sh

graph2.pl

temperatur.php

ds.lua

ds18b20.lua

send.lua

init.lua