Mit dem Raspberry Pi eine Wetterstation anzapfen

Aus LinuxUser 06/2013

Mit dem Raspberry Pi eine Wetterstation anzapfen

© Sergey Drozdov, Fotolia

Alle Wetter

Einige Wetterstationen liefern ihre Messdaten per USB an einen angeschlossenen Rechner. Mit dem Raspberry Pi lassen sich so die Daten auswerten und per Web-Anwendung ins Netz stellen.

Meiner neu angeschafften Wetterstation TFA Nexus [1] (Abbildung 1) lagen nicht nur etliche Sensoren für Wind, Regen und Außentemperatur bei, sondern auch ein USB-Kabel und eine Auswerte-Software. Letztere wanderte aber direkt wieder in den Karton: Zum einen setzte sie Windows voraus, zum anderen war es eine reine Desktop-Anwendung. Ich wollte die Messdaten aber aufzeichnen und möglichst auch mit dem Handy von unterwegs bewundern.

Abbildung 1: Die Wetterstation TFA Nexus erfasst unter anderem Wind, Regen sowie Außentemperatur und reicht die Daten via USB weiter. (Bild: TFA-Dostmann)

Abbildung 1: Die Wetterstation TFA Nexus erfasst unter anderem Wind, Regen sowie Außentemperatur und reicht die Daten via USB weiter. (Bild: TFA-Dostmann)

So fiel mein zweiter Blick dann auf meinen Raspberry Pi. Der gab bisher mit einem kleinen Lautsprecher ein Zwergen-Mediencenter ab. Stattdessen, so mein Gedanke, könnte er doch die Messdaten aus der Wetterstation auslesen. Der Strombedarf wäre gegenüber einem PC verschwindend gering, obendrein läuft der RasPi lautlos. Gretchenfrage: Wie kommt man per USB an die Daten, wenn der Wetterstation nur ein Windows-Programm beiliegt?

Ein kleines C-Programm

Sebastian John hat das kleine Programm Te923tool [2] geschrieben, das viele Wetterstationen auslesen kann, die auf Hardware des Herstellers Hideki basieren. Mit ein paar Abstrichen funktioniert es auch für meine TFA Nexus. Dafür gilt es allerdings den Quellcode des Programms auf dem Raspberry Pi zu kompilieren. Damit das klappt, müssen die Entwicklerwerkzeuge gcc, make und libusb-dev installiert sein.

Nach Auspacken des Programm-Archivs sollte der Aufruf von make dann das Programm te923con liefern. Ein Test mit dem Aufruf te923con -h liefert – neben der Erkenntnis, ob das Programm läuft – eine ausführliche Hilfe zu dem Programm. Die wiederum verrät, dass ein Aufruf ohne Parameter die Messdaten ausgibt (Listing 1).

Listing 1

$ sudo ./te923con
1363468817:20.40:50:i:i:i:i:i:i:i:i:-1.90:60:1008.0:i:5:0:14:0.4:0.6:-3.8:115

Das vorangestellte sudo ist nötig, da der Zugriff auf den USB-Port Root-Rechte benötigt. Was die einzelnen Werte zwischen den Doppelpunkten bedeuten, erklärt die Hilfe. Ein “i” steht demnach für Werte, die das Programm nicht zuweisen konnte. Das erste Feld jedoch erklärt die Hilfe nicht: Hier handelt es sich umt die Unix-Zeit, also die Sekunden, die seit dem 1.1.1970 vergangen sind. Eine Aufruf von date -d @1363468817 +%c im Terminal macht daraus das lesbare Datum Sam 16 Mär 2013 22:20:17 CET.

Ruby installieren

Ruby bietet eine perfekte Grundlage, um die Messdaten zu verarbeiten und einen Webserver damit zu füttern. Zu den zahlreichen Bibliotheken, die man über die Ruby-eigene Paketverwaltung RubyGem nachinstallieren kann, zählen auch die Datenbankschnittstelle ActiveRecord sowie der Webserver Sinatra. Die beiden Bibliotheken machen später den Kern der Anwendung aus. Ruby lässt sich auf dem RasPi zwar aus den Debian-Paketquellen installieren, aktueller und einfacher zu verwalten ist es jedoch mit der Ruby-Versionsverwaltung Rbenv [3].

Um Rbenv aus dem Quellcode-Verzeichnis gitHub.com zu installieren, müssen Sie zunächst das Paket git einrichten. Einige Ruby-Bibliotheken werden zudem vor der Installation auf dem Zielsystem kompiliert. Um daher später weitere Bibliotheken installieren zu können, gilt es noch die Bibliotheken zlib1g-dev, libsqlite3-dev, libssl-dev und libreadline6-dev aus den Debian-Paketquellen nachzuziehen.

Zur Installation von Rbenv folgen Sie den Anweisungen auf der Webseite des Programms. Anschließend installiert der Aufruf rbenv install 2.0.0-p0 die aktuelle Ruby-Version – auf dem RasPi dauert das einen Augenblick. Bevor Sie Ruby dann verwenden können, legen Sie per rbenv global 2.0.0-p0 erst einmal diese Version als Standard fest. Ein Test mit ruby -v zeigt, ob die Installation geklappt hat.

Webanwendung mit Sinatra

Die Ruby-Bibliotheken verwalten Sie mittels RubyGem. Um Web-Anwendungen mit Sinatra zu programmieren, richten Sie mit dem Kommando gem install sinatra das Sinatra-gem ein. Listing 2 zeigt eine vollwertige Web-Anwendung, die Sie nach dem Start mit ruby webapp.rb im Browser unter der Adresse http://localhost:4567/ aufrufen.

Listing 2

require 'sinatra'
puts Sinatra::VERSION
get '/' do
  'Hello world!'
end

Datenbank befüllen

Jetzt müssen Sie die Messdaten noch geeignet ablegen, wozu in der Regel eine Datenbank dient. Bei SQLite handelt es sich um eine solche, die für einfache Zwecke oft genügt und trotzdem SQL versteht. Sie richten das gute Stück aus dem Debian-Paket sqlite3 ein. Um es aus Ruby heraus zu verwenden, benötigen Sie zudem das Ruby-gem sqlite3 benötigt.

Eine neue Datenbankdatei db.sqlite3, die zum Beispiel die Temperaturwerte zu den jeweiligen Zeitpunkten aufnimmt, erstellen Sie mit dem Befehl

$ sqlite3 db.sqlite3 'create table temperatures(zeit integer, t real)

Das Ruby-Programm in Listing 3 greift mit Hilfe von ActiveRecord auf diese Datenbank zu und füllt sie mit den Werten, die es aus einer CSV-Datei wetter.csv einliest. Die Zeilen in der CSV-Datei wiederum enthalten die Daten der Wetterstation im Format aus Listing 1.

Das Schöne an ActiveRecord: Es kümmert sich automatisch um alles, was man für das Lesen und Schreiben von Datenbanken braucht. So erkennt es in Listing 3 an den Namen der Klasse Temperature, dass es in der Datenbank die Tabelle temperatures verwenden muss, und am Namen der Variablen (zeit und t), in welche Spalten der Datenbanktabelle es schreiben muss.

Listing 3

require 'csv'
require 'active_record'
data = CSV.read('weather.csv', { col_sep: ':' })
ActiveRecord::Base.establish_connection({"adapter"=>"sqlite3", "database"=>"db.sqlite3"})
class Temperature < ActiveRecord::Base
  validates_uniqueness_of :zeit
end
data.each do |d|
  werte = { zeit: d[0], t: d[11] }
  Temperature.create werte
end

Messwerte lesen

Die Daten lassen sich dank ActiveRecord auch komfortabel wieder aus der Datenbank auslesen. Der Code in Listing 4 liest alle Einträge in einem Schwung in die Variable werte ein und multipliziert dabei die Zeitwerte mit 1000. Das Array enthält Wertepaare aus Zeit und Messwert, damit die Diagrammbibliothek diese später als Datenpunkte interpretieren kann. Die Methode inspect generiert aus dem Array eine entsprechende Zeichenkette der Form: @LI: “[[1363465023000, -1.3],[1363468623000, -1.9],…]”.

Im Listing wird diese Zeichenkette im Terminal ausgegeben, später bauen wir sie in die Webseite an der entsprechenden Stelle im Javascript-Code ein.

Listing 4

require 'active_record'
ActiveRecord::Base.establish_connection({"adapter"=>"sqlite3", "database"=>"db.sqlite3"})
class Temperature < ActiveRecord::Base
end
werte = Temperature.all.map {|m| [m.zeit * 1000, m.t]}
data = werte.inspect
puts data

Webseiten darstellen

Es gibt verschiedene Wege, die Daten zu Diagrammen zu verarbeiten und diese in einer Webseite einzubetten. So ließe sich per Skript mit Gnuplot eine Grafikdatei erzeugen und dann als Bild einbauen. Google Charts liefert eine Möglichkeit, die Daten an eine Webschnittstelle zu übermitteln und liefert eine Bilddatei zurück. Dann braucht man keine Grafikanwendungen auf dem eigenen Webserver.

Ich habe mich für eine dritte Variante entschieden und die Javascript-Bibliothek Highcharts [4] zum Erzeugen der Diagramme genutzt. Highcharts liefert sehr ansprechende Ergebnisse. Zwar kostet die Nutzung für den kommerziellen Einsatz nicht gerade wenig, die private Nutzung räumt der Anbieter Highsoft Solutions AS unter der “Creative Commons Attribution-NonCommercial 3.0 License” aber kostenfrei ein.

Listing 5 zeigt ein Diagramm für den Temperaturverlauf über 24 Stunden. Um es zu erzeugen, gilt es lediglich die beiden Javascript-Bibliotheken jQuery und Highcharts einzubetten. Das eigentliche Diagramm wird als Javascript-Funktion definiert. Das einzig Besondere stellt das Kennzeichnen der X-Achse als Datumswerte und das Einbetten der Datenwerte dar. Ein Datenwert setzt sich aus der Zeitangabe und dem Temperaturwert zusammen. Die Zeitangaben aus der Wetterstation haben wir vorher mit 1000 multipliziert, da Javascript die Werte in Millisekunden erwartet, die Angaben in den Messdaten jedoch in Sekunden vorliegen.

Listing 5

<html>
 <head>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
  <script src="http://code.highcharts.com/highcharts.js"></script>
  <script>
   $(function () {
    var chart = new Highcharts.Chart({
     chart: { renderTo: 'container' },
     title: { text: 'Messdaten'},
     xAxis: { type: 'datetime' },
     yAxis: { title: { text: 'Temperatur (C)' } },
     series: [{
      name: "Temperatur",
      data: [[1363465023000, -1.3], [1363468623000, -1.9], [1363472223000, -2.5],
      [1363475823000, -2.5], [1363479423000, -2.8], [1363483023000, -3.1],
      [1363486623000, -3.4], [1363490223000, -3.7], [1363493823000, -3.9],
      [1363497423000, -3.9], [1363501023000, -3.3], [1363504622000, 2.0],
      [1363508223000, 1.1], [1363511822000, 7.8], [1363515422000, 5.4],
      [1363519022000, 4.3], [1363522623000, 5.9], [1363526223000, 6.3],
      [1363529823000, 5.2], [1363533423000, 3.8], [1363537023000, 3.1],
      [1363540623000, 2.0], [1363544223000, 1.6], [1363547823000, 1.3],
      [1363551422000, 1.1]],
      pointStart: 1363465023000,
      pointInterval: 3600 * 1000 // one hour
     }]
    });
   });
  </script>
 </head>
 <body>
  <div id="container" style="height: 400px"></div>
 </body>
</html>

Alles zusammen

Die bisher beschriebenen Zutaten machen den Kern der Anwendung aus. Was noch fehlt, ist im Wesentlichen die regelmäßige Aktualisierung der Daten und das Zusammenspiel der bisher beschriebenen Komponenten. Eine einfache Webanwendung, die Daten aus der Datenbank ausliest und das entsprechende Diagramm generiert, sehen Sie in Listing 6.

Listing 6

require 'active_record'
require 'sinatra'
ActiveRecord::Base.establish_connection({"adapter"=>"sqlite3", "database"=>"db.sqlite3"})
class Temperature < ActiveRecord::Base
end
get '/' do
  werte = Temperature.all(order: "zeit desc", limit: 24)
  @data = werte.map {|m| [m.zeit * 1000, m.t]}.inspect
  @start_time = werte.first.zeit
  erb :index
end
__END__
@@ index
<html>
 <head>
 [ ... wie in Listing 5, bis 'series' ...]
      series: [{
        name: "Temperatur",
        data: <%= @data %>,
        pointStart: <%= @start_time * 1000 %>,
        pointInterval: 3600 * 1000 // one hour
      }]
 [ ... weiter wie in Listing 5 ...]

Die eigentliche Sinatra-Webanwendung steckt in den Zeilen 8 bis 13. Der Aufruf von erb :index baut die Daten in die Webseite ein, die wiederum ab Zeile 18 gleich in das Skript eingebettet ist. Erb ersetzt in Zeile 23 den Code <%= @data %> durch den Inhalt der Variable @data. Das Ergebnis im Browser zeigt Abbildung 2.

Abbildung 2: Ein Highcharts-Diagramm der Wetterdaten in einer Sinatra-Webanwendung.

Abbildung 2: Ein Highcharts-Diagramm der Wetterdaten in einer Sinatra-Webanwendung.

Um das regelmäßige Erfassen der Daten kümmert sich ein Cron-Job mit einem stündlichen Aufruf des Lade-Skripts aus Listing 7. Das Skript legen Sie im Verzeichnis /etc/cron.hourly ab und markieren es mit sudo chmod a+x crontab_pi als ausführbar. Das im Listing aufgeführte Skript load_data liest die Messdaten aus, schreibt sie in die CSV-Datei und lädt diese in die Datenbank.

Listing 7

30 * * * * /usr/local/bin/load-data > /dev/null 2>&1

Ausblick

Listing 6 hat das Prinzip einer Sinatra-Webanwendung gezeigt, in der mit relativ wenig Code eine vollwertige Webanwendung entsteht. Der Rest ist Fleißarbeit und besteht größtenteils darin, die anderen Messwerte der Wetterstation einzubeziehen und das Programm etwas aufzuräumen. Ein mögliches Resultat dieser Bemühungen zeigt Abbildung 3.

Abbildung 3: Die Wetterdaten in der fertigen Webanwendung.

Abbildung 3: Die Wetterdaten in der fertigen Webanwendung.

Das vorläufige Ergebnis meiner Wetter-Anwendung habe ich als Quellcode in gitHub.com [5] eingestellt. Um die Sourcen mit Git herunterzuladen und auszuprobieren, erzeugen Sie zunächst eine lokale Kopie:

$ git clone git://github.com/rheikvaneyck/rnexus.git

Später können Sie Aktualisierungen dann mit git pull nachladen. Noch ist der Code an vielen Stellen verbesserungsfähig. Einen Einblick in die Möglichkeiten, mit dem einem Raspberry Pi auch eigene Webanwendungen zu bauen, verschafft er aber allemal. 

Infos

[1] TFA Wetterstation Nexus: http://tfa-dostmann.de/index.php?id=62

[2] Te93tool: http://te923.fukz.org/

[3] Rbenv: https://github.com/sstephenson/rbenv

[4] Highcharts: http://www.highcharts.com/

[5] Rnexus Wetter-Web-Anwendung: https://github.com/rheikvaneyck/rnexus

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDF
LinuxUser 06/2013 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

1 Kommentar
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
W. Spitzner
11 Jahre her

Eine genauere Beschreibung des Ablaufes mit den Befehlsfolgen wäre schön gewesen. So muß man das Rad noch einmal neu erfinden. Für Anfänger völlig ungeeignet.
Schade..

Nach oben