2012-05-17 // Über externe Wetterdaten
Leider hat YAHOO! den Wetterservice vor einer Woche umgestellt. Damit funktionierte folgende Methode zum Auslesen der externen Wetterdaten (als Vergleich) nicht mehr:
#Humidity w3m -dump http://weather.yahoo.com/germany/baden-wurttemberg/schutterwald-12836276/?unit=c | grep -A21 "Current" | sed 's/DEG/°/g' | head -9 | tail -n1 | awk '{print $1}' #Temperature w3m -dump http://weather.yahoo.com/germany/baden-wurttemberg/schutterwald-12836276/?unit=c | grep -A25 "Current" | sed 's/DEG/°/g' | head -n25 | tail -n1 #Dewpoint w3m -dump http://weather.yahoo.com/germany/baden-wurttemberg/schutterwald-12836276/?unit=c | grep -A21 "Current" | sed 's/DEG/°/g' | head -n13 | tail -n1 | awk '{print $1}'
Da ich zu dieser Zeit auf Studienfahrt in Prag war, konnte ich mich erst letztem Wochenende diesem Problem widmen. Für diese Zeit fehlten dann leider die externen Wetterdaten:
Eine provisorische Lösung
Die Daten von YAHOO! sind eigentlich nicht zu gebrauchen: es fehlen Taupunkt und rel. Luftfeuchtigkeit und ohne Javascript ist das Auslesen nur in °F möglich
Da YAHOO aber im Endeffekt auch nur Wetterdaten von TheWeatherChannel verwendet habe ich mir TWC mal genauer angeschaut:
- Die amerikanische Seite ist genauso schwer auslesbar,…
- die deutsche Unterseite hingegen scheint etwas hinterher zu sein (Tabellenlayout…)
…und bot mir die ideale Möglichkeit für eine provisorische Lösung:
#wget verwenden, w3m -dump schlechte Idee, w3m -dump_source funtzt nicht TWC_TMP="/tmp/weather_twc_tmp" wget "http://de.weather.com/weather/local/77746?x=0&y=0" -O $TWC_TMP > /dev/null 2>&1 #Dewpoint cat $TWC_TMP | grep -A2 Taupunkt | tail -n 1 | cut -d '>' -f 2 | cut -d'&' -f1 #Humidity cat $TWC_TMP | grep -A2 Luftfeuchtigkeit | tail -n 1 | cut -d '>' -f 2 | cut -d'%' -f1 #Temperature cat $TWC_TMP | grep '<TD COLSPAN="2"' | head -n 1 | cut -d ';' -f 2 | cut -d '&' -f 1
Mehr als eine provisorische Lösung ist das aber nicht. Sobald die Seite relaunched wird (bei dem Layout wohl bald) oder gewisse Dinge verändert werden, hocke ich vor dem gleichen Problem. Ich hasse es von externen Anbietern abhängig sein zu müssen.
Richtige APIs
Längerfristig muss man folglich auf APIs zurückgreifen. Hier existieren zwei erwähnenswerte:
TheWeatherChannel bietet ebenfalls eine API an - allerdings nicht kostenlos. Wenn du weitere oder bessere Wetter APIs kennst, würde ich mich über einen Kommentar freuen.
YAHOO! Weather API
Die YAHOO API ist aber ähnlich unbrauchbar wie der Webdienst. Es fehlen wieder Taupunkt und rel. Luftfeuchtigkeit. Ist aber einfacher auslesbar als der Webdienst. Die URL setzt sich wie folgt zusammen:
http://weather.yahooapis.com/forecastrss?w=[Ortsid]&u=[Einheit (hier °C, also c]
Die Ortsid lässt sich aus der URL des Webservices bestimmen. Dazu muss man hier nach dem passenden Ort suchen. Anschließend kann man aus der URL die ID auslesen - Beispiel (ID hier: 693419):
http://weather.yahoo.com/germany/baden-wurttemberg/schutterwald-693419/
Nun kann man sich die URL „zusammenbauen“ (Fortführung vorheriges Beispiel):
http://weather.yahooapis.com/forecastrss?w=693419&u=c
Google Wetter API
In der API von Google findet auch die rel. Luftfeuchtigkeit. Der Taupunkt fehlt aber ebenfalls. Die URL setzt sich wie folgt zusammen:
http://www.google.com/ig/api?weather=[PLZ]&hl=[Sprache]
Folglich müsste ich diese URL verwenden:
http://www.google.com/ig/api?weather=77746&hl=de
Das Auslesen dürfte überhaupt kein Problem darstellen.
2012-04-26 // Neue Hardware – Intel Pentium G630T & Co
Zurzeit arbeite ich an einem neuen System für Hosting/Virtualisierung – die alte Hardware reicht einfach nicht mehr aus. Dazu habe ich mich zu folgender Hardware entschieden:
- Intel Pentium G630T 2x 2.3 GHz (nur 32W TDP)
- Alpenföhn Civetta (als Ersatz für den Intel Boxed-Kühler)
- Netgear GA311 (zweites Netzwerkinterface)
Insgesamt ein relativ preiswertes und sparsames System, dass aber über genügend Ressourcen für rechenintensive Applikationen verfügt. Wie es damit weiter geht und welche Erfahrungen ich mit dieser Hardware sammeln werde, wirst du bald auf mein.homelinux.com erfahren. Zusammengebaut sieht das Ganze so aus:
2012-04-10 // Weather.chrisge.org – Die Software III/III: Munin & Fazit
Nachdem ich das Projekt Weather.chrisge.org bereits in Grundzügen erläutert habe und die verwendete Hardware ebenfalls vorgestellt habe, werde ich in diesem Beitrag auf die Softwarekonfiguration eingehen. Da der gesamte Entwicklungsprozess mehrere Monate in Anspruch nahm, werde ich nur auf die wichtigsten Dinge eingehen. Zu einem späteren Zeitpunkt werde ich gegebenenfalls eine Dokumentation im mein.homelinux.com Wiki erstellt. Falls Fragen auftauchen sollten: melden!
Dieser Beitrag ist Teil der Serie Weather.chrisge.org:
- Teil 2: Weather.chrisge.org – Die Hardware → dieser Teil
- Teil 3: Die Software
- I: Motion → Webcam
- II: OWFS → 1-Wire
- III: Munin & Fazit → Graphen → dieser Teil
Diese Anleitung dürfte mit Debian-basierende Linux-Distributionen (z.B. Ubuntu) kompatibel sein. Die Munin Plugins müssten aber auf jeder Linux Plattform funktionsfähig sein. Ich habe sie bis jetzt aber nur mit Debian Squeeze getestet.
Graphen: Munin
Die Graphen erzeuge ich mit Munin. Der Vorteil ist, dass ich die Graphen auf einem anderen System rendern kann, also die Wetterstation ein sehr leistungsschwaches System (nur Munin-Node) sein kann, während das andere System (Munin) die Daten graphed und präsentiert, wofür mehr Leistung erforderlich ist. Zu Munin habe ich bereits eine Anleitung geschrieben:
Darin wird die Architektur von Munin (Munin u. Munin-Node) sowie die Installation und die Einrichtung näher erläutert. Diese Anleitung ist absolute Basis für diese Anleitung. Munin muss bereits voll einsatzfähig und konfiguriert sein.
Plugins
Da kein Plugin finden konnte, dass meinen erwünschten Zweck erfüllt, musste ich selbst drei Munin-Plugins schreiben. Wie dies geht, wird im Munin Wiki beschrieben.
Die Plugins werden in /usr/share/munin/plugins/ gespeichert und anschließend nach /etc/munin/plugins verlinkt:
$ sudo ln -s /usr/share/munin/plugins/PLUGIN /etc/munin/plugins/ $ sudo /etc/munin/munin-node restart #Munin-Node neustarten
Meine Plugins holen jew. noch die Daten von YAHOO! Weather und legen eine Statusdatei an, die immer den zuletzt ausgelesenen Wert anzeigen. Der Code ist nicht wirklich gesäubert und muss, wenn die Plugins verwendet werden sollen noch angepasst werden! Sie sollen nur Beispiele sein!
Folgendes muss angepasst werden:
- Der Pfad zum Sensor
- Das Statfile
- Die URL zum YAHOO! Weather Wetterbericht
Luftfeuchtigkeit
- humidity
#!/bin/sh # Simple OWFS Humidity Munin Plugin # Copyright: (C) 2012 Christoph Winkler <cw[at]chrisge[dot]org> # Web: http://www.chrisge.org / http://weather.chrisge.org # License: GPL-3 <http://www.gnu.org/licenses/gpl-3.0.txt> if [ "$1" = "config" ]; then echo 'graph_title Humidity (Luftfeuchtigkeit)' echo 'graph_args --rigid' echo 'graph_vlabel Relative Humidity in %' echo 'graph_scale no' echo 'graph_category Weather' echo 'screen0.label Local Relative Humidity' echo 'real0.label Adapted from YAHOO! Weather' echo 'real0.draw LINE1' exit 0 fi TWC_TMP="/tmp/weather_twc_tmp" wget "http://de.weather.com/weather/local/77746?x=0&y=0" -O $TWC_TMP > /dev/null 2>&1 REAL=$(cat $TWC_TMP | grep -A2 Luftfeuchtigkeit | tail -n 1 | cut -d '>' -f 2 | cut -d'%' -f1) STATE_R="/tmp/humidity_r" echo $REAL > $STATE_R BASE="/media/owfs" SENSOR_0="26.E67023010000" STATE_0="/tmp/humidity_0" if test -d ${BASE}/$SENSOR_0 then SCREEN_0=$(cat ${BASE}/$SENSOR_0/humidity ; echo) echo $SCREEN_0 > $STATE_0 echo screen0.value $SCREEN_0 fi echo real0.value $REAL
Temperatur
- temperature
#!/bin/sh # Simple OWFS Temperature Munin Plugin # Copyright: (C) 2012 Christoph Winkler <cw[at]chrisge[dot]org> # Web: http://www.chrisge.org / http://weather.chrisge.org # License: GPL-3 <http://www.gnu.org/licenses/gpl-3.0.txt> if [ "$1" = "config" ]; then echo 'graph_title Temperatures (Temperaturen)' echo 'graph_args --base 1000' echo 'graph_vlabel Temperature in Celsius' echo 'graph_category Weather' echo 'graph_scale no' echo "screen0.label Outdoor Sensor one" echo "screen1.label Outdoor Sensor two" echo "case0.label Outdoor in Sun" echo "real0.label Adapted from YAHOO! Weather" echo 'real0.draw LINE1' exit 0 fi BASE="/media/owfs" SENSOR_0="26.E67023010000" SENSOR_1="28.75798C020000" SENSOR_2="28.4F523C020000" STATE_0="/tmp/temperature_scr_0" STATE_1="/tmp/temperature_scr_1" STATE_2="/tmp/temperature_cas_0" TWC_TMP="/tmp/weather_twc_tmp" wget "http://de.weather.com/weather/local/77746?x=0&y=0" -O $TWC_TMP > /dev/null 2>&1 REAL=$(cat $TWC_TMP | grep '<TD COLSPAN="2"' | head -n 1 | cut -d ';' -f 2 | cut -d '&' -f 1) STATE_R="/tmp/temperature_r" echo $REAL > $STATE_R if test -d ${BASE}/$SENSOR_0 then SCREEN_0=$(cat ${BASE}/$SENSOR_0/temperature ; echo) echo $SCREEN_0 > $STATE_0 echo screen0.value $SCREEN_0 fi if test -d ${BASE}/$SENSOR_1 then SCREEN_1=$(cat ${BASE}/$SENSOR_1/temperature ; echo) echo $SCREEN_1 > $STATE_1 echo screen1.value $SCREEN_1 fi if test -d ${BASE}/$SENSOR_2 then CASE_0=$(cat ${BASE}/$SENSOR_2/temperature ; echo) echo $CASE_0 > $STATE_2 echo case0.value $CASE_0 fi echo real0.value $REAL
Dewpoint
Der Dewpoint → Taupunkt kann aus der relativen Luftfeuchtigkeit sowie der Temperatur errechnet werden. Mein Plugin bassiert auf diesem Skript und benötigt unbedingt das Paket bc.
- dewpoint
#!/bin/sh # Simple OWFS Humidity Munin Plugin # Copyright: (C) 2012 Christoph Winkler <cw[at]chrisge[dot]org> # Web: http://www.chrisge.org / http://weather.chrisge.org # License: GPL-3 <http://www.gnu.org/licenses/gpl-3.0.txt> # Based On: http://www.lawbiz.ch/d/spahni/programs/relhumidity.html if [ "$1" = "config" ]; then echo 'graph_title Dewpoint (Taupunkt)' echo 'graph_args --base 1000' echo 'graph_vlabel Dewpoint in Celsius' echo 'graph_category Weather' echo 'graph_scale no' echo "screen0.label Local Dewpoint" echo "real0.label Adapted from YAHOO! Weather" echo 'real0.draw LINE1' exit 0 fi BASE="/media/owfs" SENSOR_0="26.E67023010000" STATE_0="/tmp/dewpoint_0" TEMPERATURE="$(cat ${BASE}/$SENSOR_0/temperature ; echo)" HUMIDITY="$(cat ${BASE}/$SENSOR_0/humidity ; echo)" TWC_TMP="/tmp/weather_twc_tmp" wget "http://de.weather.com/weather/local/77746?x=0&y=0" -O $TWC_TMP > /dev/null 2>&1 REAL=$(cat $TWC_TMP | grep -A2 Taupunkt | tail -n 1 | cut -d '>' -f 2 | cut -d'&' -f1) STATE_R="/tmp/dewpoint_r" echo $REAL > $STATE_R if test -d ${BASE}/$SENSOR_0 then SCREEN_0=$(echo "define pa (n) { if (n >= 0.0) { return (7.5); } else { return (7.6); } } define pb (n) { if (n >= 0.0) { return (237.3); } else { return (240.7); } } define sdd (t) { return (6.1078 * e( l(10) * ((pa(t) * t) / (pb(t) + t)) ) ); } define dd (r,t) { return (r / 100.0 * sdd(t)); } /* factor 2.302585093 converts ln() to log() */ v = l(dd($HUMIDITY,$TEMPERATURE) / 6.1078) / 2.302585093; tp = ((pb($TEMPERATURE) * v) / (pa($TEMPERATURE) - v)); if ( tp >= 0.0 ) { tp = (tp + 0.05); } else { tp = (tp - 0.05); } scale = 4; (tp / 1.0); " | bc -l) if [ "$(echo $SCREEN_0 | head -c 1)" = "." ] ; then SCREEN_0=0${SCREEN_0} elif [ "$(echo $SCREEN_0 | head -c 2)" = "-." ] ; then SCREEN_0=-0${SCREEN_0#-} fi echo $SCREEN_0 > $STATE_0 echo screen0.value $SCREEN_0 fi echo real0.value $REAL
Fazit & Ausblick
Inspiriert wurde ich durch Dave's & Max's Weather-Station/Cam von der ich damals in Doozan's Forum erfahren habe. Das ganze Projekt war eine einzige große Bastelei. Ich hatte zu keinem einzigen Baustein eine vollständige Dokumentation. Letzten Endes habe ich nach einigem Herumprobieren dann doch immer eine Lösung gefunden. Unter anderem deshalb habe ich das Grundgerüst für andere Bastler dokumentiert. Wenn dir Angaben fehlen oder etwas unklar erscheint, stehe ich dir gerne zur Verfügung.
Es ist immer wieder erstaunlich zu sehen, was man mit kleiner Embedded ARM-Hardware so alles hin bekommt. Als nächstes werde ich den 1-Wire Bus durch weitere Sensoren erweitern und ggf. das System in ein wetterfestes Gehäuse draußen platzieren - im Moment steht es noch drinnen. In diesem Zusammenhang warte ich auf den Raspberry Pi, der für eine Wetterstation wirklich genial ist.
Probleme
Das größte Problem ist, dass der USB-Hub in unregelmäßigen Abständen resetet wird und der 1-Wire Adapter dann nicht mehr als ttyUSB0 sondern ttyUSB1 angemeldet wird. OWFS verliert dann den Bus, bis der Adapter abgesteckt und erneut angeschlossen wird (erscheint wieder las ttyUSB0).
Manchmal verliert Motion bei diesem Vorfall die Webcam, beendet sich und muss anschließend wieder gestartet werden.
2012-04-10 // Weather.chrisge.org – Die Software II/III: OWFS
Nachdem ich das Projekt Weather.chrisge.org bereits in Grundzügen erläutert habe und die verwendete Hardware ebenfalls vorgestellt habe, werde ich in diesem Beitrag auf die Softwarekonfiguration eingehen. Da der gesamte Entwicklungsprozess mehrere Monate in Anspruch nahm, werde ich nur auf die wichtigsten Dinge eingehen. Zu einem späteren Zeitpunkt werde ich gegebenenfalls eine Dokumentation im mein.homelinux.com Wiki erstellt. Falls Fragen auftauchen sollten: melden!
Dieser Beitrag ist Teil der Serie Weather.chrisge.org:
- Teil 2: Weather.chrisge.org – Die Hardware → dieser Teil
- Teil 3: Die Software
- I: Motion → Webcam
- II: OWFS → 1-Wire → dieser Teil
- III: Munin & Fazit → Graphen
Dieser Post ist bezüglich OWFS Verwendung (nicht Installation) nur für die in den obigen Beiträgen vorgestellte 1-Wire Hardware gültig, kann aber problemlos auf andere übertragen werden. Kompatible Betriebssysteme sollten Debian-basierende Linux-Distributionen (z.B. Ubuntu) sein. Ich habe sie bis jetzt aber nur mit Debian Squeeze getestet.
1-Wire: OWFS
Um die Werte der Sensoren auszulesen verwende ich, wie bereits erwähnt OWFS. Da OWFS nicht in den Paketquellen vorhanden ist, muss es manuell komplimiert werden. Dazu findet sich hier eine detaillierte Anleitung.
Vorbereitungen
Zuerst müssen diverse Kernelmodule deaktiviert werden:
$ sudo modprobe -r ds9490r $ sudo modprobe -r ds2490 $ sudo modprobe -r wire
…und anschließend in die /etc/modprobe.d/blacklist eingetragen werden:
# OWFS via libusb blacklist ds9490r blacklist ds2490 blacklist wire
Nun werden die für das Komplimieren benötigten Pakete installiert:
$ sudo apt-get install build-essential automake autoconf autotools-dev gcc g++ libtool fuse-utils libfuse-dev swig python2.5-dev tcl8.4-dev php5-dev
Komplimieren
Folgendes muss manuell komplimiert werden:
libusb
Hier ist es wichtig darauf zu achten, dass man libusb-0.1 (LEGACY) verwendet und in jenem Unterverzeichnis die aktuellst Version bezieht. Zur Zeit dieses Posts wäre dies diese URL:
http://sourceforge.net/projects/libusb/files/libusb-0.1%20%28LEGACY%29/0.1.12/libusb-0.1.12.tar.gz/download
libusb lade ich mit wget wie folgt herunter (wer lieber seinen Browser verwendet, kann gerne jenen verwenden und die Datei nachher an den richtigen Ort verschieben):
$ wget http://sourceforge.net/projects/libusb/files/libusb-0.1%20%28LEGACY%29/0.1.12/libusb-0.1.12.tar.gz/download -O libusb.tar.gz $ tar xvzf libusb.tar.gz $ cd libusb-0.1.12/
Nun komplimieren wir libusb:
libusb-0.1.12$ make libusb-0.1.12$ sudo make install
Folgender Befehl (hier hat die verlinkte Anleitung einen Fehler):
$ libusb-config --version
…sollte 0.1.12 ausgeben.
OWFS
Zuerst besorgt man sich die aktuellste Version von OWFS auf sourceforge.net. In diesem Fall (Stand: Apr. 2012) lautet die URL wie folgt:
http://sourceforge.net/projects/owfs/files/latest/download?source=files
OWFS wird nun wie folgt heruntergeladen (Browser: siehe libusb:
$ wget http://sourceforge.net/projects/owfs/files/latest/download?source=files -O owfs.tar.gz
Nun entpacken wir das Paket:
$ tar xvzf owfs.tar.gz $ cd owfs-2.8p14/
…anschließend kann der Build beginnen:
owfs-2.8p14$ ./configure --enable-debian owfs-2.8p14$ make owfs-2.8p14$ sudo make install
Erster Start
Wer OWFS ohne root-Rechte verwenden will, muss wie in der verlinkten Anleitung beschrieben noch etwas Hand an udev anlegen. Wer auf Nummer sicher gehen will, sollte diesen zusätzlichen Schritt durchführen. Dann könnte OWFS sowie OWSERVER ohne root-Rechte gestartet werden.
Ansonsten kann der 1-Wire Adapter (in meinem Fall der LinkUSB) mit dem fertigen 1-Wire Netz an den Rechner gehängt werden. Da jener Adapter über einen Seriellen Converter verfügt, müssten die benötigten Kernel Module normalerweise automatisch nachgeladen werden. Dies kann anhand der Ausgabe von dmesg | grep usb oder dem Syslog überprüft werden. Dort sollte folgende Meldung erscheinen:
[ 5996.029323] usb 1-1.2.4: new full speed USB device using orion-ehci and address 83 [ 5996.166193] usb 1-1.2.4: New USB device found, idVendor=0403, idProduct=6001 [ 5996.173435] usb 1-1.2.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 5996.181097] usb 1-1.2.4: Product: FT232R USB UART [ 5996.185945] usb 1-1.2.4: Manufacturer: FTDI [ 5996.190237] usb 1-1.2.4: SerialNumber: A900fxuD [ 5996.205792] usb 1-1.2.4: configuration #1 chosen from 1 choice [ 5996.227183] usb 1-1.2.4: Detected FT232RL [ 5996.231342] usb 1-1.2.4: Number of endpoints 2 [ 5996.235939] usb 1-1.2.4: Endpoint 1 MaxPacketSize 64 [ 5996.241057] usb 1-1.2.4: Endpoint 2 MaxPacketSize 64 [ 5996.246139] usb 1-1.2.4: Setting MaxPacketSize 64 [ 5996.252885] usb 1-1.2.4: FTDI USB Serial Device converter now attached to ttyUSB0
Sollte dies nicht der Fall sein, kann die Installation des Paketes libftdi1 helfen.
Aus der letzten Zeile geht hervor, dass der Adapter über /dev/ttyUSB0 angesprochen werden kann. OWFS (genauer gesagt OWSERVER) wird nun so gestartet:
$ sudo /opt/owfs/bin/owserver -p 4304 -d /dev/ttyUSB0 -t 30 --link --error_level 9
Aus einem mir bis jetzt unbekannten Grund, ist der Bus direkt nach dem Start nicht benutzbar. Ich warte normalerweise 5-10 Minuten und starte erst dann OWFS und binde damit den Bus als „Dateisystem“ ein:
$ sudo mkdir /media/owfs #Anlegen des Mountpoints
$ sudo /opt/owfs/bin/owfs -s localhost:4304 --allow_other /media/owfs
Sollte das mit einer Fehlermeldung enden, dass kein 1-Wire Bus gefunden werden konnte, wartet man am besten einfach noch mal ein paar Minuten. Diese Unberechenbarkeit ist der Grund, dass ich kein Startskript einsetze, sondern OWFS immer per Hand starte. Das Problem liegt wahrscheinlich an der verwendeten Hardwarekonfiguration (Dockstar, USB-Hub und LinUSB) - mit einer anderen, könnte es ohne Probleme funktionieren.
Zusätzlich starte ich noch OWHTTPD:
$ /opt/owfs/bin/owhttpd -p 4305 -s localhost:4304
….und rufe nun die URL
http://host:4305
auf, die ein Listing des Buses anzeigt. Hier kann ich auch die Werte der Sensoren auslesen.
Werte auslesen
In obigem Beispiel wurde der Bus in /media/owfs gemountet. Folgendes befindet sich nun in dem Verzeichnis:
$ ls /media/owfs/ 26.E67023010000 28.4F523C020000 28.75798C020000 alarm bus.0 settings simultaneous statistics structure system uncached
Die ZAHL.BLABLA benannten Verzeichnisse sind die IDs der Sensoren, in dem Verzeichnis befinden sich dann die Werte:
$ ls /media/owfs/26.E67023010000/ address B1-R1-A crc8 disconnect endcharge HIH3600 HTM1735 IAD locator offset r_address r_locator temperature udate VDD alias CA date EE family HIH4000 humidity id MultiSensor pages r_id S3-R1-A type VAD vis
Der obige Sensor ist ein MS-TH, d.h. er verfügt über Temperatur und Luftfeuchtigkeit:
$ cat /media/owfs/26.E67023010000/humidity ; echo 41.4725 $ cat /media/owfs/26.E67023010000/temperature ; echo 7.5625
So kann man mit cat ganz einfach die Werte auslesen. Die Verwendung in Skripten ist somit wirklich einfach.


















