Hallo zusammen,
da ich unseren Garten demnächst automatisch bewässern will, habe ich mich nun endlich daran gemacht, mein erstes "vorzeigbares" Plugin zu schreiben, das ich hier kurz vorstellen möchte und freue mich, wenn es sonst noch jemand brauchen kann. Schließlich habe ich ein paar Code-Teile aus dem Forum hier wiederverwertet
Kurze Beschreibung:
Wichtig war mir vor allem das zyklische Antriggern, da ich so über die Treppenlichtfunktion des Aktors sicherstellen kann, dass auch bei einer Fehlfunktion des WG bzw. des Plugins die Ventile wieder geschlossen werden.
Es ist bestimmt noch nicht perfekt, aber ich finde es schon ganz brauchbar...
da ich unseren Garten demnächst automatisch bewässern will, habe ich mich nun endlich daran gemacht, mein erstes "vorzeigbares" Plugin zu schreiben, das ich hier kurz vorstellen möchte und freue mich, wenn es sonst noch jemand brauchen kann. Schließlich habe ich ein paar Code-Teile aus dem Forum hier wiederverwertet

Kurze Beschreibung:
- Start/manueller Stop über eine einzige GA
- Rückmeldung (aktiv/inaktiv) über Status-GA
- beliebig viele Beregnungs-Stränge mit individueller Dauer
- zyklisches Antriggern des aktuellen Stranges (damit Verwendung der Treppenlicht-Funktion für erhöhte Sicherheit möglich)
- reichlich Ausgaben ins Plugin-Log
Wichtig war mir vor allem das zyklische Antriggern, da ich so über die Treppenlichtfunktion des Aktors sicherstellen kann, dass auch bei einer Fehlfunktion des WG bzw. des Plugins die Ventile wieder geschlossen werden.
Es ist bestimmt noch nicht perfekt, aber ich finde es schon ganz brauchbar...
Code:
############################################################################# # Plugin: bewaesserung.pl (Gartenberegnung steuern) # V0.5 20140309 # Autor: Mathias Gindler (mathias@gindler.de) # License: GPL (v3) # ############################################################################# # # Beschreibung: # Ansteuerung mehrerer Beregnungstränge hintereinander für eine bestimmte Dauer # (je Strang), ausgelöst/gestoppt über eine einzige GA. # Dabei wird der Strang innerhalb der Dauer zyklisch neu angetriggert, # somit kann die Treppenlichtfunktion eines Aktors für eine Sicherheits- # abschaltung verwendet werden. # ############################################################################# # # Änderungshistorie: # ############################################################################# # # Offene Punkte: # ############################################################################# # # Abhängigkeiten: # ############################################################################# # # plugin_info-Werte # - aktKreisNr: Index (0-n) des aktuellen Kreises # - Startzeit: Start des aktuellen Kreises # - Status: Bewässerung aktiv (1) oder inaktiv (0) # ############################################################################# use POSIX; use Time::Local; # Konstanten für Aufrufart use constant EVENT_RESTART => 'restart'; use constant EVENT_MODIFIED => 'modified'; use constant EVENT_BUS => 'bus'; use constant EVENT_SOCKET => 'socket'; use constant EVENT_CYCLE => 'cycle'; my $show_debug = 1; my $debugindex = 1; my $gv_event=undef; my $startzeit; my $pluginstatus; my $ga_plugintrigger = "12/6/100"; # Start/Stop der Beregnungs-Sequenz my $ga_pluginstatus = "12/6/102"; # Status, ob Sequenz aktiv/inaktiv (1/0) my $triggercycle = 10; # Re-Trigger-Intervall (entspricht max. Über-Bewässerung), # muss kleiner als Treppenlicht-Einstellung des Aktors sein my @Kreise; # Array für Regnerkreise push @Kreise, {name => "Rasen West", dauer => 100, ga_schalten => '12/6/10', ga_status => '12/6/12'}; push @Kreise, {name => "Rasen Ost", dauer => 110, ga_schalten => '12/6/20', ga_status => '12/6/22'}; push @Kreise, {name => "Hecke", dauer => 120, ga_schalten => '12/6/30', ga_status => '12/6/32'}; plugin_log($plugname, "------------------------------------") if ($show_debug > 5); # Aufruf per Bus-Telegramm $plugin_subscribe{$ga_plugintrigger}{$plugname} = 1; # aktuellen Status lesen if ($plugin_info{$plugname.'_Status'} ne '') {$pluginstatus = $plugin_info{$plugname.'_Status'}}; # Aus welchem Grund läuft das Plugin gerade if (!$plugin_initflag) {$gv_event = EVENT_RESTART;} # Restart des daemons / Reboot elsif ($plugin_info{$plugname.'_lastsaved'} > $plugin_info{$plugname.'_last'}) {$gv_event = EVENT_MODIFIED;} # Plugin modifiziert elsif (%msg) {$gv_event = EVENT_BUS;} # Bustraffic elsif ($fh) {$gv_event = EVENT_SOCKET;} # Netzwerktraffic else {$gv_event = EVENT_CYCLE;} # Zyklus plugin_log($plugname, $debugindex++." (MAIN) Aufrufgrund: $gv_event") if ($show_debug > 5); plugin_log($plugname, $debugindex++." (MAIN) aktueller Status: $pluginstatus") if ($show_debug > 5); if ($gv_event eq EVENT_RESTART) { ende(); } elsif ($gv_event eq EVENT_MODIFIED) { ende(); } elsif ($gv_event eq EVENT_SOCKET) { } elsif ($gv_event eq EVENT_CYCLE) { beregnung(); } elsif ($gv_event eq EVENT_BUS) { plugin_log($plugname, $debugindex++." (BUS) aktueller Status: $pluginstatus") if ($show_debug > 1); if ($msg{'apci'} eq "A_GroupValue_Write" and $msg{'dst'} eq $ga_plugintrigger) { if ($msg{'value'} == 1){ plugin_log($plugname, $debugindex++." (BUS) EIN-Telegramm empfangen") if ($show_debug > 1); $plugin_info{$plugname.'_cycle'} = $triggercycle; if ($pluginstatus == 1){ plugin_log($plugname, $debugindex++." (BUS) Beregnungsprogramm läuft bereits - keine Aktion ausgeführt") if ($show_debug > 0); } else{ plugin_log($plugname, $debugindex++." (BUS) Beregnungsprogramm gestartet") if ($show_debug > 0); $startzeit = time(); $plugin_info{$plugname.'_Startzeit'} = $startzeit; $plugin_info{$plugname.'_aktKreisNr'} = 0; $pluginstatus = 1; $plugin_info{$plugname.'_Status'} = $pluginstatus; beregnung(); } } else{ plugin_log($plugname, $debugindex++." (BUS) AUS-Telegramm empfangen") if ($show_debug > 1); $plugin_info{$plugname.'_cycle'} = 0; if ($pluginstatus == 0){ plugin_log($plugname, $debugindex++." (BUS) Beregnungsprogramm läuft nicht - keine Aktion ausgeführt") if ($show_debug > 0); } else{ plugin_log($plugname, $debugindex++." (BUS) Beregnungsprogramm beendet") if ($show_debug > 0); ende(); } } } } knx_write($ga_pluginstatus, $pluginstatus); # aktuellen Status an Bus zurückmelden sub beregnung{ my $x; my $kreisname; my $kreisdauer; my $ga_schalten; my $ga_status; my $istdauer; # Parameter für aktuellen Kreis setzen $x = $plugin_info{$plugname.'_aktKreisNr'}; $kreisname = $Kreise[$x]->{name}; $ga_schalten = $Kreise[$x]->{ga_schalten}; $ga_status = $Kreise[$x]->{ga_status}; $kreisdauer = $Kreise[$x]->{dauer}; plugin_log($plugname, $debugindex++." (SUB beregnung) Beregnung: Index $x ('$kreisname'), Trigger $ga_schalten, Status $ga_status") if ($show_debug > 5); if ($plugin_info{$plugname.'_Startzeit'} + $kreisdauer < time()){ plugin_log($plugname, $debugindex++." (SUB beregnung) Kreis '$kreisname' abgeschlossen") if ($show_debug > 0); $istdauer = sprintf("%2.0f", time() - $plugin_info{$plugname.'_Startzeit'}); plugin_log($plugname, $debugindex++." (SUB beregnung) Kreis '$kreisname' Dauer: $istdauer sek. (ist)/$kreisdauer sek. (soll)") if ($show_debug > 0); knx_write($ga_schalten, 0); if ($x < $#Kreise){ plugin_log($plugname, $debugindex++." (SUB beregnung) Umschalten auf nächsten Kreis") if ($show_debug > 0); $x++; $plugin_info{$plugname.'_aktKreisNr'} = $x; $plugin_info{$plugname.'_Startzeit'} = time(); # nächste Zeile aktivieren, um sofort umzuschalten; # wenn deaktiviert, wird nächster Kreis erst im nächsten Zyklus eingeschaltet ($triggercycle) beregnung(); } else{ plugin_log($plugname, $debugindex++." (SUB beregnung) keine weiteren Kreise, Beregnung beendet.") if ($show_debug > 0); ende(); } } else{ plugin_log($plugname, $debugindex++." (SUB beregnung) Beregnung für Kreis '$kreisname' (re-)triggert") if ($show_debug > 0); knx_write($ga_schalten, 1); } } sub ende{ foreach (@Kreise){ plugin_log($plugname, $debugindex++." (SUB ende) Ventil für '$_->{name}' geschlossen") if ($show_debug > 0); knx_write($_->{ga_schalten},0); } $pluginstatus = 0; $plugin_info{$plugname.'_Status'} = $pluginstatus; $plugin_info{$plugname.'_cycle'} = 0; }
Kommentar