Ankündigung

Einklappen
Keine Ankündigung bisher.

ComfoAir Steuerung über RS232

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    [WireGate-Plugin] ComfoAir Steuerung über RS232

    So...

    Nachdem das Plugin nun bei mehreren Testern über eine längere Zeit im produktiven Einsatz ist stelle ich es mal in der aktuellen Version hier ein.

    Mit dem Plugin ist es möglich die Zehnder ComfoAir direkt über einen USB-Seriell Wandler an das Wiregate anzubinden und über KNX zu steuern.

    Des weiteren können auch diverse Rückmeldungen auf dem KNX ausgegeben werden.

    EDIT: Neue Version mit separater Config

    Plugin:
    Code:
    # Plugin zur Ansteuerung einer Zender ComfoAir
    # Version 1.5 14.08.2012 BETA
    # Copyright: swiss (https://knx-user-forum.de/members/swiss.html)
    # Aufbau moeglichst so, dass man unterhalb der Einstellungen nichts veraendern muss!
    #
    #
    
    ####################
    ###Einstellungen:###
    ####################
    
    
    #BITTE ab sofort die Einstellungen unter conf.d vornemen. Damit bleiben die Einstellungen auch bei einem Update erhalten.
    
    
    ######################
    ##ENDE Einstellungen##
    ######################
    
    
    #Ab hier nichts mehr aendern.
    #Hauptverarbeitung
    
    
    #Erzeuge Variablen fuer die Zuordnung Steuerfunktionen zu den Gruppenadressen:
    my $ga_stufeabwesend = ''; #1bit Trigger fuer Stufe "Abwesend". 1=Aktivieren
    my $ga_stufe1 = ''; #1bit Trigger fuer Stufe1. 1=Aktivieren
    my $ga_stufe2 = ''; #1bit Trigger fuer Stufe2. 1=Aktivieren
    my $ga_stufe3 = ''; #1bit Trigger fuer Stufe3. 1=Aktivieren
    my $ga_komforttemp = ''; #GA DPT 9.001 zum setzen der Komforttemperatur
    my $ga_reset_filter = ''; #1bit Trigger fuer das Zuruecksetzen des Betriebsstundenzaehlers des Filters. 1=Reset
    my $ga_reset_error = ''; #1bit Trigger fuer das zuruecksetzen der KWL nach einem Fehler. 1=Reset
    
    #Hier werden die Gruppenadressen fuer die Rueckmeldungen vergeben: (Nich vergeben = inaktiv)
    my $ga_status_ventilator_zul = ''; #GA DPT5.001 fuer Status Ventilator Zuluft %
    my $ga_status_ventilator_abl = ''; #GA DPT5.001 fuer Status Ventilator Abluft %
    my $ga_status_bypass_prozent = ''; #GA DPT5.001 fuer Status Bypassklappe %
    my $ga_betriebsstunden_filter = ''; #GA DPT16.000 fuer die Rueckmeldung der Betribsstunden des Filters
    my $ga_zustand_badschalter = ''; #GA DPT1.001 fuer die Rueckmeldung des Zustandes des Badezimmerschalters
    my $ga_fehler_filter = ''; #GA DPT 1.001 fuer den Zustand des Filters. 0=OK, 1=Filter Voll
    my $ga_fehlercode = ''; #GA DPT 16.000 fuer das augeben des Fehlercodes als Text
    
    #Hier werden die Gruppenadressen für die Temperaturen vergeben: (Nicht vergeben=inaktiv)
    my $ga_aul_temp = ''; #GA DPT 9.001 für die Aussenlufttemperatur
    my $ga_zul_temp = ''; #GA DPT 9.001 für die Zulufttemperatur
    my $ga_abl_temp = ''; #GA DPT 9.001 für die Ablufttemperatur
    my $ga_fol_temp = ''; #GA DPT 9.001 für die Fortlufttemperatur
    
    #Zuordnung der Namen fuer 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';
    
    &readConf(); #conf.d einlesen
    
    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'}  = 25; 
    
    #Einrichten der Seriellen Schnittstelle fuer 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 fuer 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 Binaereingaenge abfragen
            $daten = "000300";
            plugin_log($plugname,'Binäreingänge abrufen');
            $return_value2 = command_senden($daten);
        }
    
        #Hier werden die Stoermeldungen 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 uebertragen
    sub command_senden{
        my $checksum = 0;
        my $data = $_[0];
        
        my $datasum = $data . "AD"; #+173 fuer 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); #Laenge 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;
                    
                    #Wenn die GA's vergebenwurde, die Temperaturen auf die GA's senden
                    if($ga_aul_temp ne ''){knx_write($ga_aul_temp,$t1,9.001);}
                    if($ga_zul_temp ne ''){knx_write($ga_zul_temp,$t2,9.001);}
                    if($ga_abl_temp ne ''){knx_write($ga_abl_temp,$t3,9.001);}
                    if($ga_fol_temp ne ''){knx_write($ga_fol_temp,$t4,9.001);}
                    
                    #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,'AUL: ' . $t1 . '°C, ZUL:' . $t2 . '°C, ABL: ' . $t3 . '°C, FOL: ' . $t4 . '°C');
    
        }elsif($reciv =~ /07f0000C06/i and $laenge == 28){ #Wenn der Status fuer 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 fuer 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 Rueckmeldung 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 Rueckmeldung der Binaereingaenge 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 Rueckmeldung der Stoermeldungen 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 Binaer und drehe die Reihenfolge um. z.B 0x02 = 00000010 = 010000000
                    $fehlerAlo = index($fehlerAlo,'1')+1; # Zaehle 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 fuer das uebertragen 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);
                        }else{
                            plugin_log($plugname,'Aktueller Fehlercode: keiner' );
                            knx_write($ga_fehlercode,'keiner' . $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);
                    }               
        }
    }
    
    sub readConf
    {
        my $confFile = '/etc/wiregate/plugin/generic/conf.d/'.basename($plugname,'.pl').'.conf';
        if (! -f $confFile)
        {
            plugin_log($plugname, " no conf file [$confFile] found."); 
        }
        else
        {
            plugin_log($plugname, " reading conf file [$confFile]."); 
            open(CONF, $confFile);
            my @lines = <CONF>;
            close($confFile);
            my $result = eval("@lines");
            ($result) and plugin_log($plugname, "conf file [$confFile] returned result[$result]");
            if ($@) 
            {
                plugin_log($plugname, " conf file [$confFile] returned:");
                my @parts = split(/\n/, $@);
                plugin_log($plugname, " --> $_") foreach (@parts);
            }
        }
    } # readConf
    config:

    Code:
    ####################
    ###Einstellungen:###
    ####################
    
    #Zuordnung Steuerfunktionen zu den Gruppenadressen:
    $ga_stufeabwesend = '14/7/0'; #1bit Trigger fuer Stufe "Abwesend". 1=Aktivieren
    $ga_stufe1 = '14/7/1'; #1bit Trigger fuer Stufe1. 1=Aktivieren
    $ga_stufe2 = '14/7/2'; #1bit Trigger fuer Stufe2. 1=Aktivieren
    $ga_stufe3 = '14/7/3'; #1bit Trigger fuer Stufe3. 1=Aktivieren
    $ga_komforttemp = '4/4/7'; #GA DPT 9.001 zum setzen der Komforttemperatur
    $ga_reset_filter = '14/7/5'; #1bit Trigger fuer das Zuruecksetzen des Betriebsstundenzaehlers des Filters. 1=Reset
    $ga_reset_error = '14/7/6'; #1bit Trigger fuer das zuruecksetzen der KWL nach einem Fehler. 1=Reset
    
    #Hier werden die Gruppenadressen fuer die Rueckmeldungen vergeben: (Nich vergeben = inaktiv)
    $ga_status_ventilator_zul = '14/4/3'; #GA DPT5.001 fuer Status Ventilator Zuluft %
    $ga_status_ventilator_abl = '14/4/4'; #GA DPT5.001 fuer Status Ventilator Abluft %
    $ga_status_bypass_prozent = '14/4/5'; #GA DPT5.001 fuer Status Bypassklappe %
    $ga_betriebsstunden_filter = '14/4/6'; #GA DPT16.000 fuer die Rueckmeldung der Betribsstunden des Filters
    $ga_zustand_badschalter = ''; #GA DPT1.001 fuer die Rueckmeldung des Zustandes des Badezimmerschalters
    $ga_fehler_filter = '14/0/5'; #GA DPT 1.001 fuer den Zustand des Filters. 0=OK, 1=Filter Voll
    $ga_fehlercode = '14/0/6'; #GA DPT 16.000 fuer das augeben des Fehlercodes als Text
    
    #Hier werden die Gruppenadressen für die Temperaturen vergeben: (Nicht vergeben=inaktiv)
    $ga_aul_temp = '14/0/8'; #GA DPT 9.001 für die Aussenlufttemperatur
    $ga_zul_temp = '14/0/9'; #GA DPT 9.001 für die Zulufttemperatur
    $ga_abl_temp = '14/0/10'; #GA DPT 9.001 für die Ablufttemperatur
    $ga_fol_temp = '14/0/11'; #GA DPT 9.001 für die Fortlufttemperatur
    
    #Zuordnung der Namen fuer die RRD's:
    $Name_rrd_AUL = 'KWL_Aussenluft'; #Name RRD Aussenluft
    $Name_rrd_ZUL = 'KWL_Zuluft'; #Name RRD Zuluft
    $Name_rrd_ABL = 'KWL_Abluft'; #Name RRD Abluft
    $Name_rrd_FOL = 'KWL_Fortluft'; #Name RRD Fortluft
    
    #Pfad zur seriellen Schnittstelle oder dem USB-Seriell-Wandler:
    $schnittstelle = '/dev/ttyUSB-1-2';
    
    ######################
    ##ENDE Einstellungen##
    ######################
    Gruss Patrik alias swiss

    #2
    das klingt ja phantastisch!
    Wie kann ich herausfinden, ob das auch bei meiner Paul Novus 450 funktioniert?
    Wenn es auch nur eine geringe Chance dafür gibt kauf ich mir sofort ein wiregate...

    Thx, docben

    Kommentar


      #3
      Hallo docben

      Leider kenne ich die Paul Novus 450 nicht. Beim kurzen überfliegen des Schemas fiel mir aber auf, dass dieses Gerät scheinbar keine RS232 schnittstelle besitzt. Auch das Protokoll könnte grundlegend anders sein Vieleicht findest du darüber etwas beim Hersteller heraus
      Gruss Patrik alias swiss

      Kommentar


        #4
        es hat einen RS485 Bus, also auch ein serielles Protokoll.
        Der Hersteller stellt sich leider dumm und verweist mich auf den Installateur, der nicht einmal weiß was eine serielle Schnittstelle ist.

        Danke, Ben

        Kommentar


          #5
          Ja. Aber ein RS485 Protokoll ist ganz anders aufgebaut als ein RS232. Dabei geht es um Dinge wie Kolisionserkennung, Geräteadresse usw. Das ist bei dem von mir implementierten Protokoll das auf RS232 basiert nicht enthalten. Ich befürchte, das Plugin wird bei der Paul nicht funktionieren auch wenn es aus dem Hause Zehnder zu kommen scheint.

          Wenn du aber gut in im Protokollerraten bist, kannst du versuchen die für dich wichtigen Befehle mitzuschneiden und eine Protokollbeschreibung für die Paul erstellen. Dann wäre eine Implementierung in einem Plugin nicht mehr so weit
          Ansonnsten muss ich dich leider endtäuschen. Ohne Protokollbeschreibung wird das leider nichts

          PS: USB ist auch seriell aber das Protokoll hat mit RS232 auch nicht viel gemeinsam.
          Gruss Patrik alias swiss

          Kommentar


            #6
            Also ein bisschen hab ich schon mitgeloggt, ergibt allerdings noch keinen Sinn für mich...
            Gibts es eine Beschreibung verschiedener etablierter RS485 Protokolle? Ich nehme an, die werden kein neues erfunden haben...
            Danke, Ben

            Kommentar


              #7
              Zitat von docben Beitrag anzeigen
              Gibts es eine Beschreibung verschiedener etablierter RS485 Protokolle?
              RS485 beschreibt einen elektrischen Standard - beileibe kein Protokoll.

              Selbst bei Verwendung von MODBUS kämst Du nicht weiter, wenn die Funktion der Registeradressen unbekannt bleiben.
              Gruss
              GLT

              Kommentar


                #8
                ok. Habe ich eine Chance wenn ich über einen RS485 <> RS232 Umsetzer mitlogge? Und ein dann ein bekanntes Protokoll wie zB. Modbus annehme? Wie gesagt, ich nehme nicht an, dass die was ganz neues erfunden haben...
                Meine Heizung (Ökofen Pelletsofen) hat auch einen RS485 Bus. Die ist nach der Lüftung dran...

                Wie ist das beste Vorgehen, was brauche ich alles dazu?
                (Anfänger halt :-)

                Danke, Ben

                Kommentar


                  #9
                  Hallo

                  Kann ich die Applikation auch ohne Wiregate nutzen, z.B. mit HS oder EIBD?
                  Ich kann IP Telegramme senden/empfangen. Wie funktioniert die Umwandlung IP/Serial?

                  rschwend

                  Kommentar


                    #10
                    Zum Tema Protokoll sniffen und interpretieren kann ich nichts sagen. Da habe ich 0 Ahnung...

                    Zum nutzen des Plugins im hs oder mit eibd:

                    HS... Naja geht nur sehr beschränkt. Wird sich wohl auf das senden beschränken und du must das Protokoll vollständig neu implementieren. Das Plugin so wie es hier oben veröffentlicht ist, kannst du im HS nicht nutzen.

                    eibd... Das hängt sehr stark von deinen Linuxkentnissen ab. Da hängen sehr viele Dinge dran. EIBD ist nur die Schnittstelle zum KNX (Softwaremässig). Dann brauchst du noch einen Perl-interpreter eine lib die dir knxread und knxwrite zur Verfügung stellt, dann noch das RRD-Tool und unter umständem musst du doch noch das Plugin anpassen...

                    -> Da ist mir ein WG für 300 Euro in dem ich einfach nur das Plugin hineinkopieren muss und den USB-Seriell wandler anschliessen kann 1000 mal lieber
                    Gruss Patrik alias swiss

                    Kommentar


                      #11
                      Hallo Swiss,
                      das Plugin sieht grandios aus! Ich werde meiner ComfoAir auch mal etwas Luft machen.

                      Meinst Du diesen Wandler hier?

                      Seriell/RS232 auf USB-Wandler - WireGate

                      Weiß jemand wie weit ich ein RS232 Kabel ziehen kann? Meine Comfoair steht im Spitzboden und das Wiregate hängt im Zählerschrank. Das sind ca. 12m Kabel. Wenn ich das noch aus meinen Packet Radio Zeiten kenne war das Kabel ja nur aufgelöster. Da müßte ich es ja auch verlängert wieder drauf bekommen.

                      Kommentar


                        #12
                        Hallo Carsten

                        Genau so ein USB-Seriell Wandler wird benötigt. Kann bei der ComfoAir direkt auf der Konektorplatine eingesteckt werden und es kann losgehen

                        Wegen dem verlängern. Das ist ein bischen Glückssache aber wird warscheinlich schon funktionieren. Ich habe meinen Beamer im Wohnzimmer über den USB-Seriellwandler angeschlossen. Das WG steht im Rack. Sind ca. 20m Ich habe mir dafür den USB-Extender aus dem WG-shop bestellt. Damit brauchst du nur eine Netzwerkleitung. Funktioniert einwandfrei.
                        Gruss Patrik alias swiss

                        Kommentar


                          #13
                          Hallo Patrick,
                          ich hab mein Wiregate kurzerhand auf den Dachboden zu meiner KWL gestellt. Da Netzwerk und KNX eh überal herumliegt war das die einfachste Lösung.

                          Dein Plugin arbeitet perfekt!!

                          Ich hab jetzt auf die Schnelle nur bei den Temperaturen die ausgelesen werden die Komfort-Temperatur ergänzt und lasse sie nochmal auf die GA schreiben. Damit wird die Temperatur auch aktualisiert wenn sie jemand mal am Regler selbst verändert.

                          Code:
                              if($reciv =~ /07f000D209/i and $laenge == 34){ #Wenn die Temperaturen empfangen wurden und die L?nge passt
                                  
                                          my $kt1 = substr($reciv,10,2);
                                          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
                                          
                                          $kt1 =  (hex($kt1)/2)-20;
                                          $t1 =  (hex($t1)/2)-20;
                                          $t2 =  (hex($t2)/2)-20;
                                          $t3 =  (hex($t3)/2)-20;
                                          $t4 =  (hex($t4)/2)-20;
                                          
                                          #Wenn die GA's vergebenwurde, die Temperaturen auf die GA's senden
                                          if($ga_komforttemp ne ''){knx_write($ga_komforttemp,$kt1,9.001);}
                                          if($ga_aul_temp ne ''){knx_write($ga_aul_temp,$t1,9.001);}
                                          if($ga_zul_temp ne ''){knx_write($ga_zul_temp,$t2,9.001);}
                                          if($ga_abl_temp ne ''){knx_write($ga_abl_temp,$t3,9.001);}
                                          if($ga_fol_temp ne ''){knx_write($ga_fol_temp,$t4,9.001);}
                                          
                                          #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,'AUL: ' . $t1 . '°C, ZUL:' . $t2 . '°C, ABL: ' . $t3 . '°C, FOL: ' . $t4 . '°C');
                          Ich gehe mal der Annahme das du dich über https://www.see-solutions.de/sonstig...g_ComfoAir.pdf dieses Protokoll entlanggehangelt hast.

                          Bisher hat Du ja alle wichtigen Funktionen umgesetzt, aber falls noch jemandem etwas fehlt, kann ich mich gerne daran versuchen das Plugin noch etwas zu erweitern.

                          grüße
                          Carsten

                          Kommentar


                            #14
                            Hallo Carsten

                            Ja genau mit dieser Protokollbeschreibung habe ich das Plugin erstellt War aber ein Kampf bis es richtig funktionierte. Nun bin ich froh dass sich die Mühe gelohnt hat.

                            Schön wäre immer noch, wenn man das Plugin auf Socat umbauen könnte aber die Richtigen Soketeinstellungen habe ich immer noch nicht gefungen Wenn jemand da eine Lösung finden würde, könnte man ohne Bauchschmerzen das gesammte Protokoll implementieren und auch voll nutzen Aber so gehts bis jetzt auch
                            Gruss Patrik alias swiss

                            Kommentar


                              #15
                              Erster Versuch mit socket

                              Lieber Patrik

                              Ich möchte in den nächsten Tagen versuchen, ob ich meine Zehnder mit Hilfe von MOXA-Schnittstellen auf Dein tolles Plugin reagierten. Leider habe ich von Socat und ähnlichem keinen blossen Schimmer. Um mein Trial und Error auf die Socat-Einstellungen einzugrenzen, wäre ich Dir sehr dankbar, wenn Du im nachfolgenden Code prüfen könntest, ob ich aus Deiner Sicht die Kommunikation über Sockets (statt direkt auf die serielle Schnittstelle) richtig umgesetzt habe. Sobald ich dies weiss, kann ich mit den Socket-Einstellungen spielen.
                              Meine Änderungen habe ich im Code mit "#DC " markiert.

                              Herzlichen Dank für Deine Unterstützung, falls Du dazu gelegentlich Zeit findet.
                              Liebe Grüsse
                              Diego

                              Code:
                              # Plugin zur Ansteuerung einer Zender ComfoAir
                              # Version 1.5 14.08.2012 BETA
                              # Copyright: swiss (https://knx-user-forum.de/members/swiss.html)
                              # Aufbau moeglichst so, dass man unterhalb der Einstellungen nichts veraendern muss!
                              #
                              #
                              
                              ####################
                              ###Einstellungen:###
                              ####################
                              
                              
                              #BITTE ab sofort die Einstellungen unter conf.d vornemen. Damit bleiben die Einstellungen auch bei einem Update erhalten.
                              
                              
                              ######################
                              ##ENDE Einstellungen##
                              ######################
                              
                              
                              #Ab hier nichts mehr aendern.
                              #Hauptverarbeitung
                              
                              
                              #DC eingefügt ******** Anfang
                                  my $socknum = 87; # Eindeutige Nummer des Sockets
                                  my $send_ip = "10.0.0.247"; # Sendeport (UDP, siehe in Socket-Einstellungen)
                                  my $send_port = "16011"; # Sendeport (UDP, siehe in Socket-Einstellungen)
                                  my $recv_ip = "10.0.0.247"; # Empfangsport (UDP, siehe in Socket-Einstellungen)
                                  my $recv_port = "16012"; # Empfangsport (UDP, siehe in Socket-Einstellungen)
                              #DC eingefügt ******** Ende
                                  
                              #Erzeuge Variablen fuer die Zuordnung Steuerfunktionen zu den Gruppenadressen:
                              my $ga_stufeabwesend = ''; #1bit Trigger fuer Stufe "Abwesend". 1=Aktivieren
                              my $ga_stufe1 = ''; #1bit Trigger fuer Stufe1. 1=Aktivieren
                              my $ga_stufe2 = ''; #1bit Trigger fuer Stufe2. 1=Aktivieren
                              my $ga_stufe3 = ''; #1bit Trigger fuer Stufe3. 1=Aktivieren
                              my $ga_komforttemp = ''; #GA DPT 9.001 zum setzen der Komforttemperatur
                              my $ga_reset_filter = ''; #1bit Trigger fuer das Zuruecksetzen des Betriebsstundenzaehlers des Filters. 1=Reset
                              my $ga_reset_error = ''; #1bit Trigger fuer das zuruecksetzen der KWL nach einem Fehler. 1=Reset
                              
                              #Hier werden die Gruppenadressen fuer die Rueckmeldungen vergeben: (Nich vergeben = inaktiv)
                              my $ga_status_ventilator_zul = ''; #GA DPT5.001 fuer Status Ventilator Zuluft %
                              my $ga_status_ventilator_abl = ''; #GA DPT5.001 fuer Status Ventilator Abluft %
                              my $ga_status_bypass_prozent = ''; #GA DPT5.001 fuer Status Bypassklappe %
                              my $ga_betriebsstunden_filter = ''; #GA DPT16.000 fuer die Rueckmeldung der Betribsstunden des Filters
                              my $ga_zustand_badschalter = ''; #GA DPT1.001 fuer die Rueckmeldung des Zustandes des Badezimmerschalters
                              my $ga_fehler_filter = ''; #GA DPT 1.001 fuer den Zustand des Filters. 0=OK, 1=Filter Voll
                              my $ga_fehlercode = ''; #GA DPT 16.000 fuer das augeben des Fehlercodes als Text
                              
                              #Hier werden die Gruppenadressen für die Temperaturen vergeben: (Nicht vergeben=inaktiv)
                              my $ga_aul_temp = ''; #GA DPT 9.001 für die Aussenlufttemperatur
                              my $ga_zul_temp = ''; #GA DPT 9.001 für die Zulufttemperatur
                              my $ga_abl_temp = ''; #GA DPT 9.001 für die Ablufttemperatur
                              my $ga_fol_temp = ''; #GA DPT 9.001 für die Fortlufttemperatur
                              
                              #Zuordnung der Namen fuer 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:
                              #DC kommentiert my $schnittstelle = '/dev/ttyUSB-1-1';
                              
                              &readConf(); #conf.d einlesen
                              
                              #DC kommentiert 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'}  = 25; 
                              
                              #Einrichten der Seriellen Schnittstelle fuer die Kommunikation mit dem ComfoAir
                              #DC kommentiert my $seriel = Device::SerialPort->new($schnittstelle) || die "Kann $schnittstelle nicht öffnen! ($!)\n";
                              #DC kommentiert $seriel->baudrate(9600);
                              #DC kommentiert $seriel->parity("none");
                              #DC kommentiert $seriel->databits(8);
                              #DC kommentiert $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 fuer 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
                              # DC Eingefügt ******* Anfang
                                  if (!$socket[$socknum]) { # socket erstellen
                                          $socket[$socknum] = IO::Socket::INET->new(LocalPort => $recv_port,
                                                                    Proto => "udp",
                                                                    LocalAddr => $recv_ip,
                                                                    PeerPort  => $send_port,
                                                                    PeerAddr  => $send_ip,
                                                                    ReuseAddr => 1
                                                                     )
                                      or return ("open of $recv_ip : $recv_port failed: $!");
                              
                                      $socksel->add($socket[$socknum]); # add socket to select
                              
                                      $plugin_socket_subscribe{$socket[$socknum]} = $plugname; # subscribe plugin
                                      return "opened Socket $socknum";
                                  }
                              # DC Eingefügt ******* Ende
                              
                                  # 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 Binaereingaenge abfragen
                                      $daten = "000300";
                                      plugin_log($plugname,'Binäreingänge abrufen');
                                      $return_value2 = command_senden($daten);
                                  }
                              
                                  #Hier werden die Stoermeldungen 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 uebertragen
                              sub command_senden{
                                  my $checksum = 0;
                                  my $data = $_[0];
                                  
                                  my $datasum = $data . "AD"; #+173 fuer 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
                              #DC kommentiert    $seriel->write($command); #Befehl an die ComfoAir senden
                              # DC eingefügt ****** Anfang
                                  #$plugin_info{$plugname.'_debug'} = $command;
                                  syswrite($socket[$socknum], $command);
                              # DC eingefügt ****** Ende    
                              
                                  $reciv = '';
                                      
                                  $|=1;
                                  my $exit=0;
                                  while($exit < 25000)
                                  {
                              #DC  kommentiert       my ($cin, $sin) = $seriel->read(45);
                              # DC eingefügt ****** Anfang
                                  my $sin ='';
                                  if ($fh) { # Antwort auslesen
                                      $sin = <$fh>;
                                  }
                                  my $cin = length($sin);
                              # DC eingefügt ****** Ende
                                  if($cin > 0){
                                      $sin = unpack "H*", $sin;
                                      $reciv .= $sin;
                                      $exit=0;
                                  }else{
                                      $exit++
                                  }
                              
                                      if($reciv =~ /070f/i){           
                                   #DC  kommentiert         $seriel->write($ack); #ACK senden
                                   # DC eingefügt ****** Anfang
                                      syswrite($socket[$socknum], $ack); #ACK senden
                                   # DC eingefügt ****** Ende    
                                              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); #Laenge 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;
                                              
                                              #Wenn die GA's vergebenwurde, die Temperaturen auf die GA's senden
                                              if($ga_aul_temp ne ''){knx_write($ga_aul_temp,$t1,9.001);}
                                              if($ga_zul_temp ne ''){knx_write($ga_zul_temp,$t2,9.001);}
                                              if($ga_abl_temp ne ''){knx_write($ga_abl_temp,$t3,9.001);}
                                              if($ga_fol_temp ne ''){knx_write($ga_fol_temp,$t4,9.001);}
                                              
                                              #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,'AUL: ' . $t1 . '°C, ZUL:' . $t2 . '°C, ABL: ' . $t3 . '°C, FOL: ' . $t4 . '°C');
                              
                                  }elsif($reciv =~ /07f0000C06/i and $laenge == 28){ #Wenn der Status fuer 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 fuer 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 Rueckmeldung 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 Rueckmeldung der Binaereingaenge 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 Rueckmeldung der Stoermeldungen 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 Binaer und drehe die Reihenfolge um. z.B 0x02 = 00000010 = 010000000
                                              $fehlerAlo = index($fehlerAlo,'1')+1; # Zaehle 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 fuer das uebertragen 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);
                                                  }else{
                                                      plugin_log($plugname,'Aktueller Fehlercode: keiner' );
                                                      knx_write($ga_fehlercode,'keiner' . $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);
                                              }               
                                  }
                              }
                              
                              sub readConf
                              {
                                  my $confFile = '/etc/wiregate/plugin/generic/conf.d/'.basename($plugname,'.pl').'.conf';
                                  if (! -f $confFile)
                                  {
                                      plugin_log($plugname, " no conf file [$confFile] found."); 
                                  }
                                  else
                                  {
                                      plugin_log($plugname, " reading conf file [$confFile]."); 
                                      open(CONF, $confFile);
                                      my @lines = <CONF>;
                                      close($confFile);
                                      my $result = eval("@lines");
                                      ($result) and plugin_log($plugname, "conf file [$confFile] returned result[$result]");
                                      if ($@) 
                                      {
                                          plugin_log($plugname, " conf file [$confFile] returned:");
                                          my @parts = split(/\n/, $@);
                                          plugin_log($plugname, " --> $_") foreach (@parts);
                                      }
                                  }
                              } # readConf

                              Kommentar

                              Lädt...
                              X