Sodala. Hab nun ein paar Dinge überarbeitet:
- Korrektes read der Beregnungszeiten von der Visu
- Berücksichtigung der Beregnungszeiten nur, wenn ga definiert, sonst wird der Default-Wert der im Plugin je Kreis definiert wird, verwendet.
- Freigabe-GA: Sequenz läuft nur, wenn Freigabe = 1, wird während einer laufenden Sequenz die Freigabe auf 0 gesetzt, wird die Sequenz abgebrochen.
- Fehlerhaftes Verhalten: Unterscheidung BUS und Cycle: Es wird gezielt mit den Variablen verglichen, die unter subscribe definert sind.
Nur elsif (%msg) reicht offensichtlich nicht, möglicherweise steht hier ein Wert, der in einem anderen plugin subscribed ist und zufällig "zeitgleich" am Bus gesendet wird?
Somit wird nun alles unterstützt, was auf dem CV-Ausschnitt zu sehen ist (außer Regenmenge).
Größter offener Punkt:
Ich möchte aus der CV auch einzelne Kreise einschalten und zyklisch triggern. Derzeit schaltet sich ein Kreis, der einzeln eingeschaltet wird, NIE bzw. falls definiert nach der Treppenlichtzeit des Aktors aus.
lg
Robert
- Korrektes read der Beregnungszeiten von der Visu
- Berücksichtigung der Beregnungszeiten nur, wenn ga definiert, sonst wird der Default-Wert der im Plugin je Kreis definiert wird, verwendet.
- Freigabe-GA: Sequenz läuft nur, wenn Freigabe = 1, wird während einer laufenden Sequenz die Freigabe auf 0 gesetzt, wird die Sequenz abgebrochen.
- Fehlerhaftes Verhalten: Unterscheidung BUS und Cycle: Es wird gezielt mit den Variablen verglichen, die unter subscribe definert sind.
Nur elsif (%msg) reicht offensichtlich nicht, möglicherweise steht hier ein Wert, der in einem anderen plugin subscribed ist und zufällig "zeitgleich" am Bus gesendet wird?
Somit wird nun alles unterstützt, was auf dem CV-Ausschnitt zu sehen ist (außer Regenmenge).
Größter offener Punkt:
Ich möchte aus der CV auch einzelne Kreise einschalten und zyklisch triggern. Derzeit schaltet sich ein Kreis, der einzeln eingeschaltet wird, NIE bzw. falls definiert nach der Treppenlichtzeit des Aktors aus.
Code:
############################################################################# # Plugin: bewaesserung.pl (Gartenberegnung steuern) # V0.6 20140708 # Autor: Mathias Gindler (mathias@gindler.de) # Erweiterung: Robert_Mini # 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: # - Zeitsteuerung # - Regenmengen- und Temperaturabhängigkeit # - Ansteuerung einzelner Kreise mit re-trigger ohne Sequenz ############################################################################# # # 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; use Math::Round; # return; # 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 = 2; my $debugindex = 1; my $gv_event=undef; my $startzeit; my $pluginstatus; my $ga_plugintrigger = "5/4/102"; # Start/Stop der Beregnungs-Sequenz my $ga_pluginstatus = "5/4/103"; # Status, ob Sequenz aktiv/inaktiv (1/0) my $ga_gesamtzeit = "5/4/104"; # Status, ob Sequenz aktiv/inaktiv (1/0) my $ga_zeitfaktor = "5/4/106"; # Globaler Faktor, DPT9 my $ga_resetdauer = "5/4/108"; # Reset GA schreibt die Defaultwerte aus dem plugin zurück auf den Bus, DPT 1 my $ga_freigabe_gesamt = "5/4/100"; # Freigabe GA, sperrt Bewässerungssequenz undabhängig vom Aktor und sendet Ende() my $triggercycle = 30; # 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 => "Wiese Gartenhaus", dauer => 900, ga_schalten => '5/4/115', ga_status => '5/4/99', ga_sperre => '5/4/116', ga_restzeit => '5/4/118', ga_dauer => '5/4/119'}; push @Kreise, {name => "Terrasse", dauer => 600, ga_schalten => '5/4/125', ga_status => '5/4/99', ga_sperre => '5/4/126', ga_restzeit => '5/4/128', ga_dauer => '5/4/129'}; push @Kreise, {name => "Obstgarten", dauer => 900, ga_schalten => '5/4/110', ga_status => '5/4/99', ga_sperre => '5/4/111', ga_restzeit => '5/4/113', ga_dauer => '5/4/114'}; push @Kreise, {name => "Spruehregner", dauer => 450, ga_schalten => '5/4/120', ga_status => '5/4/99', ga_sperre => '5/4/121', ga_restzeit => '5/4/123', ga_dauer => '5/4/124'}; push @Kreise, {name => "Brunnen", dauer => 600, ga_schalten => '5/4/130', ga_status => '5/4/99', ga_sperre => '5/4/131', ga_restzeit => '5/4/133', ga_dauer => '5/4/134'}; plugin_log($plugname, "------------------------------------") if ($show_debug > 5); # Aufruf per Bus-Telegramm $plugin_subscribe{$ga_plugintrigger}{$plugname} = 1; $plugin_subscribe{$ga_resetdauer}{$plugname} = 1; $plugin_subscribe{$ga_freigabe_gesamt}{$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 and ($msg{'dst'} eq $ga_plugintrigger or $msg{'dst'} eq $ga_resetdauer or $msg{'dst'} eq $ga_freigabe_gesamt)) {$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) { ## Start durch GA # Zeiten vom Bus lesen ergänzen 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{'data'} == 1){ #value durch data ersetzt $plugin_info{$plugname.'_cycle'} = $triggercycle; my $freigabe_gesamt = knx_read($ga_freigabe_gesamt,0,1); plugin_log($plugname, $debugindex++." (BUS) EIN-Telegramm empfangen, Freigabe $freigabe_gesamt") if ($show_debug > 1); if ($freigabe_gesamt == 0){ # Keine Freigabe, Sequenz beenden! plugin_log($plugname, $debugindex++." (BUS) keine Freigabe => Ende") if ($show_debug > 0); ende(); } elsif ($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; $plugin_info{$plugname.'_StartzeitSequenz'} = $startzeit; 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(); } } } elsif ($msg{'apci'} eq "A_GroupValue_Write" and $msg{'dst'} eq $ga_resetdauer) { if ($msg{'data'} == 1){ #value durch data ersetzt plugin_log($plugname, $debugindex++." (BUS) ga_resetdauer aufgerufen") if ($show_debug > 1); foreach (@Kreise){ my $kreisdauer = ($_->{dauer})/60; knx_write($_->{ga_dauer}, $kreisdauer, 9); } } } elsif ($msg{'apci'} eq "A_GroupValue_Write" and $msg{'dst'} eq $ga_freigabe_gesamt) { if ($msg{'data'} == 0){ #value durch data ersetzt plugin_log($plugname, $debugindex++." (BUS) Freigabe aufgehoben => Ende") if ($show_debug > 0); ende(); } } } knx_write($ga_pluginstatus, $pluginstatus, 1); # aktuellen Status an Bus zurückmelden sub beregnung{ my $x; my $kreisname; my $kreisdauer; my $ga_schalten; my $ga_status; my $ga_sperre; my $ga_restzeit; my $ga_dauer; 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}; $ga_sperre = $Kreise[$x]->{ga_sperre}; $ga_restzeit = $Kreise[$x]->{ga_restzeit}; $ga_dauer = $Kreise[$x]->{ga_dauer}; my $sperre = 0; if ($ga_sperre) {$sperre = knx_read($ga_sperre, 0,1);} my $zeitfaktor = knx_read($ga_zeitfaktor, 0,9); my $dauer = 0; my $dauer_bus = 0; if ($ga_dauer) { $dauer = 60 * round(knx_read($ga_dauer, 0,9)); } else {$dauer = $Kreise[$x]->{dauer};} $kreisdauer = $dauer * $zeitfaktor; my $restzeit = 0; my $gesamtzeit = 0; plugin_log($plugname, $debugindex++." (SUB beregnung) Beregnung: Index $x ('$kreisname'), Trigger $ga_schalten, Status $ga_status, Sperre $sperre, Zeitfaktor $zeitfaktor Dauer $kreisdauer") if ($show_debug > 5); if ($plugin_info{$plugname.'_Startzeit'} + $kreisdauer - 2 < time() or ($sperre == 1)){ if (!$sperre) { 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 > 1); knx_write($ga_schalten, 0, 1); } else { plugin_log($plugname, $debugindex++." (SUB beregnung) Kreis '$kreisname' gesperrt") if ($show_debug > 0); } knx_write($ga_restzeit, $restzeit, 9); 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); $gesamtzeit = (time() - $plugin_info{$plugname.'_StartzeitSequenz'})/60; knx_write($ga_gesamtzeit, $gesamtzeit, 9); ende(); } } else{ plugin_log($plugname, $debugindex++." (SUB beregnung) Beregnung für Kreis '$kreisname' (re-)triggert") if ($show_debug > 1); knx_write($ga_schalten, 1, 1); $restzeit = ($plugin_info{$plugname.'_Startzeit'} + $kreisdauer - time())/60; knx_write($ga_restzeit, $restzeit, 9); $gesamtzeit = (time() - $plugin_info{$plugname.'_StartzeitSequenz'})/60; knx_write($ga_gesamtzeit, $gesamtzeit, 9); } } sub ende{ foreach (@Kreise){ plugin_log($plugname, $debugindex++." (SUB ende) Ventil für '$_->{name}' geschlossen") if ($show_debug > 0); knx_write($_->{ga_schalten},0,1); knx_write($_->{ga_restzeit}, 0, 9); } $pluginstatus = 0; $plugin_info{$plugname.'_Status'} = $pluginstatus; $plugin_info{$plugname.'_cycle'} = 0; }
Robert
Kommentar