1wire
Länkar till otestat mög
[redigera]En annan variant (läs "hack") på lösning baserat på OWW
[redigera]Översikt
[redigera]Basmög: "one-wire weather", http://oww.sourceforge.net/
OWW kan läsa flera temperatursensorer men loggar i grundutförande enbart en. Därför får man göra en patch för att logga mer data. Loggningen sker via http till ett CGI-script. Webservern kan därefter göra behandling av data.
En bättre lösning är troligtvis att skriva något som använder owfs (one-wire filesystem) på sensorsidan och om man kör mätningarna på samma burk som loggningen dessutom ersätta webserverskickandet med ett rent cronjobb.
Färdighårdvara från temperatur.nu, med usb-adapter (ex https://shop.temperatur.nu/temperaturnat-1-sensor-p-30.html). Möget körs på en linuxmaskin med 2.6.16-kärna.
RRD
[redigera]Jag har valt att använda RRD för loggning eftersom den kan rita fina grafer, göra vissa uträkningar, etc. För att kunna använda detta behöver man skapa en rrd-fil först:
rrdtool create weather.rrd DS:temp:GAUGE:600:U:U RRA:AVERAGE:0.5:1:576 RRA:MIN:0.5:1:576 RRA:MAX:0.5:1:576 RRA:AVERAGE:0.5:6:432 RRA:MIN:0.5:6:432 RRA:MAX:0.5:6:432 RRA:AVERAGE:0.5:24:540 RRA:MIN:0.5:24:540 RRA:MAX:0.5:24:540 RRA:AVERAGE:0.5:288:450 RRA:MIN:0.5:288:450 RRA:MAX:0.5:288:450
Parametrarna är gott magiska och jag minns inte vad de betyder.
Skapa en per sensor, i scripten nedan finns det en "weather_indoor.rrd" också.
Konfigurering
[redigera]Sätt konfigureringen i OWW att använda dallasprotokollet:
httpdallas http://<adress till server och katalog med mög i>/weather.php httpdallason 1
Konfigurera även ID för sensorerna så att de inte byter plats logiskt om de byter plats fysiskt.
Loggningsscript
[redigera]weather.php
Uppdaterar en rrd-fil samt loggar temperaturen i en textfil för att undvika att något tappas bort när rrd slår runt. Använder två parametrar "Tem" och "Tem2" som skickas av oww (se patchen nedan)
<?php
$filetostorein = "temperatures.log";
$filetostoreindoor = "temperatures_indoor.log";
# get the temperature from the request
$temp = $_REQUEST['Tem'];
$indoor = $_REQUEST['Tem2'];
# get the date (seconds since 1970)
$t = time();
$handle = fopen($filetostorein,"a");
fwrite($handle, $t . " " . $temp . "\n");
fclose($handle);
$handle = fopen($filetostoreindoor,"a");
fwrite($handle, $t . " " . $indoor . "\n");
fclose($handle);
# update rrd database
system("/opt/csw/bin/rrdupdate weather.rrd $t:$temp");
system("/opt/csw/bin/rrdupdate weather_indoor.rrd $t:$indoor");
?>
Script för presentation av data
[redigera]Jag använder tre script som är väldigt lika, graph.php, weekgraph.php, monthgraph.php.
graph.php
<?php
header('Content-Type: image/png');
system("./baz.sh");
print file_get_contents("weather.png");
?>
Skillnaden ligger i att de anropar olika shellscript, baz.sh, wbaz.sh, mbaz.sh.
JA, det går att göra snyggare och optimalare, men man skall inte ändra saker som fungerar...
baz.sh
#!/usr/bin/bash /opt/csw/bin/rrdtool graph weather.png -z -f "" -t "Temperature - Last day" -E -a PNG \ DEF:tmax=weather.rrd:temp:MAX DEF:indoor=weather_indoor.rrd:temp:AVERAGE \ DEF:tmin=weather.rrd:temp:MIN DEF:temp=weather.rrd:temp:AVERAGE \ DEF:yday=weather.rrd:temp:AVERAGE:end=now-1d:start=end-1d \ SHIFT:yday:86400 VDEF:tempmax=tmax,MAXIMUM VDEF:tempmin=tmin,MINIMUM \ CDEF:diff=temp,yday,- \ LINE1:diff#ffff00:"" \ LINE1:indoor#0000FF:"" LINE1:temp#FF0000:"" \ LINE1:yday#00FF00:"" \ GPRINT:tempmin:"Min %2.1lf C" LINE0.5:tempmax#6699FF:"" LINE0.5:tempmin#6699FF GPRINT:tempmax:"Max %2.1lf C" \ VDEF:tempavg=temp,AVERAGE GPRINT:tempavg:"Avg %2.1lf C" VDEF:tempcur=temp,LAST GPRINT:tempcur:"Now %2.1lf C" \ GPRINT:tempcur:"Time %H.%M\n":strftime \ VDEF:inavg=indoor,AVERAGE VDEF:inmax=indoor,MAXIMUM VDEF:inmin=indoor,MINIMUM VDEF:incur=indoor,LAST \ GPRINT:inmin:"Inmin %2.1lf C" GPRINT:inmax:"Inmax %2.1lf C" GPRINT:inavg:"Inavg %2.1lf C" GPRINT:incur:"Innow %2.1lf C" \ 2>&1 > /dev/null
wbaz.sh:
#!/usr/bin/bash /opt/csw/bin/rrdtool graph weatherweek.png -z -e now -s end-1week -f "" -t "Temperature - Last week" -E -a PNG DEF:tmax=weather.rrd:temp:MAX DEF:indoor=weather_indoor.rrd:temp:AVERAGE DEF:tmin=weather.rrd:temp:MIN DEF:temp=weather.rrd:temp:AVERAGE LINE1:indoor#0000FF LINE1:temp#FF0000:"" VDEF:D=temp,LSLSLOPE VDEF:H=temp,LSLINT CDEF:projection=temp,POP,D,COUNT,*,H,+ LINE1:projection#BB2030:"" VDEF:tempmax=tmax,MAXIMUM VDEF:tempmin=tmin,MINIMUM GPRINT:tempmin:"Min %2.1lf C" LINE0.5:tempmax#6699FF:"" LINE0.5:tempmin#6699FF GPRINT:tempmax:"Max %2.1lf C" VDEF:tempavg=temp,AVERAGE GPRINT:tempavg:"Avg %2.1lf C" VDEF:tempcur=temp,LAST GPRINT:tempcur:"Time %H.%M":strftime 2>&1 > /dev/null
mbaz.sh:
#!/bin/sh /opt/csw/bin/rrdtool graph weathermonth.png -z -e now -s end-1month -f "" -t "Temperature - Last month" -E -a PNG \ DEF:indoor=weather_indoor.rrd:temp:AVERAGE \ LINE1:indoor#0000FF \ DEF:tmax=weather.rrd:temp:MAX \ DEF:tmin=weather.rrd:temp:MIN \ DEF:temp=weather.rrd:temp:AVERAGE LINE1:temp#FF0000:"" \ VDEF:tempmax=tmax,MAXIMUM \ VDEF:tempmin=tmin,MINIMUM \ GPRINT:tempmin:"Min %2.1lf C" \ GPRINT:tempmax:"Max %2.1lf C" \ VDEF:tempavg=temp,AVERAGE GPRINT:tempavg:"Avg %2.1lf C" \ VDEF:tempcur=temp,LAST GPRINT:tempcur:"Time %H.%M":strftime \ DEF:ymonth=weather.rrd:temp:AVERAGE:end=now-1y:start=end-1y \ SHIFT:ymonth:31556926 \ LINE1:ymonth#00FF00:lastyear \ 2>&1 > /dev/null
Jag har även två script som visar ALL data:
Nattligt cronjob, "nightlycron.sh", körs kl 00:00 varje natt
#!/usr/bin/bash
#
# script to collect the max, avg, min data during the day and write it to a log
#
export PATH=/usr/local/bin:/opt/csw/bin:$PATH
cd <path to directory with data>
rm -f temp.tmp
rm -f tempp.tmp
#
# calc the data on daily basis
#
firstdata=0
for midnight in `sed 's/^/@/' < temperatures.log | cut -d' ' -f1 | gdate -f - +%y%m%d | uniq | gdate -f - +%s`; do
if [ $firstdata = 0 ]; then firstdata=$midnight; fi
foo=`gdate -d @$midnight`
echo "$midnight: $foo"
awk "BEGIN {c=0;sum=0;max=-100;min=100;start=$midnight;stop=start+86400} \$1 > start && \$1 < stop {apa=\$2;sum=sum+apa;c=c+1;if(max<apa) max=apa; if(min>apa) min=apa;} END {print start\",\"max\",\"sum/c\",\"min}" < temperatures.log >> tempp.tmp
done
#
# remove bad datapoints
#
grep -v "0.0,0,0.0" tempp.tmp > temp.tmp
#
# and plot the graph
#
/opt/csw/bin/gnuplot yearly.gnuplot
# update image
wget http://<www>/<weatherpath>/graph.php -o /dev/null -O /dev/null
yearly.gnuplot:
set term png size 481,179 set datafile separator "," #set xrange [1208948000:1211022500] set output "weatheryear.png" set timefmt "%s" set format x "%b %y" set xtics nomirror rotate set xdata time #unset tics unset key plot "temp.tmp" using 1:2 with lines, "temp.tmp" using 1:3 with lines, "temp.tmp" using 1:4 with lines
Patch
[redigera]--- sendwx.c.orig 2008-05-17 13:46:46.814612534 +0200
+++ sendwx.c 2008-05-17 13:37:15.360145696 +0200
@@ -256,6 +256,8 @@
static rainlist remote_list24 = {NULL, 0, 0, RAININT_TIMEOUT_24HR} ;
static int remote_rain = 0 ;
+ return 1;
+
char *start = NULL, *end = NULL ;
int i ;
@@ -540,7 +542,7 @@
/*if (!strstr(session->body, session->reply))*/
{
/* Not the expected reply */
- werr(WERR_WARNING, _("URL fetch failed: %s"), session->body) ;
+ werr(WERR_DEBUG0, _("URL fetch failed: %s"), session->body) ;
}
else
{
@@ -665,38 +667,49 @@
sprintf(urlstring, "%s?Mode=0&WID=%s&Dat=%d"
"&Tem=%.1f&WSp=%.0f&WDr=%d"
"&RSp=%.2f&Dar=%d"
- "&Cod=%s&Lon=%.6f&Lat=%.6f",
+ "&Cod=%s&Lon=%.6f&Lat=%.6f&Tem2=%.1f",
setup_httpdallas,
Wid,
(int) convert_time(means->meanTime),
+/*
convert_temp(weather_primary_T(means), setup_f),
+*/
+ means->meanT[0],
convert_speed(means->meanWs, setup_f),
means->point,
convert_mm(means->rain, !setup_f),
(int) convert_time(ws.t_rain[0]),
(setup_f)?"English":"Metric",
setup_longitude,
- setup_latitude
+ setup_latitude,means->meanT[1]
) ;
}
else
{
sprintf(urlstring, "%s?Mode=0&WID=%s&Dat=%d"
"&Tem=%.1f&WSp=%.0f&WDr=%d&Cod=%s"
- "&Lon=%.6f&Lat=%.6f",
+ "&Lon=%.6f&Lat=%.6f&Tem2=%.1f",
setup_httpdallas,
Wid,
(int) convert_time(means->meanTime),
+/*
convert_temp(weather_primary_T(means), setup_f),
+*/
+ means->meanT[0],
convert_speed(means->meanWs, setup_f),
means->point,
convert_mm(means->rain, !setup_f),
(int) convert_time(ws.t_rain[0]),
(setup_f)?"English":"Metric",
setup_longitude,
- setup_latitude
+ setup_latitude,means->meanT[1]
) ;
}
else
{
sprintf(urlstring, "%s?Mode=0&WID=%s&Dat=%d"
"&Tem=%.1f&WSp=%.0f&WDr=%d&Cod=%s"
- "&Lon=%.6f&Lat=%.6f",
+ "&Lon=%.6f&Lat=%.6f&Tem2=%.1f",
setup_httpdallas,
Wid,
(int) convert_time(means->meanTime),
+/*
convert_temp(weather_primary_T(means), setup_f),
+*/
+ means->meanT[0],
+
convert_speed(means->meanWs, setup_f),
means->point,
(setup_f)?"English":"Metric",
setup_longitude,
- setup_latitude
+ setup_latitude,means->meanT[1]
) ;
}
+ //puts(urlstring);
+ //exit(0);
+
set_old_locale();
+
}
static void