Ankündigung

Einklappen
Keine Ankündigung bisher.

bewaesserung.pl - mein erstes Plugin zur Gartenbewässerung

Einklappen
Dieses Thema ist geschlossen.
X
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    #31
    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.

    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;
    }
    lg
    Robert

    Kommentar


      #32
      Zitat von Robert_Mini Beitrag anzeigen
      Sodala. Hab nun ein paar Dinge überarbeitet
      Hi Robert,

      super, vielen Dank! Funktioniert klasse :-)

      Eine kleine Anmerkung hätte ich noch: wenn der Zyklus beendet wurde (nach der abgelaufenen Zeit oder wenn man "Freigabe gesamt" deaktiviert) sollte mMn der Status von "Bewässerung starten" (ga_plugintrigger) auf "0" gesetzt werden oder?

      Danke und viele Grüße,
      Micha

      Kommentar


        #33
        Hallo Micha!

        Sollte eigentlich schon so funktionieren.
        Sub ende() setzt die Variable $plugnname.'_Status' auf 0. Am Ende der Hauptroutine wird dieser Wert auf die status-GA des Plugins geschickt.

        Der Switch für die Sequenz in der Visu hört auf diese GA und wird damit auf AUS rückgesetzt (hatte ich bereits so getestet). Der Switch hat deshalb 2 Adresse, wobei die 2. Adresse mit read auf die Status-Rückmeldung "hört".

        Die ga_plugintrigger auf 0 setzten ist aus meiner Sicht nicht erforderlich (Vergleiche Licht EIN über GA_Licht und Zentral aus => GA Licht wird nicht mit 0 gesendet, da das Objekt bereits auf die Zentral-Aus GA hört. Der korrekte Status steht immer im Status-Objekt).

        Gerne weitere Anregungen/Kommentare...

        lg
        Robert

        Kommentar


          #34
          Zitat von Robert_Mini Beitrag anzeigen
          Sollte eigentlich schon so funktionieren.
          Tut es auch :-) Aus irgendeinem Grund hatte ich die read-Adresse in der Visu auskommentiert...

          Danke und schönen Abend noch!

          VG
          Micha

          Kommentar


            #35
            Zitat von mivola Beitrag anzeigen
            Bei uns wird der Garten erst dieses Jahr gemacht - deshalb kann ich es leider nicht testen. Aber die Beschreibung hört sich gut an :-)

            Nur eine Sache: sowas gehört ins SVN (wg Account am besten an makki wenden), sonst geht es hier im Forum irgendwann unter...

            VG
            Micha
            So, nun will ich mal eine Rückmeldung geben. Der Garten ist fertig, der Rasen gesät und der Beregnung läuft. Das Plugin ist wirklich spitze :-) Danke dafür!

            Noch eine allgemeine Frage damit ich mal ein Gefühl bekomme: wie lange lasst ihr den Rasen (bzw die Saat) bewässern, wenn es wie jetzt nicht allzu warm (20°C) und trocken ist?

            VG
            Micha

            Kommentar


              #36
              Gute Frage.
              Meine Untergrenze, dass überhaupt beregnet wird ist 20°C.

              Darüber:
              - Alle 3 Tage bis 25°C
              - Alle 2 Tage bis 30°C
              - Täglich ab 30°C

              Beregnungsdauer ist 15-18min bei den größeren Flächen mit Turbinenberegnern, wobei die Überdeckung 2-3 ist. Bei Sprühern habe ich im Moment 8min.
              Das sollte etwa 15mm Beaufschlagung entsprechen, was meiner Einschätzung auch wurzeltief ist.

              Den globalen Faktor möchte ich künftig zusätzlich noch temperaturabhängig anpassen.

              Anmerkung: bin auch noch in der Findungsphase.
              Für alle die mir jetzt sagen wollen, das ist zu oft und nicht wurzeltief...
              Wir haben etwa 50cm Erdreich, dann Schotter und die Oberfläche wird durch den Wind zusätzlich ausgetrocknet.

              Btw: Habe die Automatik in einem weiteren Plugin umgesetzt, falls Interesse besteht, kann ich das am WE posten.

              lg
              Robert

              Kommentar


                #37
                Zitat von Robert_Mini Beitrag anzeigen
                Btw: Habe die Automatik in einem weiteren Plugin umgesetzt, falls Interesse besteht, kann ich das am WE posten.
                Würde mich schon interessieren. Ich habe das aktuell als 2-Zeiler im Logikprozessor.

                VG
                Micha

                Kommentar


                  #38
                  Hallo
                  Gibt es was neues zum Plugin.
                  Habe die Version aus den SVN installiert und dann festgestellt das die aus Beitrag #31 wohl neuer ist.
                  Die passt aber auch nicht zu der CV Config GAs.
                  Gruß Netfritz
                  KNX & Wago 750-849 ,Wiregate u. Cometvisu, iPad 3G 64GB.
                  WP Alpha-Innotec WWC130HX (RS232-Moxa-LAN),Solaranlage für Brauchwasser und Heizung.
                  PV-Anlage = SMA Webbox2.0 , SunnyBoy 4000TL, Sharp 4kWP

                  Kommentar


                    #39
                    Hi,

                    ich grabe den alten Thread jetzt wieder mal aus.
                    Ich hatte grundsätzlich ein sehr ähnliches eigenes Plugin von mir im Einsatz, das hier ist aber deutlich flexibler, deshalb stelle ich da jetzt um.

                    Im Großen und Ganzen ist auch alles verständlich, nur ein paar Kleinigkeiten muss ich nachfragen:
                    - $ga_plugintrigger ist Bewässerung starten in der Visu
                    - $ga_pluginstatus wird in der Visu nicht verwendet
                    - $ga_gesamtzeit ist die Zeit rechts neben dem Switch "Bewässerung starten"
                    - $ga_zeitfaktor, $ga_resetdauer und $ga_freigabe_gesamt sind eh klar.
                    - Was macht der trigger Freigeben, rechts neben dem Trigger Standardzeiten reset? Da weiß ich nicht, welche GA ich rein schreiben soll.

                    Ansonsten werde ich das die nächsten Tage mal testen, vorbereitet ist alles, muss es nur noch einspielen. Bin schon gespannt. :-)

                    Danke
                    Marcus

                    Kommentar


                      #40
                      Hallo Marcus,

                      du musst Dir eine GA "AlleFreigeben" anlegen. Diese liegt mit einem Read auf allen Buttons "Freigegeben/Gesperrt" der Kreise.
                      Mit einem Druck auf "Alle Freigeben" sendet diese "0", alle Buttons "Freigegeben/Gesperrt" hören auf "0".
                      Vielleicht etwas umständlich ausgedrückt....

                      Die GA "AlleFreigeben" ist hier im Beispiel der xml die "5/4/107".

                      Edit: Das ganze spielt sich nur in der Visu ab.

                      Gruß,
                      Dennis

                      Kommentar


                        #41
                        Also kurz gesagt, wenn man "Alle Freigeben" auf gesperrt setzt, gehen alle einzelnen Kreise auch auf gesperrt, bzw. umgekehrt?

                        Kommentar


                          #42
                          Genau. In der Beispiel-Visu ist der Button aber nur für das Freigeben angelegt. D.h. er sendet nur eine "0".

                          Im Beispiel als fett markiert:

                          Code:
                          <group name="Parameter Bewässerungskreise">
                                    <trigger value="1">
                                      <layout colspan="4"/>
                                      <label>Standardzeiten wiederherstellen</label>
                                      <address transform="DPT:1.001" mode="readwrite">5/4/108</address>
                                    </trigger>
                                    <[B]trigger value="0" mapping="Freigeben">[/B]
                                      <layout colspan="2"/>
                                      <address transform="DPT:1.001" mode="readwrite">[B]5/4/107[/B]</address>
                                    </trigger>
                                    <infotrigger uplabel="+" downlabel="-" upvalue="1" downvalue="-1" align="left" infoposition="right" format="%.0f min" change="absolute" min="0" max="20">
                                      <layout colspan="4"/>
                                      <label><icon name="time_timer"/>Dauer Soll</label>
                                      <address transform="DPT:9.001" mode="readwrite">5/4/114</address>
                                    </infotrigger>
                                    <switch mapping="Sperre" styling="GreenRed">
                                      <layout colspan="2"/>
                                      <label></label>
                                      <address transform="DPT:1.001" mode="readwrite">5/4/111</address>
                                      <address transform="DPT:1.001" mode="[B]read">5/4/107[/B]</address>
                                    </switch>
                                    <infotrigger uplabel="+" downlabel="-" upvalue="1" downvalue="-1" align="left" infoposition="right" format="%.0f min" change="absolute" min="0" max="20">
                                      <layout colspan="4"/>
                                      <label><icon name="time_timer"/>Dauer Soll</label>
                                      <address transform="DPT:9.001" mode="readwrite">5/4/119</address>
                                    </infotrigger>
                                    <switch mapping="Sperre" styling="GreenRed">
                                      <layout colspan="2"/>
                                      <label></label>
                                      <address transform="DPT:1.001" mode="readwrite">5/4/116</address>
                                      <address transform="DPT:1.001" mode="[B]read">5/4/107[/B]</address>
                                    </switch>

                          Kommentar

                          Lädt...
                          X