Ankündigung

Einklappen
Keine Ankündigung bisher.

Steuerung der KWL Cofoair mit diesem Protokol möglich?

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

    so war es-bis zum reset wurde abwechselnd A1 A3 im EASE-Display angezeigt.


    Mit dem ersten Abziehen hat ein Relais angezogen, welches erst nach dem Quitieren abfiel. GGf hat das mit dem
    "Hm - was ich gerade noch sehe:
    2012-06-18 10:31:45.125,KWL V1.0,Aktueller Fehlercode: AE226
    Ich vermute mal das ist nicht AE sondern EA? 226 würde E2 = 11100010 bedeuten? Evtl. Lesefehler? Macht imho keinen sinn..."

    was zu tun!?!

    Grüße,
    Lio

    Kommentar


      Hallo lio

      sehr gerne.

      Ich habe mal das Plugin geändert. Es kann aber so nur immer 1 Fehler (A, E oder EA) auf einmal ausgeben. Dabei ist das ganze nach Hirarchie...

      z.B. Wenn Fehler A1, A3 und A5 anstehen würden, dann würde erstmal nur Fehler A1 ausgegeben. Ist der behoben, wird nur Fehler A3 ausgegeben und ist dann auch dieser Fehler behoben wird noch der Fehler A5 ausgegeben.

      ALSO IMMER NUR 1 FEHLER

      Trotzdem bitte mal testen ob das so funktioniert wie von mir angedacht

      Code:
      # Plugin zur Ansteuerung einer Zender ComfoAir
      # Version 1.1 19.06.2012 BETA
      # Copyright: swiss (https://knx-user-forum.de/members/swiss.html)
      # Aufbau möglichst so, dass man unterhalb der Einstellungen nichts verändern muss!
      #
      #
      
      ####################
      ###Einstellungen:###
      ####################
      
      #Zuordnung Steuerfunktionen zu den Gruppenadressen:
      my $ga_stufeabwesend = '14/7/0'; #1bit Trigger für Stufe "Abwesend". 1=Aktivieren
      my $ga_stufe1 = '14/7/1'; #1bit Trigger für Stufe1. 1=Aktivieren
      my $ga_stufe2 = '14/7/2'; #1bit Trigger für Stufe2. 1=Aktivieren
      my $ga_stufe3 = '14/7/3'; #1bit Trigger für Stufe3. 1=Aktivieren
      my $ga_komforttemp = '14/7/4'; #GA zum setzen der Komforttemperatur
      my $ga_reset_filter = '14/7/5'; #1bit Trigger für das Zurücksetzen des Betriebsstundenzählers des Filters. 1=Reset
      my $ga_reset_error = '14/7/6'; #1bit Trigger für das zurücksetzen der KWL nach einem Fehler. 1=Reset
      
      #Hier werden die Gruppenadressen für die Rückmeldungen vergeben: (Nich vergeben = inaktiv)
      my $ga_status_ventilator_zul = '14/0/0'; #GA DPT5.001 für Status Ventilator Zuluft %
      my $ga_status_ventilator_abl = '14/0/1'; #GA DPT5.001 für Status Ventilator Abluft %
      my $ga_status_bypass_prozent = '14/0/2'; #GA DPT5.001 für Status Bypassklappe %
      my $ga_betriebsstunden_filter = '14/0/3'; #GA DPT16.000 für die Rückmeldung der Betribsstunden des Filters
      my $ga_zustand_badschalter = '14/0/4'; #GA DPT1.001 für die Rückmeldung des Zustandes des Badezimmerschalters
      my $ga_fehler_filter = '14/0/5'; #GA DPT 1.001 für den Zustand des Filters. 0=OK, 1=Filter Voll
      my $ga_fehlercode = '14/0/6'; #GA DPT 16.000 für das augeben des Fehlercodes als Text
      
      #Zuordnung der Namen für die RRD's:
      my $Name_rrd_AUL = 'KWL_Aussenluft'; #Name RRD Aussenluft
      my $Name_rrd_ZUL = 'KWL_Zuluft'; #Name RRD Zuluft
      my $Name_rrd_ABL = 'KWL_Abluft'; #Name RRD Abluft
      my $Name_rrd_FOL = 'KWL_Fortluft'; #Name RRD Fortluft
      
      #Pfad zur seriellen Schnittstelle oder dem USB-Seriell-Wandler:
      my $schnittstelle = '/dev/ttyUSB-1-1';
      
      ######################
      ##ENDE Einstellungen##
      ######################
      
      #Ab hier nichts mehr ändern.
      #Hauptverarbeitung
      
      use Device::SerialPort;
      
      my $return_value2;
      my $daten;
      my $reciv;
      my $reciv_all;
      my $ack = pack("H*","07F3");
      
      
      # Zyklischer Aufruf nach restart, empfang GA oder nach einstellung rrd (typisch 300sek).
      $plugin_info{$plugname.'_cycle'}  = 60; 
      
      #Einrichten der Seriellen Schnittstelle für die Kommunikation mit dem ComfoAir
      my $seriel = Device::SerialPort->new($schnittstelle) || die "Kann $schnittstelle nicht öffnen! ($!)\n";
      $seriel->baudrate(9600);
      $seriel->parity("none");
      $seriel->databits(8);
      $seriel->stopbits(1);
      
      plugin_log($plugname,''); 
      
      if ($msg{'apci'} eq "A_GroupValue_Write"){ #Wenn ein Telegramm vom KNX empfangen wird, ab hier auswerten
          if ($msg{'dst'} eq $ga_stufeabwesend && knx_read($msg{'dst'},0,1) == 1) {
              $daten = "00990101";
              plugin_log($plugname,'Stufe abwesend');
              $return_value2 = command_senden($daten);
          }elsif ($msg{'dst'} eq $ga_stufe1 && knx_read($msg{'dst'},0,1) == 1) {
              $daten = "00990102";
              plugin_log($plugname,'Stufe 1');
              $return_value2 = command_senden($daten);
          }elsif ($msg{'dst'} eq $ga_stufe2 && knx_read($msg{'dst'},0,1) == 1) {
              $daten = "00990103";
              plugin_log($plugname,'Stufe 2');
              $return_value2 = command_senden($daten);
          }elsif ($msg{'dst'} eq $ga_stufe3 && knx_read($msg{'dst'},0,1) == 1) {
              $daten = "00990104";
              plugin_log($plugname,'Stufe 3');
              $return_value2 = command_senden($daten);
          }elsif ($msg{'dst'} eq $ga_komforttemp) {
              my $komforttemp = knx_read($msg{'dst'},0,9.001);
              plugin_log($plugname,'Komforttemp    : ' . $komforttemp . '°C');
              my $temphex = ($komforttemp + 20)*2; #Rechne die Temperatur für die ComfoAir um
              $temphex = sprintf "%x" , $temphex; # Mache aus Integer HEX
              $daten = "00D301" . $temphex;
              $return_value2 = command_senden($daten);
          }elsif ($msg{'dst'} eq $ga_reset_filter && knx_read($msg{'dst'},0,1) == 1) {
              $daten = "00DB0400000001";
              plugin_log($plugname,'Filter zurücksetzen');
              $return_value2 = command_senden($daten);
          }elsif ($msg{'dst'} eq $ga_reset_error && knx_read($msg{'dst'},0,1) == 1) {
              $daten = "00DB0401000000";
              plugin_log($plugname,'Fehler zurücksetzen');
              $return_value2 = command_senden($daten);
          }
          return;
      } else { # zyklischer Aufruf
      
          # Plugin an Gruppenadresse "anmelden", hierdurch wird das Plugin im folgenden bei jedem eintreffen eines Telegramms auf die GA aufgerufen und der obere Teil dieser if-Schleife durchlaufen
          $plugin_subscribe{$ga_stufeabwesend}{$plugname} = 1;
          $plugin_subscribe{$ga_stufe1}{$plugname} = 1;
          $plugin_subscribe{$ga_stufe2}{$plugname} = 1;
          $plugin_subscribe{$ga_stufe3}{$plugname} = 1;
          $plugin_subscribe{$ga_komforttemp}{$plugname} = 1;
          $plugin_subscribe{$ga_reset_filter}{$plugname} = 1;
          $plugin_subscribe{$ga_reset_error}{$plugname} = 1;
          
          $daten = "00D100";
          plugin_log($plugname,'Temperatur abrufen');
          $return_value2 = command_senden($daten);
          
          if($ga_status_ventilator_zul && $ga_status_ventilator_abl){ #Nur wenn beide GA's vergeben sind, dann die Zustände der Ventilatoren abfragen
              $daten = "000B00";
              plugin_log($plugname,'Ventilator Status abrufen');
              $return_value2 = command_senden($daten);
          }
          if($ga_status_bypass_prozent){ #Nur wenn die GA vergeben ist, dann Zustand Bypassklappe abfragen
              $daten = "000D00";
              plugin_log($plugname,'Bypass Zustand abrufen');
              $return_value2 = command_senden($daten);
          }
          if($ga_betriebsstunden_filter){ #Nur wenn die GA vergeben ist, die Betriebsstunden abfragen
              $daten = "00DD00";
              plugin_log($plugname,'Betriebsstunden abrufen');
              $return_value2 = command_senden($daten);
          }
          if($ga_zustand_badschalter){ #Nur wenn die GA vergeben ist, die Binäreingänge abfragen
              $daten = "000300";
              plugin_log($plugname,'Binäreingänge abrufen');
              $return_value2 = command_senden($daten);
          }
      
          #Hier werden die Störmeldungen abgefragt
          $daten = "00D900";
          plugin_log($plugname,'Störungen abrufen');
          $return_value2 = command_senden($daten);
          
          return;
      }
      
      # Ab hier wird das Datenpaket inklusive Checksumme zusammengestellt und an die ComfoAir übertragen
      sub command_senden{
          my $checksum = 0;
          my $data = $_[0];
          
          my $datasum = $data . "AD"; #+173 für die Checksummenberechnung
          my @hex  = map { hex($_) } ($datasum =~ /(..)/g);
          
          
          my $x07warschon = 0;
          
          foreach (@hex) {
              $checksum += ($_) unless $x07warschon; # unless ist dasselbe wie if not/!
              if ($_ == 0x07) { $x07warschon = 1; }
          }
      
          $checksum = sprintf "%x\n" , $checksum; #Mache aus Integer wieder HEX
          $checksum = substr($checksum,-3,2); #Verwede nur die letzten beiden Stellen
          my $command = pack("H*","07F0" . $data . $checksum . "070F");
          my $commandhex = $command;
          
          $commandhex =~ s/(.)/sprintf("0x%x ",ord($1))/eg;
          plugin_log($plugname,'transmit       : ' . $commandhex); #Zeigt im Pluginlog das fertige Datenpaket, dass übertragen wird
          $seriel->write($command); #Befehl an die ComfoAir senden
          $reciv = '';
              
          $|=1;
          my $exit=0;
          while($exit < 25000)
          {
              my ($cin, $sin) = $seriel->read(45);
              if($cin > 0){
              $sin = unpack "H*", $sin;
              $reciv .= $sin;
              $exit=0;
          }else{
              $exit++
          }
      
          if($reciv =~ /070f/i){           
                 $seriel->write($ack); #ACK senden
                  last;
          }
          }    
      
      
              my $test = substr($reciv,0,4);
              if($test eq '07f3'){
                  $reciv = substr($reciv,4); #falls noch ein 07f3 enthalten ist, wir dieses hier entfernt.
                  plugin_log($plugname,'reciv neu      : ' . $reciv);
              }
      
          my $laenge = length($reciv); #Länge des Antworttelegramms ermitteln
      
          if($reciv =~ /07f000D209/i and $laenge == 34){ #Wenn die Temperaturen empfangen wurden und die Länge passt
              
              my $t1 = substr($reciv,12,2);
                      my $t2 = substr($reciv,14,2);
                      my $t3 = substr($reciv,16,2);
                      my $t4 = substr($reciv,18,2);
                      
                      #Hier werden die Temperaturen "decodiert" damit sie einen Sinn ergeben
                      $t1 =  (hex($t1)/2)-20;
                      $t2 =  (hex($t2)/2)-20;
                      $t3 =  (hex($t3)/2)-20;
                      $t4 =  (hex($t4)/2)-20;
                      
                      #Ab hier werden die RRD's mit den aktuellen Temperaturen aktualisiert:
                      update_rrd($Name_rrd_AUL,"",$t1);
                      update_rrd($Name_rrd_ZUL,"",$t2);
                      update_rrd($Name_rrd_ABL,"",$t3);
                      update_rrd($Name_rrd_FOL,"",$t4);
                      
                      plugin_log($plugname,'reciv: T1: ' . $t1 . '°C, T2:' . $t2 . '°C, T3: ' . $t3 . '°C, T4: ' . $t4 . '°C');
      
          }elsif($reciv =~ /07f0000C06/i and $laenge == 28){ #Wenn der Status für die Ventilatoren empfangen wurden
                      my $vent_zul = substr($reciv,10,2);
                      my $vent_abl = substr($reciv,12,2);
                      plugin_log($plugname,'ZUL: ' . hex($vent_zul) . '% ABL: ' . hex($vent_abl) . '%');
                      knx_write($ga_status_ventilator_zul,hex($vent_zul),5.001);
                      knx_write($ga_status_ventilator_abl,hex($vent_abl),5.001);    
          }elsif($reciv =~ /07f0000E04/i and $laenge == 24){ #Wenn der Status für die Bypassklappe empfangen wurden
                      my $bypass_prozent = substr($reciv,10,2);
                      plugin_log($plugname,'Bypass: ' . hex($bypass_prozent) . '%');                
                      knx_write($ga_status_bypass_prozent,hex($bypass_prozent),5.001);
          }elsif($reciv =~ /07f000DE14/i and $laenge == 56){ #Wenn die Rückmeldung der Betriebsstunden empfangen wurden
                      my $betriebsstunden_filter = substr($reciv,40,4);
                      plugin_log($plugname,'Betriebsstunden: ' . hex($betriebsstunden_filter) . 'h');                 
                      knx_write($ga_betriebsstunden_filter,hex($betriebsstunden_filter) . 'h',16.000);
          }elsif($reciv =~ /07f0000402/i){ #Wenn die Rückmeldung der Binäreingänge empfangen wurden
                      my $zustand_badschalter = substr($reciv,12,1);
                      plugin_log($plugname,'Zustand Badezimmerschalter: ' . $zustand_badschalter);                 
                      knx_write($ga_zustand_badschalter,$zustand_badschalter,1.001);
          }elsif($reciv =~ /07f000DA11/i and $laenge == 50){ #Wenn die Rückmeldung der Störmeldungen empfangen wurden
                      my $fehlerA = substr($reciv,10,2);
                      my $fehlerE = substr($reciv,12,2);
                      my $fehlerFilter = substr($reciv,26,2);
                      my $fehlerEA = substr($reciv,28,2);
                      
                      $fehlerA = reverse(pack("H*",$fehlerA)); #Wandle den Wert in Binär und drehe die Reihenfolge um. z.B 0x02 = 00000010 = 010000000
                      $fehlerA = index($fehlerA,'1'); # Zähle an welcher Stelle die 1 auftaucht (von links gelesen) z.B. 01000000 = INDEX 2 = Feler2
      
                      $fehlerE = index(reverse(pack("H*",$fehlerE)),'1');
                      $fehlerEA = index(reverse(pack("H*",$fehlerEA)),'1');
                      
                      if($ga_fehlercode){ #Wenn die GA für das übertragen den Fehlercodes eingertagen wurde, ab hier auswerten
      #                        knx_write($ga_fehlercode,'A' . $fehlerA,16.001);
      #                        knx_write($ga_fehlercode,'E' . hex($fehlerE),16.001);
      #                        knx_write($ga_fehlercode,'EA' . hex($fehlerEA),16.001);
      
                          if($fehlerA > 0){
                              plugin_log($plugname,'Aktueller Fehlercode: A' . $fehlerA);
                              knx_write($ga_fehlercode,'A' . $fehlerA,16.001);
                          }elsif($fehlerE > 0){
                              plugin_log($plugname,'Aktueller Fehlercode: E' . $fehlerE);
                              knx_write($ga_fehlercode,'E' . $fehlerE,16.001);
                          }elsif($fehlerEA > 0){
                              plugin_log($plugname,'Aktueller Fehlercode: EA' . $fehlerEA);
                              knx_write($ga_fehlercode,'EA' . $fehlerEA,16.001);
                          }
                      }
                      if(hex($fehlerFilter) > 0){
                          plugin_log($plugname,'Aktueller Fehler: Filter Voll');
                          knx_write($ga_fehler_filter,1,1);
                      }else{
                  knx_write($ga_fehler_filter,0,1);
                      }               
          }
      }
      Gruss Patrik alias swiss

      Kommentar


        Hi,
        ich habe jetzt mal - sehr kontrolliert - alle 4 Temperaturfühler abgezogen.
        Nachdem ich einen Fühler wieder angesteckt habe wurde ersteinmal ein Reset durchgeführt (power off/on) um dem Fehler zu löschen.
        Das hier sind meine validierten Ergebnisse:
        Code:
        Einer Abgezogen (T1/T3)rechts (AUL) =a1
        2012-06-19 21:41:13.529,ComfoAir,Störungen abrufen
        2012-06-19 21:41:13.529,ComfoAir,transmit       : 0x7 0xf0 0x0 0xd9 0x0 0x86 0x7 0xf
        2012-06-19 21:41:13.576,ComfoAir,reciv neu      : 07f000da11010000000000000000000000000000000099070f
        00000001 = Fehler 1 
        => passt
        
        Einer Abgezogen (T2/T4)rechts (FOL) =a4
        2012-06-19 21:46:22.733,ComfoAir,Störungen abrufen
        2012-06-19 21:46:22.733,ComfoAir,transmit       : 0x7 0xf0 0x0 0xd9 0x0 0x86 0x7 0xf
        2012-06-19 21:46:22.780,ComfoAir,reciv neu      : 07f000da110800000000000000000000000000000000a0070f
        00001000 = Hex 8 = Fehler 4
        => passt
        
        Beide Abgezogen =a1+a4
        2012-06-19 21:42:18.493,ComfoAir,Störungen abrufen
        2012-06-19 21:42:18.493,ComfoAir,transmit       : 0x7 0xf0 0x0 0xd9 0x0 0x86 0x7 0xf
        2012-06-19 21:42:18.540,ComfoAir,reciv neu      : 07f000da110900000000000000000000000000000000a1070f
        00000001 = Fehler 1 
        00001000 = Hex 8 = Fehler 4
        ======================================
        00001001 = Hex 9 = Fehler 1+4 => passt
        
        Einer Abgezogen (T1/T3) links: (ABL) =a3
        2012-06-19 21:48:28.266,ComfoAir,Störungen abrufen
        2012-06-19 21:48:28.266,ComfoAir,transmit       : 0x7 0xf0 0x0 0xd9 0x0 0x86 0x7 0xf
        2012-06-19 21:48:28.313,ComfoAir,reciv neu      : 07f000da1104000000000000000000000000000000009c070f
        00000100 = Hex 4 = Fehler 3
        =>Passt
        
        Einer Abgezogen (T1/T3) links: (ZUL) =A2
        2012-06-19 21:50:31.320,ComfoAir,Störungen abrufen
        2012-06-19 21:50:31.320,ComfoAir,transmit       : 0x7 0xf0 0x0 0xd9 0x0 0x86 0x7 0xf
        2012-06-19 21:50:31.367,ComfoAir,reciv neu      : 07f000da1102000000000000000000000000000000009a070f
        00000010 = hex 2 = Fehler 2
        => passt
        
        Beide abgezogen = a3+a2
        2012-06-19 21:52:35.936,ComfoAir,Störungen abrufen
        2012-06-19 21:52:35.936,ComfoAir,transmit       : 0x7 0xf0 0x0 0xd9 0x0 0x86 0x7 0xf
        2012-06-19 21:52:35.984,ComfoAir,reciv neu      : 07f000da1106000000000000000000000000000000009e070f
        00000010 = Fehler 2
        00000100 = Fehler 3
        ====================
        00000110 = hex 6 = fehler 2+3
        => passt
        
        Alle 4 abgezogen = a1+a2+a3+a4
        2012-06-19 21:53:36.426,ComfoAir,Störungen abrufen
        2012-06-19 21:53:36.426,ComfoAir,transmit       : 0x7 0xf0 0x0 0xd9 0x0 0x86 0x7 0xf
        2012-06-19 21:53:36.472,ComfoAir,reciv neu      : 07f000da110f00000000000000000000000000000000a7070f
        00000001 = Fehler 1 
        00000010 = Fehler 2
        00000100 = Fehler 3
        00001000 = Fehler 4
        ====================
        00001111 = hex F = Fehler 1+2+3+4
        => passt
        Für mich bedeuted das es können mehrere Fehler auf einmal übertragen werden,
        die fehler sind "Binär" und die Umrechnung wie aus den Beispielen zu entnehmen.

        Leider scheint auch die aktuelle Version den Fehler nicht richtig auszugeben
        (@swiss: ich habe nichts am code geändert - in der annahme das du den neuesten Code bei mir laufen hast?)

        @Lio: der Lesefehler ist (vermutlich) einfach nur ein lesefehler bzw. eine Kollision gewesen => einfach ignorieren.

        Gruß
        Thorsten

        Kommentar


          Hallo Thorsten

          Ja die aktuelle Version läuft gerade bei dir.

          Was passt denn genau nicht? Es wird immer nur 1 Fehler ausgegeben, bis dieser behoben ist. Danach der nächste.

          Auch wenn du sämtliche Tempsensoren abklemmst, wird zunächst nur Fehler A1 ausgegeben.

          Ist der Fehler A1 behoben wird Fehler A2 gemeldet usw... bis sämtliche Fehler behoben sind.
          Gruss Patrik alias swiss

          Kommentar


            zumindest im Log war/ist garnichts angekommen - bei allen Fehlern....

            Kommentar


              Ok. Danke fürs Feedback

              Ich habe mal ein paar Debugzeilen eingefügt um das auslesen und auswerten etwas sichtbarer zu machen.

              -> Warscheinlich liegt das Problem daran, dass Hex hier nicht sauber nach Binär gewandelt wird. Ich gehe dem nach. Ich möchte ungern eine Übersetzungstabelle dafür schreiben müssen
              Gruss Patrik alias swiss

              Kommentar


                @Thorsten

                Hast du gerade einen Fehler A1 drauf?? Nicht oder?
                Gruss Patrik alias swiss

                Kommentar


                  Hi,
                  a) Fehler A1? nö... oh - ja - ähm da waren die Fehler A1 bis A4 drauf. (binär 00001111) - hab gerade einen Reset gemacht
                  (war noch vom "Alle 4 abgezogen = a1+a2+a3+a4" Test...).
                  Jetzt ist es sauber. Danke für den Hinweis - dachte das Plugin arbeitet falsch

                  b) die Betriebsstunden: werden die als 14 Byte text übertragen? (DTP16.0001) Ist für die Auswertung schlecht... ich würde da DTP12 nehmen (bin mir nicht sicher ob DTP7 auch reichen würde)

                  Gruß
                  Thorsten

                  Nachtrag zu a) Fehler 00001111 = 0x0F =Fehler A1 bis A4. Das Debug1 zeigt auch 0f, Debug2 aber "Fehler A: 0". Debug 2 ist damit aber falsch, oder?

                  Kommentar


                    Hallo Thorsten

                    Ja das Plugin arbeitet noch nicht ganz richtig. Das bekommen wir aber noch in den Griff. Ich dachte, dass A1 nicht sein konnte und habe noch iene andere Version versucht. Ich habe dass mal zurück gesetzt. Nun sollte Fehler A eigentlich tun.

                    Wegen den Beriebsstunden... Das müsste man testen. Ist aber sehr eifach zu machen. Ku kannst ja mal mit Zeile 233 etwas experimentieren

                    Und könntest du für mich nochmal einen Fehler simulieren und den dann wie zuvor unquitiert lassen? so kann ich ein wehnig testen bis es passt.
                    Gruss Patrik alias swiss

                    Kommentar


                      Sooo...

                      Nach langem testen funktioniert in der neusten Version auch die Ausgabe des Fehlercodes als 14Byte-Text. Damit kann man z.B. in der CV einfach ein Mapping machen um die Fehler im Klartext anzuzeigen oder man nimmt ggf. wenn es dann so weit ist einfach das Handbuch und schaut nach

                      Code:
                      # Plugin zur Ansteuerung einer Zender ComfoAir
                      # Version 1.2 21.06.2012 BETA
                      # Copyright: swiss (https://knx-user-forum.de/members/swiss.html)
                      # Aufbau möglichst so, dass man unterhalb der Einstellungen nichts verändern muss!
                      #
                      #
                      
                      ####################
                      ###Einstellungen:###
                      ####################
                      
                      #Zuordnung Steuerfunktionen zu den Gruppenadressen:
                      my $ga_stufeabwesend = '14/7/0'; #1bit Trigger für Stufe "Abwesend". 1=Aktivieren
                      my $ga_stufe1 = '14/7/1'; #1bit Trigger für Stufe1. 1=Aktivieren
                      my $ga_stufe2 = '14/7/2'; #1bit Trigger für Stufe2. 1=Aktivieren
                      my $ga_stufe3 = '14/7/3'; #1bit Trigger für Stufe3. 1=Aktivieren
                      my $ga_komforttemp = '14/7/4'; #GA DPT 9.001 zum setzen der Komforttemperatur
                      my $ga_reset_filter = '14/7/5'; #1bit Trigger für das Zurücksetzen des Betriebsstundenzählers des Filters. 1=Reset
                      my $ga_reset_error = '14/7/6'; #1bit Trigger für das zurücksetzen der KWL nach einem Fehler. 1=Reset
                      
                      #Hier werden die Gruppenadressen für die Rückmeldungen vergeben: (Nich vergeben = inaktiv)
                      my $ga_status_ventilator_zul = '14/4/3'; #GA DPT5.001 für Status Ventilator Zuluft %
                      my $ga_status_ventilator_abl = '14/4/4'; #GA DPT5.001 für Status Ventilator Abluft %
                      my $ga_status_bypass_prozent = '14/4/5'; #GA DPT5.001 für Status Bypassklappe %
                      my $ga_betriebsstunden_filter = '14/4/6'; #GA DPT16.000 für die Rückmeldung der Betribsstunden des Filters
                      my $ga_zustand_badschalter = '14/0/4'; #GA DPT1.001 für die Rückmeldung des Zustandes des Badezimmerschalters
                      my $ga_fehler_filter = '14/0/5'; #GA DPT 1.001 für den Zustand des Filters. 0=OK, 1=Filter Voll
                      my $ga_fehlercode = '14/0/6'; #GA DPT 16.000 für das augeben des Fehlercodes als Text
                      
                      #Zuordnung der Namen für die RRD's:
                      my $Name_rrd_AUL = 'KWL_Aussenluft'; #Name RRD Aussenluft
                      my $Name_rrd_ZUL = 'KWL_Zuluft'; #Name RRD Zuluft
                      my $Name_rrd_ABL = 'KWL_Abluft'; #Name RRD Abluft
                      my $Name_rrd_FOL = 'KWL_Fortluft'; #Name RRD Fortluft
                      
                      #Pfad zur seriellen Schnittstelle oder dem USB-Seriell-Wandler:
                      my $schnittstelle = '/dev/ttyUSB-1-1';
                      
                      ######################
                      ##ENDE Einstellungen##
                      ######################
                      
                      #Ab hier nichts mehr ändern.
                      #Hauptverarbeitung
                      
                      use Device::SerialPort;
                      
                      my $return_value2;
                      my $daten;
                      my $reciv;
                      my $reciv_all;
                      my $ack = pack("H*","07F3");
                      
                      
                      # Zyklischer Aufruf nach restart, empfang GA oder nach einstellung rrd (typisch 300sek).
                      $plugin_info{$plugname.'_cycle'}  = 8; 
                      
                      #Einrichten der Seriellen Schnittstelle für die Kommunikation mit dem ComfoAir
                      my $seriel = Device::SerialPort->new($schnittstelle) || die "Kann $schnittstelle nicht öffnen! ($!)\n";
                      $seriel->baudrate(9600);
                      $seriel->parity("none");
                      $seriel->databits(8);
                      $seriel->stopbits(1);
                      
                      plugin_log($plugname,''); 
                      
                      if ($msg{'apci'} eq "A_GroupValue_Write"){ #Wenn ein Telegramm vom KNX empfangen wird, ab hier auswerten
                          if ($msg{'dst'} eq $ga_stufeabwesend && knx_read($msg{'dst'},0,1) == 1) {
                              $daten = "00990101";
                              plugin_log($plugname,'Stufe abwesend');
                              $return_value2 = command_senden($daten);
                          }elsif ($msg{'dst'} eq $ga_stufe1 && knx_read($msg{'dst'},0,1) == 1) {
                              $daten = "00990102";
                              plugin_log($plugname,'Stufe 1');
                              $return_value2 = command_senden($daten);
                          }elsif ($msg{'dst'} eq $ga_stufe2 && knx_read($msg{'dst'},0,1) == 1) {
                              $daten = "00990103";
                              plugin_log($plugname,'Stufe 2');
                              $return_value2 = command_senden($daten);
                          }elsif ($msg{'dst'} eq $ga_stufe3 && knx_read($msg{'dst'},0,1) == 1) {
                              $daten = "00990104";
                              plugin_log($plugname,'Stufe 3');
                              $return_value2 = command_senden($daten);
                          }elsif ($msg{'dst'} eq $ga_komforttemp) {
                              my $komforttemp = knx_read($msg{'dst'},0,9.001);
                              plugin_log($plugname,'Komforttemp    : ' . $komforttemp . '°C');
                              my $temphex = ($komforttemp + 20)*2; #Rechne die Temperatur für die ComfoAir um
                              $temphex = sprintf "%x" , $temphex; # Mache aus Integer HEX
                              $daten = "00D301" . $temphex;
                              $return_value2 = command_senden($daten);
                          }elsif ($msg{'dst'} eq $ga_reset_filter && knx_read($msg{'dst'},0,1) == 1) {
                              $daten = "00DB0400000001";
                              plugin_log($plugname,'Filter zurücksetzen');
                              $return_value2 = command_senden($daten);
                          }elsif ($msg{'dst'} eq $ga_reset_error && knx_read($msg{'dst'},0,1) == 1) {
                              $daten = "00DB0401000000";
                              plugin_log($plugname,'Fehler zurücksetzen');
                              $return_value2 = command_senden($daten);
                          }
                          return;
                      } else { # zyklischer Aufruf
                      
                          # Plugin an Gruppenadresse "anmelden", hierdurch wird das Plugin im folgenden bei jedem eintreffen eines Telegramms auf die GA aufgerufen und der obere Teil dieser if-Schleife durchlaufen
                          $plugin_subscribe{$ga_stufeabwesend}{$plugname} = 1;
                          $plugin_subscribe{$ga_stufe1}{$plugname} = 1;
                          $plugin_subscribe{$ga_stufe2}{$plugname} = 1;
                          $plugin_subscribe{$ga_stufe3}{$plugname} = 1;
                          $plugin_subscribe{$ga_komforttemp}{$plugname} = 1;
                          $plugin_subscribe{$ga_reset_filter}{$plugname} = 1;
                          $plugin_subscribe{$ga_reset_error}{$plugname} = 1;
                          
                          $daten = "00D100";
                          plugin_log($plugname,'Temperatur abrufen');
                          $return_value2 = command_senden($daten);
                          
                          if($ga_status_ventilator_zul && $ga_status_ventilator_abl){ #Nur wenn beide GA's vergeben sind, dann die Zustände der Ventilatoren abfragen
                              $daten = "000B00";
                              plugin_log($plugname,'Ventilator Status abrufen');
                              $return_value2 = command_senden($daten);
                          }
                          if($ga_status_bypass_prozent){ #Nur wenn die GA vergeben ist, dann Zustand Bypassklappe abfragen
                              $daten = "000D00";
                              plugin_log($plugname,'Bypass Zustand abrufen');
                              $return_value2 = command_senden($daten);
                          }
                          if($ga_betriebsstunden_filter){ #Nur wenn die GA vergeben ist, die Betriebsstunden abfragen
                              $daten = "00DD00";
                              plugin_log($plugname,'Betriebsstunden abrufen');
                              $return_value2 = command_senden($daten);
                          }
                          if($ga_zustand_badschalter){ #Nur wenn die GA vergeben ist, die Binäreingänge abfragen
                              $daten = "000300";
                              plugin_log($plugname,'Binäreingänge abrufen');
                              $return_value2 = command_senden($daten);
                          }
                      
                          #Hier werden die Störmeldungen abgefragt
                          $daten = "00D900";
                          plugin_log($plugname,'Störungen abrufen');
                          $return_value2 = command_senden($daten);
                          
                          return;
                      }
                      
                      # Ab hier wird das Datenpaket inklusive Checksumme zusammengestellt und an die ComfoAir übertragen
                      sub command_senden{
                          my $checksum = 0;
                          my $data = $_[0];
                          
                          my $datasum = $data . "AD"; #+173 für die Checksummenberechnung
                          my @hex  = map { hex($_) } ($datasum =~ /(..)/g);
                          
                          
                          my $x07warschon = 0;
                          
                          foreach (@hex) {
                              $checksum += ($_) unless $x07warschon; # unless ist dasselbe wie if not/!
                              if ($_ == 0x07) { $x07warschon = 1; }
                          }
                      
                          $checksum = sprintf "%x\n" , $checksum; #Mache aus Integer wieder HEX
                          $checksum = substr($checksum,-3,2); #Verwede nur die letzten beiden Stellen
                          my $command = pack("H*","07F0" . $data . $checksum . "070F");
                          my $commandhex = $command;
                          
                          $commandhex =~ s/(.)/sprintf("0x%x ",ord($1))/eg;
                      #    plugin_log($plugname,'transmit       : ' . $commandhex); #Zeigt im Pluginlog das fertige Datenpaket, dass übertragen wird
                          $seriel->write($command); #Befehl an die ComfoAir senden
                          $reciv = '';
                              
                          $|=1;
                          my $exit=0;
                          while($exit < 25000)
                          {
                              my ($cin, $sin) = $seriel->read(45);
                              if($cin > 0){
                              $sin = unpack "H*", $sin;
                              $reciv .= $sin;
                              $exit=0;
                          }else{
                              $exit++
                          }
                      
                          if($reciv =~ /070f/i){           
                                 $seriel->write($ack); #ACK senden
                                  last;
                          }
                          }    
                      
                      
                              my $test = substr($reciv,0,4);
                              if($test eq '07f3'){
                                  $reciv = substr($reciv,4); #falls noch ein 07f3 enthalten ist, wir dieses hier entfernt.
                      #            plugin_log($plugname,'reciv neu      : ' . $reciv);
                              }
                      
                          my $laenge = length($reciv); #Länge des Antworttelegramms ermitteln
                      
                          if($reciv =~ /07f000D209/i and $laenge == 34){ #Wenn die Temperaturen empfangen wurden und die Länge passt
                              
                              my $t1 = substr($reciv,12,2);
                                      my $t2 = substr($reciv,14,2);
                                      my $t3 = substr($reciv,16,2);
                                      my $t4 = substr($reciv,18,2);
                                      
                                      #Hier werden die Temperaturen "decodiert" damit sie einen Sinn ergeben
                                      $t1 =  (hex($t1)/2)-20;
                                      $t2 =  (hex($t2)/2)-20;
                                      $t3 =  (hex($t3)/2)-20;
                                      $t4 =  (hex($t4)/2)-20;
                                      
                                      #Ab hier werden die RRD's mit den aktuellen Temperaturen aktualisiert:
                                      update_rrd($Name_rrd_AUL,"",$t1);
                                      update_rrd($Name_rrd_ZUL,"",$t2);
                                      update_rrd($Name_rrd_ABL,"",$t3);
                                      update_rrd($Name_rrd_FOL,"",$t4);
                                      
                                      plugin_log($plugname,'reciv: AUL: ' . $t1 . '°C, ZUL:' . $t2 . '°C, ABL: ' . $t3 . '°C, FOL: ' . $t4 . '°C');
                      
                          }elsif($reciv =~ /07f0000C06/i and $laenge == 28){ #Wenn der Status für die Ventilatoren empfangen wurden
                                      my $vent_zul = substr($reciv,10,2);
                                      my $vent_abl = substr($reciv,12,2);
                                      plugin_log($plugname,'ZUL: ' . hex($vent_zul) . '% ABL: ' . hex($vent_abl) . '%');
                                      knx_write($ga_status_ventilator_zul,hex($vent_zul),5.001);
                                      knx_write($ga_status_ventilator_abl,hex($vent_abl),5.001);    
                          }elsif($reciv =~ /07f0000E04/i and $laenge == 24){ #Wenn der Status für die Bypassklappe empfangen wurden
                                      my $bypass_prozent = substr($reciv,10,2);
                                      plugin_log($plugname,'Bypass: ' . hex($bypass_prozent) . '%');                
                                      knx_write($ga_status_bypass_prozent,hex($bypass_prozent),5.001);
                          }elsif($reciv =~ /07f000DE14/i and $laenge == 56){ #Wenn die Rückmeldung der Betriebsstunden empfangen wurden
                                      my $betriebsstunden_filter = substr($reciv,40,4);
                                      plugin_log($plugname,'Betriebsstunden: ' . hex($betriebsstunden_filter) . 'h');                 
                                      knx_write($ga_betriebsstunden_filter,hex($betriebsstunden_filter) . 'h',16.000);
                          }elsif($reciv =~ /07f0000402/i){ #Wenn die Rückmeldung der Binäreingänge empfangen wurden
                                      my $zustand_badschalter = substr($reciv,12,1);
                                      plugin_log($plugname,'Zustand Badezimmerschalter: ' . $zustand_badschalter);                 
                                      knx_write($ga_zustand_badschalter,$zustand_badschalter,1.001);
                          }elsif($reciv =~ /07f000DA11/i and $laenge == 50){ #Wenn die Rückmeldung der Störmeldungen empfangen wurden
                                      my $fehlerAlo = substr($reciv,10,2);
                                      my $fehlerAhi = substr($reciv,34,2);
                                      my $fehlerE = substr($reciv,12,2);
                                      my $fehlerFilter = substr($reciv,26,2);
                                      my $fehlerEA = substr($reciv,28,2);
                                      
                              my $numAlo = 'A';
                              my $numAhi = 'A';
                              my $numE = 'A';
                              my $numEA = 'A';
                              
                              $numAlo .= unpack("B*",pack("H*",$fehlerAlo));
                              $numAhi .= unpack("B*",pack("H*",$fehlerAhi));
                              $numE .= unpack("B*",pack("H*",$fehlerE));
                              $numEA .= unpack("B*",pack("H*",$fehlerEA));
                                              
                                      $fehlerAlo = reverse($numAlo); #Wandle den Wert in Binär und drehe die Reihenfolge um. z.B 0x02 = 00000010 = 010000000
                                      $fehlerAlo = index($fehlerAlo,'1')+1; # Zähle an welcher Stelle die 1 auftaucht (von links gelesen) z.B. 01000000 = INDEX 2 = Feler2
                      
                              if($fehlerAhi ne '00'){
                                  $fehlerAhi = index(reverse($numAhi),'1')+9;
                              }else{
                                  $fehlerAhi = '';
                              }
                                      $fehlerE = index(reverse($numE),'1')+1;
                                      $fehlerEA = index(reverse($numEA),'1')+1;
                                      
                                      if($fehlerAhi == 16){$fehlerAhi = 0;}
                                      
                                      if($ga_fehlercode){ #Wenn die GA für das übertragen den Fehlercodes eingertagen wurde, ab hier auswerten
                      
                                          if($fehlerAlo > 0){
                                              plugin_log($plugname,'Aktueller Fehlercode: A' . $fehlerAlo);
                                              knx_write($ga_fehlercode,'A' . $fehlerAlo,16.001);
                                          }elsif($fehlerAhi ne ''){
                                              plugin_log($plugname,'Aktueller Fehlercode: A' . $fehlerAhi);
                                              knx_write($ga_fehlercode,'A' . $fehlerAhi,16.001);                        
                                          }elsif($fehlerE > 0){
                                              plugin_log($plugname,'Aktueller Fehlercode: E' . $fehlerE);
                                              knx_write($ga_fehlercode,'E' . $fehlerE,16.001);
                                          }elsif($fehlerEA > 0){
                                              plugin_log($plugname,'Aktueller Fehlercode: EA' . $fehlerEA);
                                              knx_write($ga_fehlercode,'EA' . $fehlerEA,16.001);
                                          }
                                      }
                                      if(hex($fehlerFilter) > 0){
                                          plugin_log($plugname,'Aktueller Fehler: Filter Voll');
                                          knx_write($ga_fehler_filter,1,1);
                                      }else{
                                  knx_write($ga_fehler_filter,0,1);
                                      }               
                          }
                      }
                      Gruss Patrik alias swiss

                      Kommentar


                        Patrik: machs doch ins SVN, im Zweifel im Stundentakt, das kost nix, tut nicht weh und ist für Entwicklung da - und man behält mit passenden Tools den Überblick

                        Makki
                        EIB/KNX & WireGate & HS3, Russound,mpd,vdr,DM8000, DALI, DMX
                        -> Bitte KEINE PNs!

                        Kommentar


                          Hallo makki

                          Ja ich denke auch, dass das Plugin langsam den Stand erreicht hat, in dem es im SVN am besten aufgehoben ist. Ich mach das heute Abend
                          Gruss Patrik alias swiss

                          Kommentar


                            Soo...

                            Also. Ab sofort ist die jeweils aktuelle Version im SVN unter folgendem Link zu finden:

                            SourceForge.net Repository - [openautomation] Log of /wiregate/plugin/generic/ComfoAir_kwl.pl

                            Hier werden nur noch Updatemeldungen so wie "Support anfragen" und Erweiterungswünsche eingestellt

                            Aktuelle Version: 1.3 BETA

                            Änderungen:

                            - Fehler bei der übertragung des Fehlercodes als 14Byte-Text behoben. Nun wird bei behobenem Fehler "keiner" auf den BUS gesendet um die Fehlermeldung in der Visu zurückzusetzen.
                            Gruss Patrik alias swiss

                            Kommentar


                              Zitat von makki Beitrag anzeigen
                              machs doch ins SVN, im Zweifel im Stundentakt, das kost nix, tut nicht weh und ist für Entwicklung da - und man behält mit passenden Tools den Überblick

                              Makki

                              sicherlich richtig, einzig der Dank und der Respekt an den Entwickler geht darin etwas verloren...
                              ...in diesem sinne: helo world

                              Kommentar


                                Naja auch wenn die Update's hier im Forum veröffentllicht werden...

                                Ich wette die meisten die das Plugin bei sich zuhause einsetzen melden sich auch hier nicht zu Wort. Also macht es am Ende auch keinen Unterschied.

                                Trotzdem ist es schön wenn man ab und zu höhrt, dass der eigene Aufwand geschätzt wird
                                Gruss Patrik alias swiss

                                Kommentar

                                Lädt...
                                X