Intro

In diesem Artikel geht es um den Aufbau einer Wetterstation am Modellflugplatz. Die Station besteht aus einer handelsüblichen Wetterstation vom Typ WH 1080, welche unter verschiedene Markennahmen und Typbezeichnungen im Handel zu bekommen ist. Diese bietet die Erfassung von Temperatur (aussen und innen), Luftdruck (absolut und relativ), Luftfeuchte (relativ), Windrichtung, Windgeschwindigkeit und Regenmenge. Über eine USB Schnittstelle an der Zentraleinheit lassen sich die gemessenen Werte auslesen und weiter verarbeiten.

Das Auslesen, Verarbeiten und Darstellung der gemessenen Werte übernimmt ein Raspberry Pi zusammen mit pywws. Mit Apache auf dem Raspberry werden die Daten für den Webrowser abrufbar dargestellt. Dazu werden noch die Java Script Bibliotheken "SteelSeries Gauges" und "Highcharts" eingesetzt. Mit den "Steel Series Gauges" werden die aktuellen Werte dargestellt. Für die Stunden- und Tagesverläufe eignet sich "Highcharts" am Besten. Über einen UMTS-Router lassen sich die Daten der Wetterstation dann im Internet abrufen.

Grundinstallation Raspberry Pi

Nachdem der Raspberry Pi angekommen und ausgepackt ist, muss erst einmal das Betriebssystem auf eine SD-Karte gespielt werden. Diese muss mindestens 4 GB groß sein. Sollen möglichst viele Wetterdaten auf der Karte vorgehalten werden, ist es natürlich ratsam, eine größere Karte zu nehmen. Da der Preisunterschied zwischen 4 GB und 8 GB nicht wesentlich ist, verwende ich eine 8 GB Karte.

Grundinstallation Schritt 1:

Zuerst wird die SD Karte noch einmal formatiert. Dazu wird das kostenlose Tool SD Formatter V4.0 eingesetzt. Dieses lässt sich von folgender Quelle herunterladen:
https://www.sdcard.org/downloads/formatter_4/

Grundinstallation Schritt 2:

Als nächstes wird das Betriebssstem NOOBS von der Raspberry Pi Support Seite heruntergeladen. Die ZIP-Datei ist unter folgender Adresse zu finden:
http://www.raspberrypi.org/downloads

Für meine Installation nutze ich die zu diesem Zeitpunkt aktuelle Version NOOBS_V1.4.1.zip. Diese wird nach dem Herunterladen entpackt. Danach wird dann der entpackte Inhalt in das Hauptverzeichnis der SD-Karte kopiert.

Grundinstallation Schritt 3:

Jetzt ist es Zeit die mit dem Raspberry Betriebssystem versehene SD-Karte in den Raspberry einzusetzten. Als nächstes werden noch ein Monitor (bzw. auch LCD Fernseher) per HDMI und eine Tastatur/Maus über USB angeschlossen. Die Stromversorgung erfolgt dann mittels eines Smartphone Netzteils und Smartphone Ladekabel (Micro USB).

Nachdem die Stromversorgung angeschlossen ist, sollte sich der Raspberry langsam melden und sich für die initiale Installation vorbereiten.

Einrichtung neuer User:

Falls die Wetterstation aus dem Internet erreichbar sein soll, empfielt es sich vor den weiteren Arbeiten 2 neue Nutzer anzulegen. Der erste soll ein administrativer Account sein, so wie es der Standard User "pi" darstellt. Der zweite wird als einfacher Nutzer erstellt, unter dessem Account nachher die pywws Anwendung läuft.

Zuerst kommt der neue Admin (Ersatz für den allseits bekannten 'pi'). Hier sollte natürlich jeder etwas Phantasie walten lassen und einen eigenen Namen dafür wählen. Der hier genutzte "myadmin" ist also stellvertretend für einen eigenen User zu sehen.

sudo adduser -shell /bin/bash -home /home/myadmin myadmin

Jetzt kommen die Ausgaben von adduser. Es wird auch gleich nach einem Passwort für den neuen Nutzer gefragt.

Adding user `myadmin' ...

Adding new group `myadmin' (1002) ...
Adding new user `myadmin' (1001) with group `myadmin' ...
Creating home directory `/home/myadmin' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for myadmin
Enter the new value, or press ENTER for the default
        Full Name []:
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [Y/n] Y

Nachdem der User angelegt ist, müssen ihm die gleichen Gruppen zugeordnet werden, wie sie auf dem Nutzer 'pi' zugeordnet sind:

sudo addgroup myadmin adm
sudo addgroup myadmin sudo
sudo addgroup myadmin audio
sudo addgroup myadmin video
sudo addgroup myadmin plugdev
sudo addgroup myadmin games
sudo addgroup myadmin users
sudo addgroup myadmin netdev
sudo addgroup myadmin input

Als nächstes wird der Account angelegt, unter welchem später pywws automatisch laufen soll. Ebenso wie für "myadmin" ist der hier verwendete "mypywws" als Platzhalter zu sehen.

sudo adduser -shell /bin/bash -home /home/mypywws mypywws

Jetzt kommen wieder die Ausgaben und Abfragen, wie für den User 'myadmin'.

Anschließend noch dem "normalen" Nutzer die Gruppen zuordnen.

sudo addgroup mypywws plugdev
sudo addgroup mypywws users
sudo addgroup mypywws input

Als nächstes wird eine eigene Gruppe für die Wetteranwendung erstellt:

sudo groupadd weather

 Jetzt werden noch die beiden neuen Nutzer auch dieser Gruppe zugeordnet:

sudo adduser myadmin weather
sudo adduser mypywws weather

Jetzt wird dem myadmin noch beigebogen, dass er sudo ohne Passworteingabe nutzen kann:

sudo vi /etc/sudoers

Am einfachsten ist es, den letzten Eintrag für den Standarduser 'pi' auf den neuen User 'myadmin' umzubiegen:

Von:

# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.d
pi ALL=(ALL) NOPASSWD: ALL

 Nach:

# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.d
myadmin ALL=(ALL) NOPASSWD: ALL

Jetzt sollte geprüft werden, ob beide User richtig eingerichtet sind. Dementsprechend ist es an der Zeit sich einmal mit beiden Usern anzumelden. Falls dies geht und  auch "sudo" für den User "myadmin" funktioniert, kann der User "pi" erst einmal gesperrt werden. Dazu erst einmal als User "myadmin" anmelden und dann folgenden Befehl eingeben:

sudo passwd -l pi

ACHTUNG: Diesen Schritt nur ausführen, wenn auch sicher ist, dass "myadmin" über "sudo" Root-Rechte bekommen kann!

Ansonsten geht es wieder zurück auf Los! und die SD Karte muss noch einmal neu eingerichtet werden.

 

Installation von pywws:

Installation der benötigten Libraries:

Bevor pywws installiert werden kann, müssen einige Pakete auf dem Raspberry Pi installiert werden. Dazu einfach folgende Kommandos ausführen:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install git
sudo apt-get install python-dev
sudo apt-get install libudev-dev

Nun muss der Source Code für libusb heruntergeladen, kompiliert und installiert werden:

mkdir ~/src
cd ~/src
wget http://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-1.0.9/libusb-1.0.9.tar.bz2
tar xvjf libusb-1.0.9.tar.bz2
cd ~/src/libusb-1.0.9
./configure
make
sudo make install

Im nächsten Schritt wird Cyton installiert:

cd ~/src
wget http://pypi.python.org/packages/source/C/Cython/Cython-0.22.1.tar.gz
tar xvzf Cython-0.22.1.tar.gz
cd ~/src/Cython-0.22.1
sudo python setup.py install

Während das letzte Kommando läuft, ist genügend Zeit gemütlich zum Abendessen zu gehen, da die Ausführung über eine Stunde dauert.

###########################################################

Update Juli 2015: Diesen Schritt bitte überspringen und stattdessen 'pyusb' installieren (siehe weiter unten)!

Als nächstes wird die cython-hidapi installiert (hid = human interface device):

cd ~/src
git clone https://github.com/gbishop/cython-hidapi.git

Im Setupscript muss jetzt allerdings noch der Pfad zu libusb berichtigt werden:

cd ~/src/cython-hidapi
vi setup.py

In der Datei muss folgende Zeile geändert werden von

os.environ['CFLAGS'] = "-I/usr/include/libusb-1.0"

zu:

os.environ['CFLAGS'] = "-I/usr/local/include/libusb-1.0"

Jetzt noch die Library installieren:

sudo python setup.py install

Ende Update Juli 2015
###########################################################

Als nächstes wird pip installiert. Damit lässt sich ähnlich wie mit apt-get das aktuelle Package von pywws installieren:

sudo apt-get install python-pip

Nachdem python-pip installiert ist, kann jetzt auch die Python USB Library installiert werden.

pip install pyusb --pre

Installation von pywws und erster Funktionstest

sudo pip install pywws

Nachdem das Paket pywws erfolgreich installiert wurde und die Zentraleinheit über USB angeschlossen ist, kann mit folgendem Befehl geprüft werden, ob die Verbindung funktioniert:

sudo python -m pywws.TestWeatherStation

Es sollte dann eine Ausgabe erscheinen, die in etwa so aussieht:

0000 55 aa ff ff 3f 1d ff ff ff 82 2d 00 40 ff ff ff 01 20 02 21 09 00 00 00 00 7f 00 f0 0f 00 80 bf
0020 97 27 42 1d 00 00 00 00 00 00 00 13 09 12 22 45 41 23 c8 00 00 00 46 2d 2c 01 65 80 c8 00 00 00
0040 64 00 64 80 a0 28 80 25 a0 28 80 25 00 b4 00 00 68 01 00 0a 00 f4 01 12 00 00 00 00 00 00 00 00
0060 00 00 40 1f 5e 12 13 01 aa 00 7d 01 72 00 7d 01 72 00 ad 00 35 00 ab 1d f2 1c 2c 28 5b 27 55 00
0080 c0 02 f4 ff fd ff fd ff fd ff ba 03 00 13 09 08 10 17 13 08 22 16 25 13 09 04 06 17 13 08 22 15
00a0 07 13 08 22 18 09 13 09 11 08 41 13 09 07 10 43 13 08 22 06 31 13 09 07 10 43 13 08 22 06 31 13
00c0 09 07 10 22 13 08 22 15 07 13 08 20 22 03 13 08 25 14 52 13 08 21 00 13 13 09 12 05 10 13 08 27
00e0 15 36 13 09 07 10 15 13 09 07 10 22 13 09 07 10 22 13 09 07 10 22 13 09 07 10 22 13 08 28 09 40

Weitere Konfigurationsschritte

Sollen die Wetterdaten möglichst zeitnah in der Zentraleinheit gelogged werden (Minimum ist 1 Minute) und dementsprechend auch von pywws ausgelesen werden, dann lässt sich das Speicherintervall mit folgendem Befehl auf 1 Minute einstellen:

sudo python -m pywws.SetWeatherStation -r 1

Wenn die Wetterstation erst kurz in Betrieb ist, dann kann es sein, dass der DCF Empfänger die Zeit noch nicht synchronisiert hat. Mit dem folgenden Befehl kann man versuchen, die Zeit mit dem Raspberry abzugleichen:

sudo python -m pywws.SetWeatherStation -c

Anscheinend funktioniert das wohl nicht mit allen Wetterstationen, ansonsten wäre die folgende Ausgabe nicht zu erklären:

13:45:19:pywws.Logger:pywws version 15.07.0
Clock setting is not known to work on any model of weather station.
If it works for you, please let Jim Easterbrook know.
waiting for exact minute

Nachdem die Verbindung zur Wetterstation erfolgreich getestet wurde und das Speicherintervall in der Station eingestellt wurde, können die nächsten Schritte für das automatische Auslesen und Verarbeiten der Daten durchgeführt werden.

 

Zuerst wird im Home Verzeichnis des Users unter dessen Account später pywws (hier "mypywws") laufen soll ein Unterverzeichnis erstellt.

Damit später für eine eventuelle Datensicherung alles kompakt beianander liegt sollen in dem Unterverzeichnis folgende Dine landen:

  • die Konfigurationsdatei für die Verarbeitung der Daten
  • die aus der Wetterstation ausgelesenen Daten
  • die von pywws verarbeiteten Daten (stündlich, täglich, monatilche Summen)
  • die Templates für die Ausgabe der Daten

Dazu zuerst in den Benutzer wechseln unter welchem später pywws laufen soll (hier "mypywws"):

su - mypywws
cd ~
mkdir weather_data
cd weather_data/
mkdir templates
mkdir log
mkdir tmp
mkdir results
exit

Jetzt sind wir wieder im Userkontext von "myadmin". Mit dem folgenden Befehl wird pywws das erste mal gestartet. Dabei legt pywws im Datenverzeichnis die Konfigurationsdateien an:

sudo python -m pywws.LiveLog -vvv /home/mypywws/weather_data

Nachdem pywws kurz gelaufen ist (nur ca. 10 - 20 Sekunden) wird es mit CTRL-C wieder gestoppt.

Im Verzeichnis /home/mypywws/weather_data sollten jetzt die Dateien status.ini und weather.ini liegen. Da pywws mit sudo gestartet wurde, gehören die beiden Dateien dem User root. Für's Erste ist das in Ordnung, das muss jedoch später noch korrigiert werden. Dies kann aber erst gemacht werden, wenn auch der User "mypywws" auf den USB Port zugreifen darf. Dies wird weiter unten noch beschrieben, Stichwort "UDEV".

Als nächstes werden die Templates aus dem Verzeichnis /usr/local/share/pywws/examples in das Datenverzeichnis kopiert:

sudo cp -r /usr/local/lib/python2.7/dist-packages/pywws/examples/templates /home/mypywws/weather_data

Jetzt muss die pywws Konfigurationsdatei weather.ini angepasst werden. In früheren Versionen von pywws wurde durch den ersten Start eine Beispieldatei angelegt, welche die wichtigsten Einträge schon hatte. Mit der aktuellen Version wird jedoch nur eine minimale Datei angelegt. D. h. jetzt muss erst einmal die Datei im Editor geöffnet werden.

cd ~/weather_data/
sudo vi weather.ini

Die Datei sieht erst einmal so aus:

[config]
ws type = Unknown
usb activity margin = 3.0
pressure offset = 263.7

Ok, das ist erst einmal etwas dünn, hier müssen noch etliche Einträge rein. Das sollte eigentlich so aussehen:

[config]
ws type = 1080
logdata sync = 1
day end hour = 0
rain day threshold = 0.2
template encoding = iso-8859-1
gnuplot encoding = iso_8859_1
language = en

[paths]
work = /home/mypywws/weather_data/tmp/
templates = /home/mypywws/weather_data/templates/templates/
graph_templates = /home/mypywws/weather_data/templates/graph_templates/
local_files = /home/mypywws/weather_data/results/

[live]
services = []
yowindow = 
twitter = []
plot = []
text = []

[logged]
services = []
yowindow = 
twitter = []
text = ['livedata.json', '3hrs.log']
plot = []

[hourly]
services = []
yowindow = 
twitter = []
text = ['24hrs.log', 'my_forecast.txt', 'my_forecast_icon.txt']
plot = []

[12 hourly]
services = []
yowindow = 
twitter = []
text = []
plot = []

[daily]
services = []
yowindow = 
twitter = []
text = []
plot = []

[ftp]
local site = True
secure = False
site = ftp.username.your_isp.co.uk
user = username
password = secret
directory = /var/www/weather/data/

[Zambretti]
north = True
baro upper = 1050.0
baro lower = 950.0

 

Konfiguration der Startumgebung

Nach der Installation hat nur der Root User zugriff auf das USB-Device für die Wetterstation. Damit aber "normale" Nutzer auch das Device ansprechen können, muss noch eine Regel für UDEV erstellt werden. Dazu wird im Verzeichnis  /etc/udev/rules.d/ eine neue Datei angelegt. In der Datei wird der Gruppe "weather" der Zugriff auf das Device erlaubt.

sudo vi /etc/udev/rules.d/38-weather-station.rules

 Diese bekommt folgenden Inhalt:

# WH-1080 Weather Station
ACTION!="add|change", GOTO="weather_station_end"
SUBSYSTEM=="usb", ATTRS{idVendor}=="1941", ATTRS{idProduct}=="8021", GROUP="weather"
LABEL="weather_station_end"

Nach dem Neustart des Raspberry Pi darf der User mypywws die pywws Software auch ohne vorangestelltes "sudo" starten (was er sowieso nicht könnte, da er nicht in der Gruppe sudo ist).

Jetzt muss der Raspberry erst mal neue gestartet werden:

sudo reboot

Bevor geprüft werden kann, ob der User "mypywws" jetzt auch Zugriff auf die Wetterstation hat, muss noch der Owner für die Daten im seinem Home-Verzeichnis geändert werden:

sudo chown -R mypywws:weather /home/mypywws/weather_data/

Nun erst mal wieder in den Kontext des User "mypywws" wechseln:

su - mypywws

Jetzt sollte sich pywws vom User "mypywws" auch ohne "sudo" starten lassen:

python -m pywws.LiveLog -vvv ~/weather_data/

Nachdem dies erfolgreich getestet wurde, kann auch der automatische Start von pywws eingerichtet werden. Dazu geht es erst einmal zurück in den Kontext von "myadmin" und dann wird das Start/Stop-Skript angelegt.

exit
sudo vi /etc/init.d/pywws

 Dann wird folgender Inhalt in die Datei geschrieben:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          pywws 
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:    2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: start/stop pywws weather logging
# Description:       Start/stop the python tool pywws to read an process weather station data 
#                   
### END INIT INFO
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
DESC="pywws LiveLog"
NAME=pywws-livelog.py
DAEMON=/usr/local/bin/$NAME
DAEMON_ARGS="-vv -l /home/mypywws/weather_data/log/livelog.txt /home/mypywws/weather_data/"
case "$1" in
  start)
        echo -n "Starting $DESC: "
        start-stop-daemon --start --chuid mypywws:weather --pidfile /var/run/$NAME.pid \
            --make-pidfile --background --startas $DAEMON -- $DAEMON_ARGS
        echo "$NAME."
        ;;
  stop)
        echo -n "Stopping $DESC: "
        start-stop-daemon --stop --quiet --oknodo \
	    --pidfile /var/run/$NAME.pid
        rm -f /var/run/$NAME.pid
        echo "$NAME."
        ;;
esac
:

Das Skript muss jetzt noch das Execute Flag bekommen, damit es auch ausgeführt werden kann. Weiterhin wird es noch in die Start/Stop-Sequenz des Raspberry aufgenommen werden.

sudo chmod a+x /etc/init.d/pywws
sudo update-rc.d pywws defaults

 

Installation von Apache 2 und PHP 5

Für die Darstellung der Wetterdaten wird jetzt Apache 2 und PHP 5 installiert:

sudo apt-get install apache2
sudo apt-get install php5

Wird im Browser die Adresse des Raspberry aufgerufen sollte folgender Text erscheinen:

It works!
This is the default web page for this server.
The web server software is running but no content has been added, yet.

Um zu prüfen, ob auch PHP funktioniert, wird im Verzeichnis /var/www wird die Datei phpinfo.php erstellt:

sudo vi /var/www/phpinfo.php
<?php
phpinfo();
?>

Wenn im Browser http://<raspberry-ip-adresse>/phpinfo.php aufgerufen wird, sollte eine Info Seite mit den PHP Einstellungen im Browser angezeigt werden.

Nach dem Test sollte die Datei gleich wieder gelöscht werden:

sudo rm /var/www/phpinfo.php

 Jetzt kann das Webverzeichnis für die Darstellung der Wetterdaten vorbereitet werden.

sudo su
cd /var/www
mkdir wdata
mkdir js
mkdir phpscript
mkdir css
chown -R mypywws:weather *

Falls der Raspberry die Wetterdaten im Internet direkt anzeigen soll, müssen noch ein paar Änderungen an der Konfiguration von Apache und PHP vorgenommen werden. Da die Konfigurationsdateien dem root User gehören, bleiben wir einfach im root Kontext (also kein "exit" nach den vorausgegangenen Kommandos).

cd /etc/apache2/
vi apache2.conf

 Fast am Ende der Datei wird die Zeile "Include conf.d/security" eingefügt. Die Datei sollte dann wie folgt aussehen (hier nur der letzte Ausschnitt):

# Include generic snippets of statements
Include conf.d/
Include conf.d/security
# Include the virtual host configurations:
Include sites-enabled/
# Security

Nach dem Speichern der apache2.conf Datei wird die Security Datei angepasst (diese befindet sich im Verzeichnis "/etc/apache2/conf.d/"):

cd conf.d
vi security

Zuerst wird die Zeile "Servertokens OS" durch voranstellen eines "#" auskommentiert und dann die Zeile  "ServerTokens Prod" eingefügt:

#
# ServerTokens
# This directive configures what you return as the Server HTTP response
# Header. The default is 'Full' which sends information about the OS-Type
# and compiled in modules.
# Set to one of:  Full | OS | Minimal | Minor | Major | Prod
# where Full conveys the most information, and Prod the least.
#
ServerTokens Prod 
#ServerTokens OS
#ServerTokens Full

Weiterhin wird "ServerSignature" auf "Off" umgestellt:

#
# Optionally add a line containing the server version and virtual host
# name to server-generated pages (internal error documents, FTP directory
# listings, mod_status and mod_info output etc., but not CGI generated
# documents or custom error documents).
# Set to "EMail" to also include a mailto: link to the ServerAdmin.
# Set to one of:  On | Off | EMail
#
ServerSignature Off
#ServerSignature On

Durch diese Einstellungen wird Apache angeweisen, keine Informationen zum Betriebssystem und der Apache Version im HTTP Header preiszugeben.

Vor der Änderung sieht der Header so aus:

HTTP/1.1 200 OK
Date: Sun, 15 Sep 2013 09:36:45 GMT
Server: Apache/2.2.22 (Debian)
X-Powered-By: PHP/5.4.4-14+deb7u4
Content-Length: 2146
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: image/gif

Wie zu sehen ist, verrät PHP auch noch etwas über seine Umgebung. Dazu muss jedoch die Datei php.ini geändert werden:

cd /etc/php5/apache2/
vi php.ini

Jetzt muss in der php.ini die Zeile  "expose_php = On" gesucht werden und der Wert auf "expose_php = Off" umgestellt werden:

; Decides whether PHP may expose the fact that it is installed on the server
; (e.g. by adding its signature to the Web server header).  It is no security
; threat in any way, but it makes it possible to determine whether you use PHP
; on your server or not.
; http://php.net/expose-php
expose_php = Off

Damit die geänderten Konfigurationsdaten angezogen werden, muss der Apache Server durchgestartet werden:

/etc/init.d/apache2 restart

Jetzt sollte der HTTP-Header so aussehen:

HTTP/1.1 200 OK
Date: Sun, 15 Sep 2013 09:48:02 GMT
Server: Apache
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 8367
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

Im Standard würde Apache den Inhalt eines Directories anzeigen, falls keine index.html Datei vorhanden ist. Das muss natürlich unterbunden werden, wenn der Raspberry aus dem Internet erreichbar sein soll. Daher wird im nächsten Schritt die Konfigurationsdatei für das default virtuelle Verzeichnis von Apache verändert.

cd /etc/apache2/sites-enabled/
vi 000-default

Der Inhalt der Datei sollte dann nach allen Änderungen so aussehen:

<VirtualHost *:80>
	ServerAdmin webmaster@localhost
	DirectoryIndex index.php index.html
	DocumentRoot /var/www
	<Directory />
		Options FollowSymLinks
		AllowOverride None
	</Directory>
	<Directory /var/www/>
		Options -Indexes FollowSymLinks MultiViews
		AllowOverride All
		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
	</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>

Eine gute Idee ist noch das Apache Module mod_rewrite zu aktivieren. Erst dann ist es möglich über .htaccess Dateien z. B. den Zugriff auf Dateien auf dem Server einzuschränken. Damit kann z. B. sichergestellt werden, dass die Rohdaten von pywws für die Darstellung nur über ein PHP-Script geliefert werden. Da PHP-Script läuft ja lokal auf dem Raspberry. Wenn dann z. B. nur für das Verzeichnis "wdata" der Zugriff auf "localhost" eingeschränkt wird, kann niemand die Daten direkt mit dem Browser aufrufen.

a2enmod rewrite
service apache2 restart

Hinweis zur Sicherheit im Internet

Ich möchte hier explizit darauf hinweisen, das die oben aufgeführten Schritte noch keine Garantie für ein 100% sicheres System sind!

Wer also plant seinen Raspberry im Internet bekannt zu machen und lange daran Freude haben will, der sollte noch einmal im Netz nach "rasbperry hardening", "apache hardening" oder ähnliche Suchkriterien suchen!

Auch würde ich den Raspberry nie direkt am Internet betreiben, sondern einen Internet Router mit mindestens NAT davor stellen. Besser wäre noch einer mit einer entsprechenden Firewall. Der Apache Webserver des Raspberry wird dann über ein Portforwarding im Router erreichbar gemacht.

Auch sollte über einen cron-Job dafür gesorgt werden, dass der Raspberry regelmäßig mit den neuesten Versionen der Pakete versorgt wird.

 

Bereitstellen der Daten aus pywws

Nach den vorausgegangen Schritten sollten die Voraussetzungen geschaffen sein, das

  • ein eigener Benutzer für pywws eingerichtet wurde
  • pywws die Verbindung mit der Wetterstation herstellen kann und die Daten ausliest
  • pywws unter dem eigens erstellen Nutzer (hier "mypywws") laufen kann
  • die Software automatisch gestartet wird, sobald der Raspberry Pi gestartet wird
  • ein Apache 2 Server mit PHP 5 läuft

Jetzt geht es daran, ein Template für pywws zu erstellen, welches die Daten zusammenstellt und anschließend als ASCII Datei im Verzeichnis "/var/www/wdata" ablegt.

Dazu ist es jetzt an der Zeit sich wieder als Benutzer "mypywws" anzumelden und dann wird geht es in das Verzeichnis für Templates.

exit
su - mypywws
cd weather_data/templates/templates/
vi 2hrs.log
#timezone local#
#roundtime True#
#raw#
#jump -119#
#loop 120#
#idx "%m.%d.%Y %H:%M"# #abs_pressure "%.1f" "1013"# #rel_pressure "%.1f" "1013"# #temp_out "%.1f" "0.0"# #hum_out "%.0f" "0.0"# #calc "apparent_temp(data['temp_out'], data['hum_out'], data['wind_ave'])" "%.1f" "0.0"# #calc "wind_chill(data['temp_out'], data['wind_ave'])" "%.1f" "0.0"# #calc "dew_point(data['temp_out'], data['hum_out'])" "%.1f" "0.0"# #wind_ave "%.1f" "0.0" "wind_kmph(x)"# #wind_gust "%.1f" "0.0" "wind_kmph(x)"# #wind_dir "%.0f" "0.0" "winddir_degrees(x)"# #wind_dir "%s" "-" "winddir_text(x)"# #calc "data['rain']-prevdata['rain']" "%0.1f" "0.0"#
#jump 1#
#endloop#

Hmm, was macht pywws anhand dieses Templates jetzt eigentlich?

#timezone local#  pywws speichert alle Zeiten in UTC. Mit diesem Kommando wird alles auf die lokale Zeitzone umgerechnet. 
#roundtime True#  
#raw# Hiermit wird pywws angewiesen, die Rohdaten auszulesen, also keine summierten Werte.

#jump -119#
#loop 120#

 

#jump 1#
#endloop# 
Hiermit wird eine Schleife über 120 Datensätze ausgeführt.

#idx "%m.%d.%Y %H:%M"#

Hiermit wird der Zeitstempel des Datensatzes im Format "M.D.YYYY hh:mm" ausgeben.
#abs_pressure "%.1f" "1013"# Hiermit wird der absolute Luftdruck ausgeben. Genauigkeit auf eine Nachkommastelle. Falls kein Messwert vorliegt, wird der Wert 1013 ausgeben.
#rel_pressure "%.1f" "1013"# Hiermit wird der relative Luftdruck ausgeben. Genauigkeit auf eine Nachkommastelle. Falls kein Messwert vorliegt, wird der Wert 1013 ausgeben.
#temp_out "%.1f" "0.0"# Hiermit wird die Außentemperatur ausgegeben. Genauigkeit auf eine Nachkommastelle. Falls kein Messwert vorliegt, wird der Wert 0.0 ausgeben.
#hum_out "%.0f" "0.0"# Hiermit wird die relative Luftfeuchtigkeit (außen) ausgegeben. Genauigkeit auf eine Nachkommastelle. Falls kein Messwert vorliegt, wird der Wert 0.0 ausgeben.
#calc "apparent_temp(data['temp_out'], data['hum_out'], data['wind_ave'])" "%.1f" "0.0"# Hiermit wird die gefühlte Temperatur ausgegeben. Genauigkeit auf eine Nachkommastelle. Falls kein Messwert vorliegt, wird der Wert 0.0 ausgeben.
#calc "wind_chill(data['temp_out'], data['wind_ave'])" "%.1f" "0.0"# Hiermit wird die Windchill Temperatur ausgeben. Genauigkeit auf eine Nachkommastelle. Falls kein Messwert vorliegt, wird der Wert 0.0 ausgeben.
#calc "dew_point(data['temp_out'], data['hum_out'])" "%.1f" "0.0"# Hiermit wird der Taupunkt ausgeben. Genauigkeit auf eine Nachkommastelle. Falls kein Messwert vorliegt, wird der Wert 0.0 ausgeben. 
#wind_ave "%.1f" "0.0" "wind_kmph(x)"# Hiermit wird die mittlere Windgeschwindigkeit in km/h ausgeben. Genauigkeit auf eine Nachkommastelle. Falls kein Messwert vorliegt, wird der Wert 0.0 ausgeben.
#wind_gust "%.1f" "0.0" "wind_kmph(x)"# Hiermit wird die Geschwindigkeit der Böen in km/h ausgeben. Genauigkeit auf eine Nachkommastelle. Falls kein Messwert vorliegt, wird der Wert 0.0 ausgeben. 
#wind_dir "%.0f" "0.0" "winddir_degrees(x)"#  Hiermit wird die Windrichtung in Grad ausgeben. Keine Nachkommastellen. Falls kein Messwert vorliegt, wird der Wert 0.0 ausgeben.
#wind_dir "%s" "-" "winddir_text(x)"# Hiermit wird die Windrichtung als Text ausgeben.
#calc "data['rain']-prevdata['rain']" "%0.1f" "0.0"# Hiermit wird die aktuelle Wert für Regen ausgeben. Da in den Rohdaten die Werte über den Tag summiert werden, wird hier immer der vorhergehende Wert abgezogen.

Damit ist jetzt schon einmal das erste eigene Template erstellt. Damit es auch von pywws verwendet wird, muss es noch in der "weather.ini" eingetragen werden.

cd ~/weather_data/
vi weather.ini

 Die Datei sollte dann nach allen Änderungen so aussehen:

[config]
ws type = 1080
template encoding = iso-8859-1
gnuplot encoding = iso_8859_1
day end hour = 0
rain day threshold = 0.2
[paths]
work = /home/mypywws/weather_data/tmp
templates = /home/mypywws/weather_data/templates/templates/
graph_templates = /home/mypywws/weather_data/templates/graph_templates/
local_files = /home/mypywws/weather_data/results/
[live]
services = []
yowindow =
twitter = []
plot = []
text = []
[logged]
services = []
yowindow =
twitter = []
text = ['2hrs.log']
plot = []
[hourly]
services = []
yowindow =
twitter = []
text = []
plot = []
[12 hourly]
services = []
yowindow =
twitter = []
text = []
plot = []
[daily]
services = []
yowindow =
twitter = []
text = []
[ftp]
local site = True
secure = False
site = ftp.username.your_isp.co.uk
user = username
password = secret
directory = /var/www/wdata/

Worüber ich anfangs gestolpert bin, dann aber beim Nachlesen by Jim Easterbrook draufgekommen bin, ist die Konfiguration des lokalen Kopierens der Ausgabe in der Sektion [ftp]. Hier wird einfach mit "local site = True" angegeben, dass die Ausgabe lokal auf dem Host kopiert wird. Mit "directory = " wird noch das Zielverzeichnis angeben.

Wenn alles richtig eingetragen wurde, kann pywws gestartet werden ("python -m pywws.LiveLog -vvv /home/mypywws/weather_data/"). Nachdem einmal das Template "2hrs.log" ausgeführt wurde, sollte im Verzeichnis "/var/www/wdata/" eine Datei "2hrs.log" liegen, welche in etwa so aussieht:

09.15.2013 13:22 741.6 1011.0 20.3 69 21.7 20.3 14.4 0.0 0.0 45 NE 0.0
09.15.2013 13:23 741.6 1011.0 20.3 69 21.7 20.3 14.4 0.0 0.0 45 NE 0.0
09.15.2013 13:24 741.7 1011.1 20.3 69 21.7 20.3 14.4 0.0 0.0 45 NE 0.0
09.15.2013 13:25 741.6 1011.0 20.2 69 21.6 20.2 14.3 0.0 0.0 45 NE 0.0
09.15.2013 13:26 741.6 1011.0 20.1 70 21.5 20.1 14.5 0.0 0.0 45 NE 0.0
09.15.2013 13:27 741.6 1011.0 20.1 70 21.5 20.1 14.5 0.0 0.0 45 NE 0.0
09.15.2013 13:28 741.6 1011.0 20.0 70 21.4 20.0 14.4 0.0 0.0 45 NE 0.0
09.15.2013 13:29 741.6 1011.0 19.9 70 21.3 19.9 14.3 0.0 0.0 45 NE 0.0
09.15.2013 13:30 741.6 1011.0 19.9 70 21.3 19.9 14.3 0.0 0.0 45 NE 0.0

Mit der "2hrs.log" kommt man jetzt den Verlauf der Daten über die letzten zwei Stunden, falls in der Zentraleinheit das Loginterfall auf 1 Minute eingestellt ist. Die Anzeige soll später als Linien Chart erfolgen.

Für die nächsten Schritte brauchen wir aber  noch ein weiteres Template. Dieses soll die aktuellen Werte und einige stündliche Werte ausgeben. Die Anzeige soll später mit Messuhren erfolgen.

cd /home/mypywws/weather_data/templates/templates/
vi livedata.log

Hier der Inhalt:

#timezone local#
[
  {
#raw#
        "DATE": "#idx "%d.%m.%Y %H:%M"#",
        "TIME": "#idx "%H:%M %Z"#",
        "HUMID_OUT": #hum_out "%.1f" "0.0"#,
        "WIND_AVG": #wind_ave "%.1f" "0.0" "wind_kmph(x)"#,
        "WIND_GUST": #wind_gust "%.1f" "0.0" "wind_kmph(x)"#,
        "WIND_DIR": #wind_dir "%.0f" "0.0" "winddir_degrees(x)"#,
        "ABS_PRESSURE": #abs_pressure "%.1f" "0.0"#,
        "REL_PRESSURE": #rel_pressure "%.1f" "0.0"#,
        "TEMP_OUT": #temp_out "%.1f" "0.0"#,
        "TEMP_FEEL": #calc "apparent_temp(data['temp_out'], data['hum_out'], data['wind_ave'])" "%.1f" "0.0"#,
        "DEW_POINT": #calc "dew_point(data['temp_out'], data['hum_out'])" "%.1f" "0.0"#,
        "WIND_CHILL": #calc "wind_chill(data['temp_out'], data['wind_ave'])" "%.1f" "0.0"#,
#hourly#
#jump -1#
#loop 1#
        "RAIN": #calc "data['rain']-prevdata['rain']" "%0.1f"#,
#jump 1#
#endloop#
        "WIND_DIR_HOUR": #wind_dir "%.0f" "0.0" "winddir_degrees(x)"#,
        "WIND_GUST_HOUR": #wind_gust "%.1f" "0.0" "wind_kmph(x)"#,
        "WIND_AVG_HOUR": #wind_ave "%.1f" "0.0" "wind_kmph(x)"#,
        "PRESSURE_TREND": #pressure_trend "%s" "0.0" "x"#,
        "RAIN_HOUR": #rain "%0.1f" "0.0"#,
#daily#
        "TEMP_OUT_MIN_DAY": #temp_out_min "%.1f" "0.0"#,
        "TEMP_OUT_MAX_DAY": #temp_out_max "%.1f" "0.0"#
  }
]

Damit das Template angezogen wird, muss wieder die Datei "weather.ini" angepasst werden:

cd /home/mypywws/weather_data/
vi weather.ini

Das neue Template wird in der Sektion [logged] aufgenommen:

[logged]
services = []
yowindow =
twitter = []
text = ['livedata.log', '2hrs.log']
plot = []

 Das Ergebnis sollte dann in etwa so aussehen:

[
  {
	"DATE": "15.09.2013 15:42",
	"TIME": "15:42 CEST",
	"HUMID_OUT": 71.0,
	"WIND_AVG": 0.0,
	"WIND_GUST": 0.0,
	"WIND_DIR": 45,
	"ABS_PRESSURE": 740.5,
	"REL_PRESSURE": 1009.9,
	"TEMP_OUT": 20.1,
	"TEMP_FEEL": 21.6,
	"DEW_POINT": 14.7,
	"WIND_CHILL": 20.1,
	"RAIN": 0.0,
	"WIND_DIR_HOUR": 180,
	"WIND_GUST_HOUR": 0.0,
	"WIND_AVG_HOUR": 0.0,
	"PRESSURE_TREND": -1.3,
	"RAIN_HOUR": 0.0,
	"TEMP_OUT_MIN_DAY": 0.0,
	"TEMP_OUT_MAX_DAY": 21.5  }
]

 

Darstellung der Daten

Für die Darstellung der Daten werden folgende Bibliotheken verwendet:

  • Steelseries Gauges (Messuhren für aktuelle Daten)
  • Highcharts (Charts für Darstellung über mehrere Stunden)

Update 16.08.2014, für alle die wissen wollen wie das geht, siehe hier: Anleitung für Steelseries Gauges und Highcharts

pywws mit Steelseries Gauges

pywws Darstellung der Windstärke über 24 Stunden 

pywws Darstellung der Windrichtung über 24 Stunden

pywws Darstellung von Temperatur, Regen, Luftruck über 24 Stunden

 

Quellen

Für die Umsetzung wurden von mir folgende Quellen in Anspruch genommen:

http://www.raspberrypi.org/

https://www.sdcard.org/downloads/formatter_4/

http://jim-easterbrook.github.io/pywws/doc/en/html/index.html

http://code.google.com/p/pywws/

http://blog.schwabl.net/

http://wiki.sandaysoft.com/a/Main_Page

http://wiki.sandaysoft.com/a/SteelSeries_Gauges

http://www.highcharts.com/