Vielen Dank.
Ein tolles vorzeitiges Weihnachtsgeschenk!

Ich werde das Plugin umgehend testen...
Ein tolles vorzeitiges Weihnachtsgeschenk!

Ich werde das Plugin umgehend testen...
# 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
Wir verarbeiten personenbezogene Daten über die Nutzer unserer Website mithilfe von Cookies und anderen Technologien, um unsere Dienste bereitzustellen. Weitere Informationen findest Du in unserer Datenschutzerklärung.
Indem Du unten auf "ICH stimme zu" klickst, stimmst Du unserer Datenschutzerklärung und unseren persönlichen Datenverarbeitungs- und Cookie-Praktiken zu, wie darin beschrieben. Du erkennst außerdem an, dass dieses Forum möglicherweise außerhalb Deines Landes gehostet wird und bist damit einverstanden, dass Deine Daten in dem Land, in dem dieses Forum gehostet wird, gesammelt, gespeichert und verarbeitet werden.
Kommentar