Damit die Balkonpflanzen auch im Urlaub nicht vertrocknen, bauen wir heute ein Bewässerungssystem und lassen Linux zweimal täglich gießen.
Im Sommer genügen schon wenige Tage Abwesenheit, damit geliebte Balkonpflanzen wegen Wassermangels irreparable Schäden erleiden. Statt nach jedem Trip zum Supermarkt zu fahren, um totes Grünzeug zu ersetzen, sorgt eine Pumpe einfach für den nötigen Wassernachschub.
Wer jedoch softwaregesteuert mit Wasser hantiert, läuft immer Gefahr, die Wohnung wegen eines unvorhergesehenen Fehlers unter Wasser zu setzen. Einen Ausweg aus diesem Dilemma zeigte eine unlängst im High-Tech Bastelmagazin ``Make'' vorgestellte Bewässerungslösung: Dort wurde einfach die verfügbare Wassermenge auf den Inhalt einer Wasserflasche beschränkt.
Abbildung 1: Der zweckentfremdede Hundekeksspender mit eingebauter Wasserpumpe. Der Schlauch führt durchs Fenster auf den Balkon hinaus. |
Weil die Frau des Perlmeisters aber keine mit Heißleim zusammengeflickten Wasserflaschen in der Wohnung duldet, ist das heute vorgestellte Pumpsystem optisch etwas ansprechender: Der Vorratsbehälter besteht aus einem im Haushaltswarenladen gekauften Hundekeksbehälter mit aufklappbarer Öffnung ($4.75) und einer auf Ebay ersteigerten Aquariumpumpe ($6.75 plus Porto). Mit einer Bohrmaschine und einem Schleifkopf wurde auf der Rückseite des Behälters oben ein Spalt hineingefräst, durch den der im Heimwerkermarkt gekaufte Wasserschlauch und das Netzkabel der Pumpe auch bei geschlossenem Deckel nach außen gelangen. Der Schlauch führt durchs Fenster auf den Balkon und endet über den Pflanzentöpfen. Über jeder zu bewässernden Pflanze wurde mit der Bohrmaschine ein kleines Loch in den Schlauch gebohrt, durch das dieser Wasser an die Pflanze abgibt. Es ist darauf zu achten, dass die Löcher nicht zu groß werden, falls doch, kann man sie leicht mit Kleber wieder verkleinern oder ganz zustopfen. Die Aquariumpumpe wurde mit Heißkleber am Behälterboden festgeklebt. Zum Wassernachfüllen klappt man einfach den roten Deckel des Behälters auf.
Abbildung 2: Nicht vergessen: Der Wasservorratsbehälter muss von Zeit zu Zeit nachgefüllt werden. |
Über ein am Stromnetz hängendes X10-Modul ([3]) wird die Pumpe ein- und ausgeschaltet. Wie schon einmal in [4] vorgestellt, kann man mit dem X10-Protokoll Signale über das Stromnetz schicken. Der Sender hängt in diesem Fall am seriellen (oder USB-) Port des Linux-Rechners und speist mittels einer X10-PC-Schnittstelle (in Deutschland unter anderem auf [5] erhältlich) Signale ins Stromnetz ein. Der Empfängerkasten hängt an einer anderen Steckdose im gleichen Stromnetz und schaltet per Signal die angeschlossene Aquariumpumpe ein und aus.
Abbildung 3: Die Aquariumpumpe wird am X10-Empfänger eingesteckt. |
Die Ansteuerung der seriellen Schnittstelle ist ausgesprochen simpel.
Das Skript in Listing water
muss als root
laufen, damit es den
Schreibzugriff auf die erste serielle Schnittstelle des Rechners
auf /dev/ttyS0
erhält, in die der X10-Sender eingestöpselt wurde.
Auch die Steuerung eines Controllers über die USB-Schnittstelle ist
übrigens machbar, das wish-Projekt ([6]) stellt die nötige freie Software
dafür bereit.
Die im Skript verwendeten Werte für den ``House Code K'' und den ``Unit Code 11'' dienen der Adressierung des Empfängers, der, wie in Abbildung 5 sichtbar, ebenfalls auf ``K'' und ``11'' eingestellt ist. Diese Werte müssen im Hausstromnetz eindeutig sein, sonst kommt es zu Konflikten.
water
nutzt die Module Device::SerialPort
und ControlX10::CM11
vom
CPAN für die Fitzelarbeit mit der seriellen Schnittstelle und den
Besonderheiten des X10-Protokolls. Gemäß X10 ist das Kommando zum
Einschalten eines Empfängers ``J'', und mit ``K'' wird anschließend
wieder abgeschaltet. Vor dem Senden eines Kommandos ist jeweils der
Empfänger zu addressieren. Und jedem Kommando geht der ``House Code''
voran.
01 #!/usr/bin/perl 02 use warnings; 03 use strict; 04 05 use Device::SerialPort; 06 use ControlX10::CM11; 07 use Log::Log4perl qw(:easy); 08 use Waterscore qw(waterscore); 09 10 my $HOUSE_CODE = "K"; 11 my $UNIT_CODE = "11"; 12 my $SERIAL = "/dev/ttyS0"; 13 my $BAUDRATE = 4800; 14 my $LOCATION = "USCA0987"; 15 16 die "You must be root" if $> != 0; 17 18 Log::Log4perl->easy_init({ 19 level => $DEBUG, 20 file => ">>/tmp/water.log"}); 21 22 my $score = waterscore($LOCATION); 23 24 if($score < 20) { 25 INFO "No water."; 26 exit 0; 27 } 28 29 my $serial = Device::SerialPort->new( 30 $SERIAL, undef); 31 $serial->baudrate($BAUDRATE); 32 33 # Address unit 34 ControlX10::CM11::send($serial, 35 $HOUSE_CODE . $UNIT_CODE); 36 37 # Turn water pump on 38 INFO "Water on"; 39 ControlX10::CM11::send($serial, 40 $HOUSE_CODE . "J"); 41 42 sleep($score/10); 43 44 # Turn water pump off 45 INFO "Water off"; 46 ControlX10::CM11::send($serial, 47 $HOUSE_CODE . "K");
Balkonpflanzen brauchen bei heißem Wetter mehr Wasser und bei Regen
gar keines. Das Skript water
kontaktiert deswegen den Wetterservice
weather.com
auf dem Internet
und fragt die aktuelle Temperatur, Luftfeuchtigkeit und
die Wetterlage ab. Aus diesen Parametern generiert es einen
Bewässerungs-``Score''
von 0 bis 100. Bei 0 brauchen die Pflanzen kein Wasser, bei 100 sehr viel.
Bei einem Score von weniger als 20 gießt water
deswegen überhaupt nicht
und darüber bringen jeweils 10 Punkte eine um eine Sekunde
längere Gießdauer. Maximal bleibt die Pumpe also 10 Sekunden an, dieser
Wert sollte auf die Pumpkapazität und den Wasserbedarf der Pflanzen
auf dem heimischen Balkon abgestimmt werden.
Die Wässerungspunktzahl wird in dem Extra-Modul Waterscore.pm
berechnet.
Dessen Funktion waterscore
wird
auf Anweisung des aufrufenden Skripts water
in dessen
Namensraum exportiert. Perls Exporter
-Modul sorgt für diesen Service.
Waterscore.pm
kontaktiert die Wetterseite
weather.com
mit einer Partner-ID und
einem Lizenzschlüssel, die man dort kostenlos erhält,
wenn man sich mit einer gültigen Email-Adresse registriert. Das CPAN-Modul
Weather::Com
abstrahiert den Zugriff auf den dort angebotenen
Webservice und wandelt
das zurückkommende XML praktischerweise gleich in Perlstrukturen um.
01 package Waterscore; 02 03 use base Exporter; 04 @EXPORT_OK = qw(waterscore); 05 06 use strict; 07 use warnings; 08 use Weather::Google; 09 use Log::Log4perl qw(:easy); 10 11 ########################################### 12 sub waterscore { 13 ########################################### 14 my($loc) = @_; 15 16 my $w = Weather::Google->new(94114); 17 18 # 'icon' => '/images/weather/cloudy.gif', 19 # 'temp_f' => '95', 20 # 'temp_c' => '35', 21 # 'wind_condition' => 'Wind: W at 5 mph', 22 # 'humidity' => 'Humidity: 42%', 23 # 'condition' => 'Cloudy' 24 25 my($cond, $temp, $humi) = $w->current('condition', 'temp_c', 'humidity'); 26 27 if(!defined $cond) { 28 ERROR "Failed to get weather from Google"; 29 return undef; 30 } 31 32 ($humi) = $humi =~ /(\d+)/; 33 DEBUG "$cond, $temp C, $humi%"; 34 35 my $score = 50; 36 $score += 50 if $humi < 50; 37 $score -= 30 if $cond =~ /Showers/; 38 $score -= 80 if $cond =~ /Rain/; 39 $score += 80 if $cond =~ /Sunny/; 40 41 if($temp > 20) { 42 $score += ($temp-15)*10; 43 } 44 45 if($temp < 16) { 46 $score /= 2.0; 47 } 48 49 $score = 100 if $score > 100; 50 $score = 0 if $score < 0; 51 DEBUG "Score: $score"; 52 return $score; 53 } 54 55 1;
weather.com
liefert das Wetter für Wetterbezirke, die mit Kürzeln
wie ``USCA0987'' (für San Francisco) bezeichnet werden.
Das Skript location
hilft, das Kürzel
für den lokalen Wetterbezirk zu finden. Abbildung 4 zeigt die
Ausgabe des Skripts mit dem Argument ``berlin''. Neben einer Reihe von
ebenfalls ``Berlin'' benannten Städten in den USA liefert es zwei
Einträge für das deutsche Berlin. Mit ``München'' kann das Modul
sonderbarerweise nichts anfangen, aber mit ``Munich'' aufgerufen liefert
es die richtige Wetterstation GMXX0087 der heimlichen Hauptstadt.
Abbildung 4: Die Wetterkürzel für verschiedene Orte mit dem Namen "Berlin". |
01 #!/usr/bin/perl -w 02 use strict; 03 use Weather::Com; 04 05 my $w = Weather::Com->new(); 06 07 $ARGV[0] or die "usage: $0 city"; 08 09 my $locs = $w->search($ARGV[0]); 10 11 for my $loc (keys %$locs) { 12 printf "%-20s %s\n", 13 $locs->{$loc}, $loc; 14 }
Waterscore.pm
bedient sich einiger empirisch ermittelter Tricks, um
den Score zu berechnen. Meldet der Wetterdienst Regen (die Worte
"Rain"
oder "Showers"
kommen im Wetterbericht vor),
werden 80 Punkte abgezogen, so dass es kaum Wasser für die Pflanzen
geben wird, es sei
denn, es ist sehr heiss. Geringe Luftfeuchtigkeit erhöht hingegen
die Punktzahl und damit die Gießwahrscheinlichkeit und -dauer.
Sonniges Wetter (angezeigt durch das Wort "Sunny"
im Feld
{cc}->{t}
) und Temperaturen über 15 Grad Celsius
wirken in ähnlicher Weise auf den Zähler ein.
Wird der Konstruktor von Weather::Com
mit einem wahren Wert für
den Parameter current
aufgerufen, holt die nachher aufgerufene Methode
get_weather()
die Messwerte für das gerade herrschende Wetter ein.
Der auf den Wert "m"
(für metrisch) gesetzte Parameter units
gibt
an, dass die Temperaturen in Celsius (und nicht in Fahrenheit) zurückkommen.
Abbildung 5: Aus einem Loch im Schlauch spritzt Wasser auf die zu bewässernde Balkonpflanze. |
Das Modul Waterscore.pm
ist so zu installieren, das water
es
findet (zum Beispiel unter /usr/lib/perl5/site_perl).
Ein als root
laufender Cronjob mit dem Eintrag
00 9,16 * * * /usr/bin/water
lässt das Bewässerungsskript zweimal täglich, am Morgen und am Abend,
ablaufen und eine angemessene Wassermenge auf die Balkonpflanzen spritzen.
Anhand der Logdatei in /tmp/water.log
lässt sich jederzeit nachverfolgen,
wann wieviel Wasser die Pflanzen benetzt hat.
Zu beachten ist, dass der Wasserbehälter genug Wasser auf Vorrat
hat, dann steht einem Kurzurlaub nichts im Wege.
Abbildung 6: Die Logdatei listet auf, wann und wieviel Wasser auf die Balkonpflanzen gegossen wurde. |
Michael Schilliarbeitet als Software-Engineer bei Yahoo! in Sunnyvale, Kalifornien. Er hat "Goto Perl 5" (deutsch) und "Perl Power" (englisch) für Addison-Wesley geschrieben und ist unter mschilli@perlmeister.com zu erreichen. Seine Homepage: http://perlmeister.com. |