Ankündigung

Einklappen
Keine Ankündigung bisher.

ComfoAir Steuerung über RS232

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

    #91
    Vielen Dank.
    Ein tolles vorzeitiges Weihnachtsgeschenk!


    Ich werde das Plugin umgehend testen...
    Gruß -mfd-
    KNX-UF-IconSet since 2011

    Kommentar


      #92
      Ist das hier vorgestellte Protokoll auch mit dem Loxone und der dazu gehörigen RS232-Schnittstelle mit der Zehnder verwendbar?
      Die Steuerung per SmartPhone macht ein Haus nicht zum SmartHome...

      Kommentar


        #93
        Hallo Janosch

        Ich kenne die Loxone zu wehnig um das mit absoluter Sicherheit zu sagen aber...

        Wenn du eine Möglichkeit hast Hex Daten über die serielle Schnittstelle zu senden, denn müsste es eigentlich gehen. Du musst halt für die Loxone ein eigenes Programm schreiben, da dieses Plugin so in der Loxone nicht lauffähig ist.

        Das PDF mit der Protokollbeschreibung wurde hier im Forum schon mehrfach veröffentlicht
        Gruss Patrik alias swiss

        Kommentar


          #94
          Danke dir für die Antwort :-)

          Ich lese mich gerade ein, wie ich das umprogrammieren muss, scheint aber zu funktionieren :-)

          LG und Danke!
          Die Steuerung per SmartPhone macht ein Haus nicht zum SmartHome...

          Kommentar


            #95
            Falls es jemanden interessiert wegen der Verknüpfung eines Loxone mit nem ComfoAir350:
            Zehnder Comfosystems CA350 auslesen und steuern - FAQs, Tutorials & HowTo's - Loxone - Forum, Community - Loxone

            LG
            Die Steuerung per SmartPhone macht ein Haus nicht zum SmartHome...

            Kommentar


              #96
              Hallo Janosch

              Du schreibst im Loxoneforum, dass man die CCEASE nicht abklemmen muss. Kannst du mir verraten wesshalb?

              -> Das Problem ist ja, dass RS232 nur für die verbindung von 2 Geräten (z.B. Lüftung und CCEASE) gedacht ist. Die sprechen auch häufig und spontan miteinander. Wenn du jetzt auf die Schnittstelle einfach Daten drauf schreibst, kommt es schnell mal zu Kollisionen. Dann stürzt entweder die EASE ab, irgend welche Parameter verstellen sich oder im dümmsten Fall bekommt das Mainbord der KWL Probleme/Fehlfunktionen.

              Auch wenn es eine gewisse Zeit paralell zu funktionieren scheint, rate ich dir in jedem Fall die EASE abzuklemme! Wir experimentieren hier schon bald 1 Jahr an der Steuerung und hatten schon diverse Probleme mit dem Paralellbetrieb!
              Gruss Patrik alias swiss

              Kommentar


                #97
                Ich hab da noch nix geschrieben :-D Kann dir daher keine Antwort geben ;-)
                Die Steuerung per SmartPhone macht ein Haus nicht zum SmartHome...

                Kommentar


                  #98
                  Ach soo. Ich dachte du nennst dich im anderen Forum Meista

                  Ich rate dir aber dennoch zur Vorsicht mit dem Paralellbetrieb -> Bei meinem Plugin schreib ich immer deutlich, dass KEIN Paralellbetrieb möglich ist. Denn wenn es jemand doch paralell betreibt und es treten Schäden auf (hatten wir auch schon ) kann ich mit gutem Gewissen sagen, dass es nicht meine Schuld ist. Ich habe es ja gesagt...
                  Gruss Patrik alias swiss

                  Kommentar


                    #99
                    ja-abklemmen-ansonsten ist alles möglich.

                    Grüße,
                    Lio

                    Kommentar


                      Habe gerade das Plugin an meiner ComfoAir550 in Betrieb genommen. Was soll ich sagen: Funktioniert sofort beim ersten Anlauf!
                      (naja, fast beim ersten Anlauf: Im Plugin ist die Schnittstelle fest eingetragen, ich hab's nur in der .conf angegeben, das wurde im Plugin überschrieben)


                      Ich hätte allerdings noch die eine oder andere Frage / Anregung:
                      1. Die aktuelle Version ist diese hier, nicht die aus dem SVN, oder?
                      2. Im Plugin ist immer noch der ganze Config-Teil enthalten. Ist mit der Umstellung auf .conf überflüssig das zu pflegen, oder? Das die Schnittstelle an der Stelle noch explizit definiert wird ist ein Versehen, oder?
                      3. Das Protokoll gibt ja noch ne Menge mehr an Werten her. Das neue Release ist dann auch für Anfänger wie mich durchschaubar und an die eigenen Bedürfnisse anpassbar? Ich hätte gerne noch das eine oder andere abgerufen bzw. in RRD gespeichert.
                      Endlich umgezogen. Fertig? Noch lange nicht... ;-)

                      Kommentar


                        Hallo Hauke
                        Zitat von Hauke Beitrag anzeigen
                        1. Die aktuelle Version ist diese hier, nicht die aus dem SVN, oder?
                        Ja, das ist richtig. Die aktuellste Version findest Du im Moment im Beitrag #90 ( https://knx-user-forum.de/273475-post90.html ), nicht im SVN.

                        Zitat von Hauke Beitrag anzeigen
                        2. Im Plugin ist immer noch der ganze Config-Teil enthalten. Ist mit der Umstellung auf .conf überflüssig das zu pflegen, oder? Das die Schnittstelle an der Stelle noch explizit definiert wird ist ein Versehen, oder?
                        emax, der spriritus rector der Config-Idee, hat hier festgelegt, dass "ein Plugin auch dann fehlerfrei ausführen muss, wenn keine Konfigurationsdatei gefunden wird", dies bedeutet, dass im Plugin wichtigen Variablen Standardwerte zugewiesen werden müssen. Grundsätzlich müssen diese aber im Plugin nicht gepflegt werden, sondern können im Urzustand belassen werden, weil das Plugin die Werte aus der Config-Datei verwendet. Weshalb es bei Dir so nicht läuft, weiss ich nicht; ich selbst hatte schon das Problem, dass die Config-Datei nicht genau den selben Namen hatte, wie das Plugin (sie hatte ein .pl im Dateinamen, mein Plugin nicht).


                        Zitat von Hauke Beitrag anzeigen
                        3. Das Protokoll gibt ja noch ne Menge mehr an Werten her. Das neue Release ist dann auch für Anfänger wie mich durchschaubar und an die eigenen Bedürfnisse anpassbar? Ich hätte gerne noch das eine oder andere abgerufen bzw. in RRD gespeichert.
                        Gerne zeige ich woran ich arbeite, damit Du beurteilen kannst, ob dies Deinen Anforderungen entspricht. Es gibt aber zwei wichtige Hinweise:
                        1. Aus Bequemlichkeitsgründen habe ich den Config-Teil noch im Plugin intergriert, in einer allfällig definitiven Version wird dies separiert werden.
                        2. Das Plugin arbeitet grundsätzlich korrekt, ich erhalte die gewünschten Werte. Jedoch: In seiner jetztigen Version verursacht das Plugin auf meinem Wiregate ein von mir nicht erkennbares Problem, weshalb im Takt des Plugins der eibd neu gestartet wird, deshalb ********** VORSICHT ************ beim Einsatz. Vielleicht findet ein Crack den Fehler, den ich begehe, oder es kann jemand die Version testen, und mir mitteilen, ob sich sein Wiregate gleich verhält wie meines.

                        Code:
                        # Plugin zur Ansteuerung einer Zehnder ComfoAir 350
                        # Version 2.0 22.11.2012 PRE-BETA
                        # Copyright: swiss (https://knx-user-forum.de/members/swiss.html) unter der Mitarbeit von fechter65 (https://knx-user-forum.de/members/fechter65.html)
                        # Basierend auf einer Protokolbeschreibung publiziert von www.see-solutions.de
                        # Die Anbindung des Lueftungsgeraets erfolt entweder über die serielle Schnittstelle oder über einen Moxa NPort
                        
                         
                        
                        ####################
                        ###Einstellungen:###
                        ####################
                        my @Aktionen;
                        my @Kommandi;
                        my @Datenfeld;
                        my $element;
                        my $ack = pack("H*","07F3");
                        my $AnfrageStart = "07F0";
                        my $AnfrageEnde = "070F";
                        my $AnfrageKommando = "";
                        my $AnfrageWert = "";
                        my $AnfrageAnzahl = "";
                        my $AnzByte = "";
                        my $StartByte = "";
                        my $Wert = "";
                        my $AnfrageName = "";
                        my $AnfrageAntwort = "";
                        my $AnfrageKLaenge = "";
                        my $AnfrageALaenge = "";
                        my $hWert='';
                        my $dWert='';
                        my $LogEintrag ='';
                        my $GA    ='';
                        my $RRD    ='';
                        my $Umrechnung ='';
                        my $DPT    ='';
                        
                        
                        
                        #Zykluszeit
                        my $Zykluszeit = "300"; #Bestimmt in welchem Rhytmus die zyklische Abfrage erfolgt
                        
                        # Dauer einer Abfrage
                        my $Zaehler = "2500"; #Mit dieser Variable Zaehler wird beeinflusst, wie lange das Plugin auf den Abschluss einer Rückmeldung der KWL wartet; empfohlener Wert für seriell: 2'500; für Moxa: 250
                        
                        # Kommunikationsart
                        my $Kom_Art = "S"; # "S" = seriell; "M" = Moxa 
                         
                        #Pfad zur seriellen Schnittstelle oder dem USB-Seriell-Wandler:
                        my $schnittstelle = '/dev/ttyUSB-1-1';
                        
                        #Angaben für die Kommunikation über den UDP-Port einer MOXA [diese Einstellungen reichen aus, d.h. auf dem Wiregate muss unter "Seriell/LAN/Socketverbindungen" KEINE Socketverbindung erstellt werden
                        my $socknum = ""; # Eindeutige Nummer des Sockets
                        my $send_ip = ""; # SendeIP (UDP)
                        my $send_port = ""; # Sendeport (UDP)    
                        my $recv_ip = ""; # EmpfangsIP (UDP)
                        my $recv_port = ""; # Empfangsport (UDP)
                        
                        # Debug level 0 = nur die wichtigsten Infos, 1 = Alle Zustaende, 2 = Rohdaten (nur für Fehlersuche)
                        my $debug=0;
                        
                        my $seriel;
                        my $sin; #Serial Input = Empangener Datenstrom
                        my $cin; #Counter Input =  Laenge des Datenpakets
                        my $laenge; #Länge des empfangenen Datenstrings nachdem kuerzen
                         
                        my $checksum = 0; #Checksumme
                        my @hex; #Hilfsarray fuer die Checksummenberechnung
                        my $x07warschon; #Hilfsvariable fuer die Checksummenberechnung
                         
                        
                        # my $daten;
                        my $reciv;
                        my $reciv_all;
                        my $rcv_checksum;
                         
                        
                        
                        #BITTE ab sofort die Einstellungen unter conf.d vornehmen. Damit bleiben die Einstellungen auch bei einem Update erhalten.
                        #-------------------------------Der nachfolgende Teil gehoert in die conf.d Datei, hier im Moment nur aus Bequemlichkeit------------------------------------------
                        # Kommunikationsart; abhaengig davon, wie die KWL mit dem Wiregate verbunden ist, muessen nachfolgend unterschiedliche Einstellungen vorgenommen werden.
                        # Im Moment stehen zwei Moeglichkeiten zur Verfuegung: 
                        #    seriell, d.h. direkt an der seriellen Schnittstelle des Wiregates oder an einem seriell-USB-Wandler am USB-Port des Wiregates angeschlossen
                        #    MOXA: die serielle Schnittstelle der KNX ist über eine MOXA-Schnittstelle über das UDP-Protokoll mit dem Wiregate verbunden
                        $Kom_Art = "M"; # "S" = seriell; "M" = Moxa
                        
                        #Serielle-Anbindung: Pfad zur seriellen Schnittstelle oder dem USB-Seriell-Wandler:
                        $schnittstelle = '/dev/ttyUSB-1-2';
                        #MOXA-Anbindung: 
                        #Angaben für die Kommunikation über den UDP-Port einer MOXA [diese Einstellungen reichen aus, d.h. auf dem Wiregate muss unter "Seriell/LAN/Socketverbindungen" KEINE Socketverbindung erstellt werden
                        $socknum = "77"; # Eindeutige Nummer des Sockets, kann grundsaetzlich frei gewaehlt werden
                        $send_ip = "10.0.0.227"; # SendeIP (UDP): IP-Adresse der MOXA
                        $send_port = "16012"; # Sendeport (UDP): Auf der MOXA gewaehlter Port
                        $recv_ip = "10.0.1.10"; # EmpfangsIP (UDP): IP-Adresse des Wiregates
                        $recv_port = "16011"; # Empfangsport (UDP): Auf dem Wiregate gewaehlter Port
                        
                        #Zykluszeit
                        $Zykluszeit = "300"; #Bestimmt in welchem Rhytmus die zyklische Abfrage erfolgt
                        
                        # Dauer einer Abfrage
                        $Zaehler = "250"; #Mit dieser Variable wird beeinflusst, wie lange das Plugin auf den Abschluss einer Rückmeldung der KWL wartet; empfohlener Wert für seriell: 25'000; für Moxa: 250
                        
                        # Debug level 0 = nur die wichtigsten Infos, 1 = Alle Zustaende, 2 = Rohdaten (nur für Fehlersuche) 3 = Einzelschritte
                        $debug="2";
                        
                        @Aktionen = 
                            #GA:         GA über die die Abfrage aufgerufen wird und / oder auf die der Rueckgabewert geschrieben wird
                            #Kdo:        HexWert des Kommandos gemaess Protokollbeschrieb; Format: vier Zeichen lang, Kleinbuchstaben
                            #Name:         Frei waehlbar
                            #Aktiv:     0: nicht aktiv; 1: zyklisch abrufen; 2: auf Anfrage Abrufen
                            #StartByte:    Erstes Byte des Datenfeldes, welches diesen Datenwert beinhaltet (gemaess Protokollbeschreibung)
                            #AnzByte:    Anzahl Bytes, die fuer diesen Datenwert zur Verfuegung steht (gemaess Protokollbeschreibung)
                            #Logeintrag:  
                            #RRD:        
                            #Umrechnung: 
                            #Wert:        
                            #DPT:        
                            ( 
                              { GA=>'7/3/248', Kdo=>'00cd', Name=>'StatusAktuelleStufe',       Aktiv=>'2', StartByte=>'9', AnzByte=>'1', LogEintrag =>'AKT_STUFE', RRD=>'', Umrechnung=>'', Wert=>'', DPT=>'5'  },
                              { GA=>'7/3/249', Kdo=>'0099', Name=>'StufeSetzen',               Aktiv=>'2', StartByte=>'1', AnzByte=>'1', LogEintrag =>'', RRD=>'', Umrechnung=>'', Wert=>'', DPT=>'5'  },
                              { GA=>'7/3/234', Kdo=>'00d3', Name=>'KomfTempSetzen',           Aktiv=>'2', StartByte=>'1', AnzByte=>'1', LogEintrag =>'', RRD=>'', Umrechnung=>'sTemp', Wert=>'', DPT=>'9'  },
                        #$ga_reset_filter = '7/3/235'; #1bit Trigger fuer das Zuruecksetzen des Betriebsstundenzaehlers des Filters. 1=Reset
                        #$ga_reset_error = '7/3/236'; #1bit Trigger fuer das zuruecksetzen der KWL nach einem Fehler. 1=Reset
                        #$ga_fehler_filter = '7/3/242'; #GA DPT 1.001 fuer den Zustand des Filters. 0=OK, 1=Filter Voll
                        #$ga_fehlercode = '7/3/243'; #GA DPT 16.000 fuer das augeben des Fehlercodes als Text
                              { GA=>'7/3/244', Kdo=>'00d1', Name=>'TempAussenluft',            Aktiv=>'1', StartByte=>'2', AnzByte=>'1', LogEintrag =>'AUL', RRD=>'KWL_Kanzlei_Aussenluft', Umrechnung=>'lTemp', Wert=>'', DPT=>'9.001'  },
                              { GA=>'7/3/245', Kdo=>'00d1', Name=>'TempZuluft',                Aktiv=>'1', StartByte=>'3', AnzByte=>'1', LogEintrag =>'ZUL', RRD=>'KWL_Kanzlei_Zuluft', Umrechnung=>'lTemp', Wert=>'', DPT=>'9.001'  },
                              { GA=>'7/3/246', Kdo=>'00d1', Name=>'TempAbluft',                Aktiv=>'1', StartByte=>'4', AnzByte=>'1', LogEintrag =>'ABL', RRD=>'KWL_Kanzlei_Abluft', Umrechnung=>'lTemp', Wert=>'', DPT=>'9.001'  },
                              { GA=>'7/3/247', Kdo=>'00d1', Name=>'TempFortluft',            Aktiv=>'1', StartByte=>'5', AnzByte=>'1', LogEintrag =>'FOL', RRD=>'KWL_Kanzlei_Fortluft', Umrechnung=>'lTemp', Wert=>'', DPT=>'9.001'  },      
                              { GA=>'7/3/237', Kdo=>'000b', Name=>'StatusVentiZUL',            Aktiv=>'1', StartByte=>'1', AnzByte=>'1', LogEintrag =>'VentiZUL', RRD=>'', Umrechnung=>'', Wert=>'', DPT=>'5' },
                              { GA=>'7/3/238', Kdo=>'000b', Name=>'StatusVentiABL',            Aktiv=>'1', StartByte=>'2', AnzByte=>'1', LogEintrag =>'VentiABL', RRD=>'', Umrechnung=>'', Wert=>'', DPT=>'5' },
                              { GA=>'7/3/239', Kdo=>'000d', Name=>'StatusBypass',            Aktiv=>'1', StartByte=>'1', AnzByte=>'1', LogEintrag =>'Bypass', RRD=>'', Umrechnung=>'', Wert=>'', DPT=>'5' },
                              { GA=>'7/3/240', Kdo=>'00dd', Name=>'BetriebsstundenFilter',    Aktiv=>'1', StartByte=>'16', AnzByte=>'2', LogEintrag =>'Betriebsstunden Filter', RRD=>'', Umrechnung=>'', Wert=>'', DPT=>'16' },
                              { GA=>'', Kdo=>'0003', Name=>'StatusBadezimmerSchalter',        Aktiv=>'0', StartByte=>'2', AnzByte=>'1', LogEintrag =>'Status Badezimmerschalter', RRD=>'', Umrechnung=>'', Wert=>'', DPT=>'1.001' },
                              );
                         
                        @Kommandi = 
                            #Name:         Frei waehlbar
                            #Kdo:        HexWert des Kommandos gemaess Protokollbeschrieb; Format: vier Zeichen lang, Kleinbuchstaben
                            #Antwort:    HexWert der Antwort gemaess Protokollbeschrieb; Format: vier Zeichen lang, Kleinbuchstaben
                            #KLaenge:     Laenge des Kommandos in Bytes
                            #ALaenge:     Laenge der Antwort in Bytes
                            ( 
                                #Lesekommandi haben als KLaenge den Wert '0'          
                              { Name=>'EingaengeAbrufen',             Kdo=>'0003', Antwort=>'0004', KLaenge=>'0', ALaenge=>'2'},
                              { Name=>'VentilatorstatusAbrufen',     Kdo=>'000b', Antwort=>'000c', KLaenge=>'0', ALaenge=>'6'},
                              { Name=>'KlappenstatusAbrufen',         Kdo=>'000d', Antwort=>'000e', KLaenge=>'0', ALaenge=>'4'},
                              { Name=>'VentilationsstufeAbrufen',     Kdo=>'00cd', Antwort=>'00ce', KLaenge=>'0', ALaenge=>'14'},
                              { Name=>'TemperaturAbrufen',             Kdo=>'00d1', Antwort=>'00d2', KLaenge=>'0', ALaenge=>'9'},
                              { Name=>'StoerungAbrufen',             Kdo=>'00d9', Antwort=>'00da', KLaenge=>'0', ALaenge=>'17'},
                              { Name=>'BetriebsstundenAbrufen',     Kdo=>'00dd', Antwort=>'00de', KLaenge=>'0', ALaenge=>'20'},
                                #Schreibkommandi haben als Antwort den Wert '' und als ALaenge den Wert '0'      
                              { Name=>'StufeSetzen',                 Kdo=>'0099', Antwort=>'', KLaenge=>'1', ALaenge=>'0'},
                              { Name=>'KomfoTempSetzen',             Kdo=>'00d3', Antwort=>'', KLaenge=>'1', ALaenge=>'0'},
                              { Name=>'VentilationsstufeSetzen',     Kdo=>'00cf', Antwort=>'', KLaenge=>'9', ALaenge=>'0'}
                             );
                        
                             
                             
                        #-------------------------------Der vorstehende Teil gehoert in die conf.d Datei, hier im Moment nur aus Bequemlichkeit------------------------------------------ 
                        ######################
                        ##ENDE Einstellungen##
                        ######################
                        
                        
                        #Ab hier nichts mehr aendern.
                        ######################
                        ##Hauptverarbeitung:##
                        ######################
                        
                        
                        
                        #&readConf(); #Konfigurationsdatei einlesen
                        
                        
                        #Einrichten der seriellen Schnittstelle fuer die Kommunikation mit dem ComfoAir 
                        if ($Kom_Art eq "S"){
                                     use Device::SerialPort;
                                     my $seriel = Device::SerialPort->new($schnittstelle) || die "Kann $schnittstelle nicht öffnen! ($!)\n";
                                     $seriel->baudrate(9600);
                                     $seriel->parity("none");
                                     $seriel->databits(8);
                                     $seriel->stopbits(1);
                                     if($debug>=1){plugin_log($plugname,'Schnittstelle: ' . $schnittstelle . ' erfolgreich geöffnet')};
                        }elsif ($Kom_Art eq "M"){
                            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; # Plugin an Socket "anmelden"
                                return "opened Socket $socknum";
                                                     if($debug>=1){plugin_log($plugname,'Socket: ' . $socknum . ' erfolgreich geöffnet')};
                            }
                        }
                        #Art des Aufrufs pruefen
                        if ($msg{'apci'} eq "A_GroupValue_Write"){ #Wenn ein Schreibtelegramm vom KNX empfangen wird, wird hier ausgewertet
                            $AnfrageKommando = '';
                            $AnfrageWert = '';
                            $AnfrageAnzahl = ''; 
                                                                                    if($debug>=1){plugin_log($plugname,'Schreibtelegramm bearbeiten: ')};    
                        #                $AnfrageWert = knx_read($msg{'dst'},0,1);    #Vom KNX-Schreibbefehl gesendeten Wert übernehmen
                        #                $AnfrageWert = knx_read($msg{'dst'});    #Vom KNX-Schreibbefehl gesendeten Wert übernehmen        
                        #                $AnfrageWert =  $msg{'value'};        
                                        $AnfrageWert = knx_read($msg{'dst'},0);    #Vom KNX-Schreibbefehl gesendeten Wert übernehmen    
                            foreach my $element (@Aktionen) {
                                if (($msg{'dst'} eq $element->{GA}) and ($element->{Aktiv}==2)) {
                                    $AnzByte         = $element->{AnzByte};
                                    $AnfrageKommando = $element->{Kdo};
                                    if ($AnzByte > 0) {  
                            
                                        if ($AnfrageWert eq ''){
                                            $AnfrageWert = $element->{Wert};        #Ersatzwert übernehmen
                                        }
                                        if ($AnfrageWert ne '') {
                                            if ($element->{LogEintrag} ne ''){plugin_log($plugname,$element->{LogEintrag}." : " . $AnfrageWert );}
                                        }
                                                                                if($debug>=1){plugin_log($plugname,'Schreiben von : ' . $AnfrageWert )};    
                                        $Datenfeld[$element->{StartByte}] = $AnfrageWert;
                                        Kom_Erstellen($AnfrageKommando);
                                        my $yyy = Antw_Empfangen(); #anstehende Daten abholen 
                                        Antw_Auswerten($yyy);        #empfangene Datenpaket auswerten
                                    }
                                    last;
                                }
                            }
                        
                        } elsif ($msg{'apci'} eq "A_GroupValue_Read"){ #Wenn ein Lesetelegramm vom KNX empfangen wird, ab hier auswerten
                            $AnfrageKommando = '';
                                                                                    if($debug>=1){plugin_log($plugname,'Lesetelegramm bearbeiten: ')};
                            foreach my $element (@Aktionen) {
                                if (($msg{'dst'} eq $element->{GA}) and ($element->{Aktiv}==2)) {
                                    $AnfrageKommando = $element->{Kdo};
                                    Kom_Erstellen($AnfrageKommando);
                                    my $yyy = Antw_Empfangen(); #anstehende Daten abholen 
                                    Antw_Auswerten($yyy);        #empfangene Datenpaket auswerten
                                    last; 
                                }
                            }
                        } elsif ($fh) {# Pruefen, ob KWL Daten sendet (Plugin wird auch aufgerufen, wenn Socat-Rückmeldung erfolgt)
                                                                                    if($debug>=1){plugin_log($plugname,'anstehende Rueckmeldung der KWL abarbeiten: ')};
                                my $yyy = Antw_Empfangen(); #anstehende Daten abholen 
                                Antw_Auswerten($yyy);        #empfangene Datenpaket auswerten
                        } else {  #zyklischer Aufruf abarbeiten
                            $plugin_info{$plugname.'_cycle'}  = $Zykluszeit; # Zyklischer Aufruf definieren
                            #my @sorted = sort {$a->[2] <=> $b->[2]} @Aktionen;    
                            #PENDENZ: @Aktionen nach Kdo sortieren, so dass Prüfung nach $KdoWarSchon unabhängig von der vom Benutzer gewaehlten Reihenfolge funktioniert.
                            my $KdoWarSchon='';
                            foreach my $element (@Aktionen) {
                                if ($element->{Aktiv} == 2) { #Aktionen, deren Aktivwert 2 ist, werden bei entsprechenden KNX-Aktivitäten aufgerufen
                                    # Plugin an Gruppenadresse "anmelden", hierdurch wird das Plugin im folgenden bei jedem Eintreffen eines Telegramms auf die entsprechende GA aufgerufen                    
                                    $plugin_subscribe{$element->{GA}}{$plugname} = 1;    
                                                                                    if($debug>=2){plugin_log($plugname,'Anmelden von: '.$element->{GA});}
                                }
                                if ($element->{Aktiv} == 1) { #Kommandi, die Aktionen haben mit Aktivwert 1 haben, werden zyklisch aufgerufen
                                    $AnfrageKommando = $element->{Kdo};
                                                                                    if($debug>=5){plugin_log($plugname,'Pruefen von : '.$AnfrageKommando);}            
                                    if ($AnfrageKommando ne $KdoWarSchon) {            #Sicherstellen, dass jedes Kommando nur einmal aufgerufen wird    
                                                                                    if($debug>=3){plugin_log($plugname,'Ausführen von: '.$AnfrageKommando->{GA});}
                                        Kom_Erstellen($AnfrageKommando);
                                        my $yyy = Antw_Empfangen(); #anstehende Daten abholen 
                                        Antw_Auswerten($yyy);        #empfangene Datenpaket auswerten
                                        $KdoWarSchon = $AnfrageKommando;
                                    }
                                }
                            }
                        }
                        return;
                        ################
                        ##Subroutinen:##
                        ################
                        #++++++++++++++++++++++++
                        sub Kom_Erstellen
                        #++++++++++++++++++++++++
                        {
                            $AnfrageKommando = $_[0];
                                                                        if($debug>=3){plugin_log($plugname,'Kommando: '.$AnfrageKommando);}
                            if ($AnfrageKommando eq ''){return;}
                            $AnfrageWert = '';
                            $AnfrageAnzahl = '';
                            # Antwort=>'', Laenge=>'1'}
                            foreach my $element (@Kommandi) {
                                if ($AnfrageKommando eq $element->{Kdo}) {
                                    $AnfrageName = $element->{Name};
                                    $AnfrageAntwort = $element->{Antwort};
                                    $AnfrageKLaenge = $element->{KLaenge};
                                    $AnfrageALaenge = $element->{ALaenge};
                                    last;
                                }
                            }
                            if ($AnfrageKLaenge > 0) { #Bei Schreibkommandi
                                foreach my $element (@Aktionen) { #Aktionen aus Array auslesen
                                    if (($AnfrageKommando eq $element->{Kdo})) { 
                                        $AnzByte = $element->{AnzByte};
                                        $Umrechnung        = $element->{Umrechnung}; 
                                        if ($AnzByte > 0) { 
                                            if ($AnzByte = 1) {#Schreibkommando mit einem Wert 
                                                my $SchreibWert = $Datenfeld[$element->{StartByte}];
                                                $AnfrageAnzahl = '01';
                                                                        if($debug>=3){plugin_log($plugname,'Datenfeld: '.$Datenfeld[$element->{StartByte}]);}    
                                                if ($Umrechnung eq 'sTemp'){ #Temperatur umrechnen
                                                    $SchreibWert = ($SchreibWert + 20)*2; 
                                                }
                                                $AnfrageWert = DatenByte_generieren($SchreibWert);
                                            } else {    #Schreibkommando mit mehr als einem Wert 
                                            ######### PENDENZ
                                            #    for($i = 0; $i<$element->{AnzByte}; $i++) {
                                            #        $AnfrageAnzahl = 'XXXXXXXXX';
                                            #        $AnfrageWert = $AnfrageWert . DatenByte_generieren( XXXXXXX);
                                            #    }    
                                            }
                                        } else {
                                            $AnfrageAnzahl = '00';
                                        }
                                        last;    
                                    }
                                }
                                                                        if($debug>=3){plugin_log($plugname,'Anfragewert: '.$AnfrageWert);}
                                Kom_Senden($AnfrageKommando, $AnfrageAnzahl, $AnfrageWert);
                        #            my $xxx = Antw_Empfangen(); 
                        #            Antw_Auswerten($xxx);
                            } else { # Bei Lesekommandi
                                Kom_Senden($AnfrageKommando, DatenByte_generieren('0'),'');
                        #            my $yyy = Antw_Empfangen();
                        #            Antw_Auswerten($yyy);
                            }
                        }
                        #++++++++++++++++++++++++
                        sub Kom_Senden
                        #++++++++++++++++++++++++
                        {
                            my $Kommandostring = $_[0];
                            my $Anzahlstring = $_[1];
                            my $Datenstring = $_[2];
                            my $command = $Kommandostring.$Anzahlstring;
                            if ($Datenstring ne ''){$command = $command.$Datenstring;}
                            my $Chkstring    = checksum_berechnen($command);
                                                        if($debug>=5){plugin_log($plugname,'data: ' . $command);}
                                                        if($debug>=5){plugin_log($plugname,'chksum: ' . $Chkstring);}    
                            $command = pack("H*", $AnfrageStart.$command.$Chkstring.$AnfrageEnde);
                            my $commandhex = $command;
                            $commandhex =~ s/(.)/sprintf("0x%x ",ord($1))/eg;
                                                    if($debug>=2){plugin_log($plugname,'transmit: ' . $commandhex);} #Zeigt im Pluginlog das fertige Datenpaket, dass uebertragen wird
                            if ($Kom_Art eq "S"){    
                                $seriel->write($command); #Befehl an die ComfoAir senden
                            } elsif ($Kom_Art eq "M"){    
                                                    if($debug>=5){plugin_log($plugname,'transmit: ' . $command);} #Zeigt im Pluginlog das fertige Datenpaket, dass uebertragen wird
                                syswrite($socket[$socknum], $command);
                            }
                        }
                        #++++++++++++++++++++++++
                        sub Antw_Empfangen
                        #++++++++++++++++++++++++
                        {
                                $reciv = '';
                                my $recivganz = '';
                                my $exit=0;
                                my $siebenWarSchon=0;
                                $sin ='';
                                while($exit < $Zaehler) 
                                { 
                                            if($debug>=5){plugin_log($plugname,'Zaehler: '.$exit);}        
                                    #ein Zeichen einlesen
                                    if ($Kom_Art eq "S"){
                                         my ($cin, $sin) = $seriel->read(1);
                                    }elsif ($Kom_Art eq "M"){
                                        if ($fh) { # Antwort auslesen
                            #                recv($fh,$sin,250,0);
                            #                    my $buf;
                                                read($fh,$sin,1);    
                            #                    read($fh,$buf,1);    
                            #                    $sin = $buf;
                                        }
                                           $cin = length($sin);
                                    }
                                    if($cin > 0){
                                        $sin = unpack "H*", $sin;
                                        $recivganz .= $sin;            #nur zur Protokollierung / Fehlerkennung
                            #            $exit=0;
                                        if ($siebenWarSchon ==1) {    #Spezialfaelle abarbeiten
                                            if ($sin eq '07'){        #Zahl 7 (gemaess Protokoll findet Verdoppelung statt, diese wird hier aufgeloest
                                                $reciv .=$sin;
                                                $siebenWarSchon =0;
                                            }elsif ($sin eq 'f3'){    #ACK empfangen
                                                                                    if($debug>=2){plugin_log($plugname,'ACK empfangen');}
                                                $siebenWarSchon =0;
                        #                        $reciv ='';
                                                if (length($reciv) > 0) { #ein ACK in der Mitte eines Datenpakets (entspricht nicht dem Protokoll, kommt aber in der Praxis vor)
                                                                            if($debug>=2){plugin_log($plugname,'ACK = Ende Datenpaket');}
                                                    if ($Kom_Art eq "S"){ 
                                                        $seriel->write($ack); #ACK senden
                                                    } elsif ($Kom_Art eq "M"){
                                                        syswrite($socket[$socknum], $ack); #ACK senden
                                                    }
                                                    #Schlaufe abbrechen
                                                    $exit = $Zaehler;
                                                    last; 
                                                }
                                            }elsif ($sin eq 'f0'){    #Anfang des Datensatzes
                                                $siebenWarSchon =0;
                        #                        $reciv ='';
                                            }elsif ($sin eq '0f'){    #Ende des Datensatzes
                                                $siebenWarSchon =0;
                                                if ($Kom_Art eq "S"){ 
                                                    $seriel->write($ack); #ACK senden
                                                } elsif ($Kom_Art eq "M"){
                                                    syswrite($socket[$socknum], $ack); #ACK senden
                                                }
                                                                                    if($debug>=3){plugin_log($plugname,'ACK senden');}
                                                #Schlaufe abbrechen
                                                $exit = $Zaehler;
                                                last; 
                                            }
                                        }elsif (($sin eq '07') and ($siebenWarSchon == 0)){
                                            $siebenWarSchon = 1;
                                            #den gelesene Wert braucht es in der Variablen $reviv nicht , er hat nur zusammen mit dem nachfolgenden Zeichen eine Bedeutung
                                        }else{    #Normalfall, eingelesenes Zeichen verwenden
                                            $reciv .=$sin;
                                        }
                                        $exit++    
                                    }else{
                                        $exit++    
                                    }
                                }
                                                            if($debug>=2){plugin_log($plugname,'reciv-vollstaendig:     ' . $recivganz);}
                                                            if($debug>=2){plugin_log($plugname,'reciv:                  ' . $reciv);}    
                                #Nun wird die Checksumme gelesen und aus dem Datenstring entfernt
                                $checksum = 0;
                                $checksum = substr($reciv,-2,2);
                                                            if($debug>=4){plugin_log($plugname,'Checksumme gelesen: '.$checksum);}
                                $laenge = length($reciv); #Laenge des Antworttelegramms ermitteln
                                $reciv = substr($reciv,0,($laenge-2));
                                                            if($debug>=4){plugin_log($plugname,'Datenpaket ohne Checksumme: '.$reciv);}
                                $rcv_checksum = checksum_berechnen($reciv);
                                if($rcv_checksum eq $checksum){
                                                            if($debug>=4){plugin_log($plugname,'reciv: ' . $reciv);} 
                                    return $reciv;
                                } else {
                                        #PENDENZ: Versuchen, aus dem Datenpaket noch valide Daten herauszulesen
                                    return;
                                }                                    
                        } # Ende Antw_Empfangen
                        #++++++++++++++++++++++++
                        sub Antw_EmpfangenAlt
                        #++++++++++++++++++++++++
                        {    
                            $reciv = '';
                            $|=1;
                            my $exit=0;
                            while($exit < $Zaehler) 
                            {
                                if ($Kom_Art eq "S"){
                                     my ($cin, $sin) = $seriel->read(45);
                                }elsif ($Kom_Art eq "M"){
                                      $sin ='';
                                      if ($fh) { # Antwort auslesen
                                        recv($fh,$sin,250,0);
                        #                        my $buf;
                        #                        read($fh,$buf,2);    
                        #                        $sin = $buf;
                                        }
                                       $cin = length($sin);
                                }
                                if($cin > 0){
                                    $sin = unpack "H*", $sin;
                                    $reciv .= $sin;
                                    $exit=0;
                                                        if($debug>=2){plugin_log($plugname,'reciv-direkt:     ' . $sin);}
                                }else{
                                    $exit++
                                }
                                    if($reciv =~ /070f/i){           
                                        if ($Kom_Art eq "S"){
                                            $seriel->write($ack); #ACK senden
                                        } elsif ($Kom_Art eq "M"){
                                            syswrite($socket[$socknum], $ack); #ACK senden
                                        }
                                                                                    if($debug>=3){plugin_log($plugname,'ACK senden');}
                                        last;
                                    }
                            }     #Ende While   
                            while ((length($reciv) > 3) && (substr($reciv,(length($reciv)-4),4) ne '070f')) #solange das Ende nicht 070f lautet
                            {
                                                                                        if($debug>=4){plugin_log($plugname,'String vor Kuerzung Ende: '.$reciv);}
                                    $reciv = substr($reciv,0,-4); #tring um die letzten vier Zeichen kürzen
                                                                                        if($debug>=4){plugin_log($plugname,'String nach Kuerzung Ende: '.$reciv);}
                            }
                                     #Hier wird der empfangene String um Start- und Endbyte gekürzt
                                                     $laenge = length($reciv); #Laenge des Antworttelegramms ermitteln
                                                     $reciv = substr($reciv,0,($laenge-4));
                                                                                    if($debug>=3){plugin_log($plugname,'String ohne 07f3: '.$reciv);}
                                                     my $test = substr($reciv,0,4);
                                                                                    if($debug>=3){plugin_log($plugname,'Erste 4 Byte des Datenpakets: '.$test);}
                                                     while ( $test eq '07f3' or $test eq '07f0' ){
                                                                    $reciv = substr($reciv,4); #falls noch ein 07f3 oder 07f0 am Anfang des Strings enthalten ist, wir dieses hier entfernt.
                                                                                    if($debug>=3){plugin_log($plugname,'reciv gekuerzt: '.$reciv);}
                                                                    $test = substr($reciv,0,4);
                                                                                    if($debug>=3){plugin_log($plugname,'NEU. Erste 4 Byte des Datenpakets: '.$test);}
                                                     }
                                                     
                                     #Nun wird die Checksumme gelesen und aus dem Datenstring entfernt
                                                     $checksum = 0;
                                                     $checksum = substr($reciv,-2,2);
                                                                                    if($debug>=4){plugin_log($plugname,'Checksumme gelesen: '.$checksum);}
                                                     $laenge = length($reciv); #Laenge des Antworttelegramms ermitteln
                                                     $reciv = substr($reciv,0,($laenge-2));
                                                                                    if($debug>=4){plugin_log($plugname,'Datenpaket ohne Checksumme: '.$reciv);}
                                    $rcv_checksum = checksum_berechnen($reciv);
                                    if($rcv_checksum eq $checksum){
                                                                                    if($debug>=4){plugin_log($plugname,'reciv: ' . $reciv);} 
                                        return $reciv;
                                    } else {
                                        return ;
                                    }
                        }
                        
                        #++++++++++++++++++++++++
                        sub Antw_Auswerten
                        #++++++++++++++++++++++++
                        {
                            my $Antwort = $_[0];
                            my $Kommandostring = substr($Antwort,0,4);
                            my $Anzahlstring = substr($Antwort,4,2);
                            my $Datenstring = substr($Antwort,6,999);
                            my $Abfragekommando ='';
                        
                            #Antwort dem entsprechenden Kommando zuordnen
                            foreach my $element (@Kommandi) { #Kommandi aus Array auslesen
                                if (($Kommandostring eq $element->{Antwort})) {
                                    $Abfragekommando = $element->{Kdo};
                                    last;
                                }
                            }
                                                                        if($debug>=3){plugin_log($plugname,'Auswerten Abfragekommando: '.$Abfragekommando);}            
                            
                            #Alle empfangenen Daten behandeln
                            foreach my $element (@Aktionen) { #Aktionen aus Array auslesen
                                if (($Abfragekommando eq $element->{Kdo})) { 
                                    $StartByte = $element->{StartByte};
                                    $AnzByte = $element->{AnzByte};
                                    $GA                    = $element->{GA};
                                    $LogEintrag          = $element->{LogEintrag};
                                    $RRD                 = $element->{RRD};
                                    $Umrechnung            = $element->{Umrechnung}; 
                                    $DPT                  = $element->{DPT};
                                    $hWert = substr($Datenstring,($StartByte-1)*2,($AnzByte*2));
                                    $dWert = hex($hWert);
                                    if ($Umrechnung eq 'lTemp'){
                                        $dWert = ($dWert/2)-20;
                                    }
                                    if ($GA ne ''){                     #Wenn GA vergeben wurde, Wert an die GA senden
                                        knx_write($GA, $dWert,$DPT);
                                    } 
                                    if ($RRD ne ''){
                                        update_rrd($RRD,"",$dWert);
                                    }
                                    if ($LogEintrag ne ''){
                                        plugin_log($plugname,'*******************   ' . $LogEintrag . ': ' . $dWert);
                                    }
                                    # hier kein "last", weil einem Kommando mehrere Daten zugeordnet sein können.
                                }
                            }
                        }
                        
                        
                        #++++++++++++++++++++++++
                        sub DatenByte_generieren 
                        #++++++++++++++++++++++++
                        {    
                            my $data_write =  sprintf "%x", $_[0]; # in Hexadezimalzahl umwandeln
                                                            if($debug>=3){plugin_log($plugname,'Datenstring vorher: '.$data_write);}
                            if ($data_write == 7) {$data_write = "0707";} # das Protokoll verlangt die Verdoppelung, wenn eine 07 übermittelt wird
                            if (length ($data_write) < 2) {$data_write = "0".$data_write}
                                                            if($debug>=3){plugin_log($plugname,'Datenstring nachher: '.$data_write);}
                            return $data_write
                        } #Ende DatenByte_generieren
                        
                        
                        #++++++++++++++++++++++++
                        sub checksum_berechnen 
                        #++++++++++++++++++++++++
                        {    
                            my $chk_datasum = $_[0];
                            $rcv_checksum =0;
                            my $i;
                             $chk_datasum = $chk_datasum . "AD"; #+173 fuer die Checksummenberechnung
                                if($debug>=3){plugin_log($plugname,'String für die Berechnung der Checksumme: '.$chk_datasum);}
                            $x07warschon = 0;
                            $laenge = length($chk_datasum);
                                for($i = 0; $i< $laenge; $i++) {
                                    my $wertstring = substr($chk_datasum,$i,2);
                                    if($debug>=5){plugin_log($plugname,'Zahl: '.$wertstring);}
                                    my $wertbetrag = hex($wertstring);
                                    if ($wertbetrag == 7) {
                                        if ($x07warschon == 1) {
                                            $x07warschon = 0;
                                            $i++;
                                            next;
                                        } else {
                                            $x07warschon = 1;
                                        }
                                    }
                                $rcv_checksum += $wertbetrag;
                                    if($debug>=5){plugin_log($plugname,'Summe: '.$rcv_checksum);}
                                $i++;
                            }
                                    if($debug>=4){plugin_log($plugname,'Summe def: '.$rcv_checksum);}
                        
                            if($debug>=4){plugin_log($plugname,'Checksumme vor der Umwandlung: '.$rcv_checksum);}
                            $rcv_checksum = sprintf "%x\n" , $rcv_checksum; #Mache aus Integer wieder HEX
                            if($debug>=4){plugin_log($plugname,'Checksumme vor der Kürzung: '.$rcv_checksum);}
                            $rcv_checksum = substr($rcv_checksum,-3,2); #Verwende nur die letzten beiden Stellen
                            if($debug>=4){plugin_log($plugname,'Checksumme nach der Kürzung: '.$rcv_checksum);}
                            return $rcv_checksum;
                        } #Ende checksum_berechnen
                        
                        
                        #++++++++++++++++++++++++
                        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
                            {
                                if($debug>=1){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 ($@) 
                                {
                                    if($debug>=1){plugin_log($plugname, " conf file [$confFile] returned:");}
                                    my @parts = split(/\n/, $@);
                                    if($debug>=2){plugin_log($plugname, " --> $_") foreach (@parts);}
                                }
                            }
                        } #Ende readConf
                        Gruss
                        Diego

                        Kommentar


                          Hallo Diego,

                          das sieht schon mal ziemlich cool aus! Ich bin nur mal kurz drübergeflogen da ich eh nur die Hälfte davon verstehe... ;-) Aber ich denke das ist das, worauf ich gewartet habe. Zu jedem Wert optional ein RRD finde ich schon mal gut. Das hinzufügen weiterer Werte aus dem Protokoll scheint auch recht einfach zu sein (Vielleicht macht's ja Sinn einfach alle Werte zu definieren, jeder schaltet nur das aktiv was er haben will?).
                          Ich nehme an, die neue Version antwortet auch auf Lese-Anforderungen an eine GA? Die derzeitige Version tut das (bei mir) nicht.

                          Welchen Vorteil hat eigentlich der Einsatz der Moxa?
                          Endlich umgezogen. Fertig? Noch lange nicht... ;-)

                          Kommentar


                            Zitat von Hauke Beitrag anzeigen
                            Welchen Vorteil hat eigentlich der Einsatz der Moxa?
                            Damit bringst Du ein Gerät mit seriellem Anschluß ins Netzwerk und kannst es vom Rechner aus über über einen virtuellen Comport ansprechen. Die Übertragung dazwischen geschieht über das Netzwerk. Nützlich, wenn man kein serielles Kabel bis zum Gerät ziehen kann.
                            Gruß, Carsten

                            Kommentar


                              Ich glaube ich habe meine Frage etwas unpräzise formuliert. Zur Zeit habe ich die ComfoAir über einen USB-Seriell-Wandler direkt am WG hängen. Das haben glaube ich auch die meisten anderen, die das Plugin einsetzen, so.
                              Ist die Anbindung über Moxa (wenn ich die Daten nur auf dem WG brauche) besser, schneller, ressourcenschonender, etc. oder gibt es sonst irgendwelche Vorteile gegenüber dem USB-Seriell-Wandler?
                              Endlich umgezogen. Fertig? Noch lange nicht... ;-)

                              Kommentar


                                Hallo Hauke

                                Zitat von Hauke Beitrag anzeigen
                                Ist die Anbindung über Moxa (wenn ich die Daten nur auf dem WG brauche) besser, schneller, ressourcenschonender, etc. oder gibt es sonst irgendwelche Vorteile gegenüber dem USB-Seriell-Wandler?
                                Der Grund, weshalb die KWL über eine Moxa anschliesse, liegt in meiner besonderen räumlichen Situation. Die drei Lüftungsgeräte sind im ganzen Haus verteilt, resp. in einem anderen Raum als das Wiregate; eine serielle oder USB-Verkabelung wäre nicht machbar. Weil ich die KWL nie am seriellen Port, resp. an USBangeschlossen hatte, kann ich keinen Vergleich machen.
                                Gruss
                                Diego

                                Kommentar

                                Lädt...
                                X