Ankündigung

Einklappen
Keine Ankündigung bisher.

Problem mit Logikprozessor.pl und Wiregate DPT

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

    [wiregate] Problem mit Logikprozessor.pl und Wiregate DPT

    Guten Morgen,

    ich hoffe ihr könnt mir helfen.

    Ich möchte den Logikprozessor auf meinem Wiregate nutzen und habe das Problem, dass das Plugin zwar laut Plugin-Log Werte sendet, allerdings wird tatsächlich kein Wert auf den KNX Bus gesendet (laut KNX Busmonitor/Log).

    - Wiregate ist auf dem aktuellen Stand
    - Logikprozessor-Skript direkt aus dem SVN gezogen inkl. Beispielkonfig.

    Ausgabe Pugin-Log:

    Code:
    2017-08-10 06:26:44.529,Logikprozessor,1.1.51 5/1/3:1 -> $logic->{mal2}{receive}(Logik) -> 1/1/35:1 gesendet; ,0s,
    2017-08-10 07:03:30.582,Logikprozessor,1.1.51 5/1/3:0 -> $logic->{mal2}{receive}(Logik) -> 1/1/35:0 gesendet; ,0s,
    2017-08-10 07:03:33.723,Logikprozessor,1.1.51 5/1/3:1 -> $logic->{mal2}{receive}(Logik) -> 1/1/35:1 gesendet; ,0s,
    2017-08-10 07:05:46.375,Logikprozessor,1.1.51 5/1/3:0 -> $logic->{mal2}{receive}(Logik) -> 1/1/35:0 gesendet; ,0s,
    Der Logikprozessor empfängt Werte auf dem Bus und wird entsprechend getriggert. Auch wird laut Log ein Wert an eine Gruppenadresse geschickt. In diesem Fall soll testweise eine Lampe geschalten werden auf 1/1/35.

    Lasse ich Warnungen mitloggen wird über das Plugin-Log folgendes ausgegeben:

    Code:
    2017-08-10 11:46:01.045,Logikprozessor,Naechster Aufruf der timer-Logik 'Test'  morgen um 11:46.
    2017-08-10 11:46:01.046,Logikprozessor,Warning: Use of uninitialized value $_ in pattern match (m//) at (eval 2314) line 173.
    2017-08-10 11:46:01.047,Logikprozessor,Warning: Use of uninitialized value $_ in pattern match (m//) at (eval 2314) line 174.
    2017-08-10 11:46:01.047,Logikprozessor,Warning: Use of uninitialized value $_ in pattern match (m//) at (eval 2314) line 175.
    2017-08-10 11:46:01.048,Logikprozessor,Warning: Use of uninitialized value $_ in pattern match (m//) at (eval 2314) line 176.
    2017-08-10 11:46:01.048,Logikprozessor,Warning: Use of uninitialized value $_ in pattern match (m//) at (eval 2314) line 177.
    2017-08-10 11:46:01.048,Logikprozessor,Warning: Use of uninitialized value $_ in pattern match (m//) at (eval 2314) line 178.
    2017-08-10 11:46:01.049,Logikprozessor,Warning: Use of uninitialized value $_ in pattern match (m//) at (eval 2314) line 179.
    2017-08-10 11:46:01.049,Logikprozessor,Warning: Use of uninitialized value $_ in pattern match (m//) at (eval 2314) line 180.
    2017-08-10 11:46:01.049,Logikprozessor,Warning: Use of uninitialized value $_ in pattern match (m//) at (eval 2314) line 181.
    2017-08-10 11:46:01.050,Logikprozessor,Warning: Use of uninitialized value $_ in smart match at (eval 2314) line 182.
    2017-08-10 11:46:01.050,Logikprozessor,Warning: Use of uninitialized value $_ in smart match at (eval 2314) line 183.
    2017-08-10 11:46:01.051,Logikprozessor,Warning: Use of uninitialized value $_ in pattern match (m//) at (eval 2314) line 184.
    2017-08-10 11:46:01.051,Logikprozessor,Warning: Use of uninitialized value $_ in pattern match (m//) at (eval 2314) line 185.
    2017-08-10 11:46:01.051,Logikprozessor,Warning: Use of uninitialized value $_ in pattern match (m//) at (eval 2314) line 186.
    2017-08-10 11:46:01.052,Logikprozessor,Warning: Use of uninitialized value $_ in pattern match (m//) at (eval 2314) line 187.
    2017-08-10 11:46:01.052,Logikprozessor,Warning: Use of uninitialized value $_ in pattern match (m//) at (eval 2314) line 188.
    2017-08-10 11:46:01.053,Logikprozessor,Warning: Use of uninitialized value $dpt in concatenation (.) or string at (eval 2314) line 189.
    2017-08-10 11:46:01.082,Logikprozessor,$logic->{Test}{transmit}(Logik) -> 1/1/35:1 gesendet (timer);  ,0s,
    Das Dämon-Log zeigt außerdem folgendes an:

    Code:
    Aug 10 18:30:03 wiregate1622 /usr/sbin/wiregated.pl: WARN - None or unsupported DPT: sent to 1/1/35 value 1
    Aug 10 18:30:03 wiregate1622 /usr/sbin/wiregated.pl: WARN - None or unsupported DPT: sent to 1/1/35 value 1
    Ich habe meine Gruppenadressen alle importiert aus der ETS5 Datei. Wenn ich mir die Gruppenadresse für die 1/1/35 auf dem Wiregate ansehe, dann scheint auch alles korrekt zu sein.

    Hat einer von euch Ideen, was ich noch versuchen kann?!?

    Danke euch und viele Grüße
    Tino

    PS. Ich hatte mein Problem bereits im Codeschnipsel-Forum (Logikprozessor-Thread) gepostet, vermute aber dass es dort kaum jemand mitbekommt. Bitte verzeiht mir den Doppelpost ;-)
    Zuletzt geändert von tinom86; 11.08.2017, 11:04.

    #2
    Hallo Tino

    Versuch mal den DTP im Wiregate nochmals einzustellen. Wahrscheinlich steht da einfach DTP 1 stell das mal auf DTP 1.1 schalten (oder so ähnlich, habs grad nicht vor Augen) um.

    Ich hatte auch schon Probleme mit importierten DTP`s. Das zuordnen zur richtigen DTP Untergruppe hat eigentlich immer geholfen. Ev dan den EIBD neu starten

    Gruess Markus

    Kommentar


      #3
      Hi Markus,

      danke für die Info.

      In der eibga.conf ist es wie folgt eingetragen:

      [1/1/35]
      DPTSubId = 1.001
      short = EG
      ga = 1/1/35
      DPTId = 1
      name = EG B▒ro L2 E6-L2 s
      DPT_SubTypeName = DPT_Switch

      Meinst du hierbei die DPTId müsste "1.1" sein statt "1"?

      Hab es mal mit 1.1 probiert... das Log sagt leider noch immer:

      Code:
      Aug 11 11:56:17 wiregate1622 /usr/sbin/wiregated.pl: WARN - None or unsupported DPT: sent to 1/1/35 value 1
      Aug 11 11:56:20 wiregate1622 /usr/sbin/wiregated.pl: WARN - None or unsupported DPT: sent to 1/1/35 value 1
      VG
      Tino
      Zuletzt geändert von tinom86; 11.08.2017, 10:58.

      Kommentar


        #4
        Hallo Tino,

        Zitat von tinom86 Beitrag anzeigen
        - Wiregate ist auf dem aktuellen Stand
        Auch wenn die Wiederholungen lästig sind. Immer die Versionsnummer angeben, sonst blickt in zwei Jahren keiner mehr durch.

        Zitat von tinom86 Beitrag anzeigen
        - Logikprozessor-Skript direkt aus dem SVN gezogen inkl. Beispielkonfig.
        Wirklich aus dem SVN oder von Github? Ist etwas aktueller.

        Nach dem Ändern des DPT hilft es bei mir immer den "WireGate Serverprozess" neu zu starten. Hatte sonst auch das Porblem unbekanter DPT.

        Grüße
        Stefan


        Contribute to Wiregate development by creating an account on GitHub.

        Kommentar


          #5
          Zitat von Hammer69 Beitrag anzeigen
          Hallo Tino,


          Auch wenn die Wiederholungen lästig sind. Immer die Versionsnummer angeben, sonst blickt in zwei Jahren keiner mehr durch.



          Wirklich aus dem SVN oder von Github? Ist etwas aktueller.

          Nach dem Ändern des DPT hilft es bei mir immer den "WireGate Serverprozess" neu zu starten. Hatte sonst auch das Porblem unbekanter DPT.

          Grüße
          Stefan

          Hallo Stefan,

          danke für deine Hilfe.

          Wiregate Version: wiregate1622 / 1.4.0

          Die Version aus Github habe ich mittlerweile auch schon probiert, funktioniert ebenfalls nicht. Auch habe ich nach dem Ändern der DPT das Wiregate neu gestartet - ebenfalls kein Erfolg.

          Im Anhang habe ich einen Screenshot vom Code des Plugin. Ab Zeile 104 scheinen zumindest laut Formatierung des Editor die Syntax nicht mehr zu passen - ich vermute allerdings eher dass es am Editor liegt. Bin leider kein Entwickler. Ein Fehler wird zumindest nicht ausgegeben.

          VG
          Tino

          You do not have permission to view this gallery.
          This gallery has 1 photos.

          Kommentar


            #6
            Hallo Tino,

            ändere doch mal bitte die eibga.conf wie folgt ab
            Code:
            [1/1/35]
            DPTSubId=1.001
            DPTId=1
            name=EG_Buero_L2_E6-L2_s
            DPT_SubTypeName=DPT_Switch
            Danach die Prozesse oder das komplette WG neu starten.

            Grüße
            Stefan

            Kommentar


              #7
              Hallo zusammen,

              möchte euch die Lösung nicht vorenthalten. Ein anderes Plugin hat gestört :O

              Ich hatte zusätzlich ein Plugin installiert, dass alle 5min meinen EMH Zähler ausliest (siehe unterer Code). Nachdem ich es entfernt hatte, ging auch der Logikprozessor wieder. Das Zählerskript läuft jetzt direkt per Cronjob.

              VG
              Tino

              Zitat von coolrunnings Beitrag anzeigen
              Also ich hab auch nen Zähler von der RWE, aber den ISKRA und nicht den EMH. Damit klappt es einwandfrei.

              Ich hab den Code mal angepasst, so dass die 4 für 24 bit steht und 6 für 40 bit. Konnte darüber allerdings nichts in der Spezi finden. Dann sähen die OBIS Daten so aus:

              Code:
              77
              07 01 00 01 08 00 FF # ID 1-1.8.0
              64 00 01 82 # Status 0x182 --> 386
              01 # keine Zeit
              62 1E # Unit 0x1E --> 30 --> Wh
              52 FF # Scaler -1 --> value+10^-1
              56 00 01 58 3F 53 # Value: 0x1583F53 --> 22560595 Wh --> 2256,0595 kWh
              01 # keine value Signatur
              Du hast du OBIS IDs 1.8.0, 1.8.1, 1.8.2 und 16.7.0
              Hier der Code:

              Code:
              #!/usr/bin/perl
              #
              # Autor: coolrunnings / www.knx-user-forum.de
              # Based on the PlugIn sml-meter by JuMi2006 / www.knx-user-forum.de
              # knx_write sub: makki / www.knx-user-forum.de
              # Version: 0.2
              # Datum: 03.11.2013
              # Licenced under the GPLv3
              
              use warnings;
              use strict;
              use Device::SerialPort;
              use feature "switch";
              use EIBConnection;
              use RRDs;
              use Scalar::Util qw(looks_like_number);
              
              #####################################################################
              # define everything here
              my $eib_url = "local:/tmp/eib"; #for local eibd "local:/tmp/eib" for eibd in LAN: "ip:192.168.2.220:6720"
              my $device = "/dev/ttyUSB0";
              my $rrdpath = "/var/www/rrd";
              
              my @obis;
              push @obis,{obis=>"1.8.0", ga =>"9/0/0", dpt => 14, rrd_name => "zaehler_verbrauch"};
              push @obis,{obis=>"16.7.0", ga =>"9/0/1", dpt => 9, rrd_name => "zaehler_leistung" };
              push @obis,{obis=>"36.7.0", ga =>"9/0/2", dpt => 9, rrd_name => "zaehler_leistung_L1"};
              push @obis,{obis=>"56.7.0", ga =>"9/0/3", dpt => 9, rrd_name => "zaehler_leistung_L2"};
              push @obis,{obis=>"76.7.0", ga =>"9/0/4", dpt => 9, rrd_name => "zaehler_leistung_L3"};
              my @countermodes = (5,15,60,1440); #Aufloesungen fuer COUNTER RRDs in Minuten (1440 = Tagesverbrauch)
              my @derivemodes = (5,15,60,1440); #Aufloesungen fuer DERIVE RRDs in Minuten (1440 = Tagesverbrauch)
              
              my $debug = "1";
              my $logging = "1";
              my $port = Device::SerialPort->new($device) || die $!;
              $port->databits(8);
              $port->baudrate(9600);
              $port->parity("none");
              $port->stopbits(1);
              $port->handshake("none");
              $port->write_settings;
              $port->dtr_active(1);
              $port->purge_all();
              $port->read_char_time(0); # don't wait for each character
              $port->read_const_time(2000); # 1 second per unfulfilled "read" call
              
              #####################################################################
              # don't touch anything starting here
              
              my $filename = "/tmp/sml_meter.log";
              if ( $logging == "1" ) {open (LOG, ">>$filename") or $logging = "0";}
              
              if ( $logging == "1" ) {print LOG "===============================================\n";}
              if ( $logging == "1" ) {print LOG (localtime)." Start new run\n";}
              
              
              my ($x,$rawdata) = 0 ;
              my $count = 0;
              my $saw = 0;
              my $start = 0;
              
              if ($debug == 1) {print "Step 1 - Collect data \n";}
              if ($logging == 1) {print LOG "Step 1 - Collect data \n";}
              
              while ($start < 2) { # wait for second 1B1B1B1B01010101
              
              ($count,$saw)=$port->read(512); # will read 512 chars
              if ($count == 512) { # 512 chars read?
              $x = uc(unpack('H*',$saw)); # nach hex wandeln
              $rawdata .= $x;
              if ($rawdata =~ /1B1B1B1B01010101/) {$start ++};
              } # if
              } # while
              
              if ($debug==1) {print "Step 2 - Reg Exp 1 build dataset \n";}
              if ($logging==1) {print LOG "Step 2 - Reg Exp 1 build dataset \n";}
              
              $rawdata =~ m/1B1B1B1B01010101(.*?)B1B1B1/;
              print $rawdata."\n";
              
              if ($debug==1) {print "Step 3 - Analyze data \n";}
              if ($logging==1) {print LOG "Step 3 - Analyze data \n";}
              
              # find OBIS values in raw data
              foreach my $obiscnt (@obis) {
              if ( $debug == 1 ) {print "\n";}
              if ( $logging == 1 ) {print LOG "-----------------------------------------------\n";}
              my $obissearch = &obis2search($obiscnt->{obis});
              
              $rawdata =~ m/$obissearch(.*?)017707/;
              my $obisdata = $1."01";
              
              if ( $debug == 1 ) {print "found: ".$obisdata."\n";}
              if ( $logging == 1 ) {print LOG "found: ".$obisdata."\n";}
              
              my $smlStatus = "";
              my $smlValTime = "";
              my $smlUnit = "";
              my $smlScaler = "";
              my $smlValue = "";
              my $smlValueS = "";
              
              ## check status
              if ( $debug == 1 ) {print "check sml status: ";}
              if ( $logging == 1 ) {print LOG "check sml status: ";}
              $smlStatus = &parseOBIS(\$obisdata);
              
              ## check value time
              if ( $debug == 1 ) {print "check sml value time: ";}
              if ( $logging == 1 ) {print LOG "check sml value time: ";}
              $smlValTime = &parseOBIS(\$obisdata);
              
              ## check unit
              if ( $debug == 1 ) {print "check sml unit: ";}
              if ( $logging == 1 ) {print LOG "check sml unit: ";}
              $smlUnit = &parseOBIS(\$obisdata);
              
              ## check scaler
              if ( $debug == 1 ) {print "check sml scaler: ";}
              if ( $logging == 1 ) {print LOG "check sml scaler: ";}
              $smlScaler = &parseOBIS(\$obisdata);
              
              ## check value
              if ( $debug == 1 ) {print "check sml value: ";}
              if ( $logging == 1 ) {print LOG "check sml value: ";}
              $smlValue = &parseOBIS(\$obisdata);
              
              ## check value signature
              if ( $debug == 1 ) {print "check sml value signature: ";}
              if ( $logging == 1 ) {print LOG "check sml value signature: ";}
              $smlValueS = &parseOBIS(\$obisdata);
              
              #print "done: ".$obisdata."\n";
              #print $smlStatus;
              
              # Calculate value
              if ( $smlValue ne "" ) {
              my $calcvalue = ($smlValue * (10**$smlScaler));
              
              # Modify value depening on unit
              my $smlUnitCfg_ref = &getSMLUnitStr($smlUnit);
              my @smlUnitCfg = @{$smlUnitCfg_ref};
              
              if ( (@smlUnitCfg) == 2 ) {
              my $tUnitStr = $smlUnitCfg[0];
              my $tUnitRRD = $smlUnitCfg[1];
              
              # Wh to kWh
              if ( $smlUnit == 30 ) {
              $calcvalue = $calcvalue * 0.001;
              $tUnitStr = "kWh";
              }
              
              if ( $debug == 1 ) {print "Unit config: [".$tUnitStr."][".$tUnitRRD."]\n";}
              if ( $logging == 1 ) {print LOG "Unit config: [".$tUnitStr."][".$tUnitRRD."]\n";}
              
              if ( $debug == 1 ) {print "Final value: [".$calcvalue." ".$tUnitStr."]\n";}
              if ( $logging == 1 ) {print LOG "Final value: [".$calcvalue." ".$tUnitStr."]\n";}
              
              # write rrd
              if ($tUnitRRD =~ m/c/) {
              &rrd_counter ($obiscnt->{rrd_name},$calcvalue)
              }
              
              if ($tUnitRRD =~ m/d/) {
              &rrd_derive ($obiscnt->{rrd_name},$calcvalue)
              }
              
              if ($tUnitRRD =~ m/g/) {
              &rrd_gauge ($obiscnt->{rrd_name},$calcvalue)
              }
              
              # send value to bus
              &knx_write ($obiscnt->{ga},$calcvalue,$obiscnt->{dpt});
              if ($debug == 1) {print "GA:".$obiscnt->{ga}." value:".$calcvalue." DPT:".$obiscnt->{dpt}."\n";}
              if ($logging == 1) {print LOG "GA:".$obiscnt->{ga}." value:".$calcvalue." DPT:".$obiscnt->{dpt}."\n";}
              
              
              }
              else {
              if ( $debug == 1 ) {print "No unit found. No data will be written.\n";}
              if ( $logging == 1 ) {print LOG "No unit found. No data will be written.\n";}
              }
              }
              }
              
              $port->close() || warn "Serial port did not close proper!\n";
              undef $port;
              
              if ( $logging == "1" ) {close LOG;}
              
              ## subs ##
              
              #####################################################################
              # convert OBIS to search parameter
              sub obis2search {
              
              my ($obisid) = @_;
              my $res = "77070100";
              
              if ($debug==1) { print "OBIS ID: ".$obisid."\n";}
              if ($logging==1) { print LOG "OBIS ID: ".$obisid."\n";}
              
              foreach my $c ( split(/\./,$obisid) ) {
              $res .= sprintf("%02X",$c);
              }
              
              $res .= "FF";
              
              if ($debug==1) { print "OBIS search: ".$res."\n";}
              if ($logging==1) { print LOG "OBIS search: ".$res."\n";}
              
              return $res;
              }
              
              #####################################################################
              # parse OBIS data
              sub parseOBIS {
              #my ($obisdata) = @_;
              my $r_obisdata = shift;
              my $res = "";
              
              if ( length($$r_obisdata) < 2 ) {
              print "error --> data too short\n";
              return $res;
              }
              
              my $smlDataTypeID = substr($$r_obisdata,0,2);
              
              if ( $smlDataTypeID == "01" ) {
              ## no data
              if ( $debug == 1 ) {print "[empty]\n";}
              if ( $logging == 1 ) {print LOG "[empty]\n";}
              $$r_obisdata =~ s/^..//; # remove first 2 characters
              return $res;
              }
              else {
              #if ( $debug == 1 ) {print "found something ";}
              #if ( $logging == 1 ) {print LOG "found something ";}
              
              my $smlDataType = substr($smlDataTypeID,0,1);
              my $smlIntBitCode = substr($smlDataTypeID,1,1);
              
              # only signed and unsigned int possible
              if ( $smlDataType != "5" && $smlDataType != "6") {
              if ( $debug == 1 ) {print "Invalid datatype [".$smlDataType."]\n"; };
              if ( $logging == 1 ) {print LOG "Invalid datatype [".$smlDataType."]\n"; };
              return $res;
              }
              
              $$r_obisdata =~ s/^..//; # remove first 2 characters
              
              
              my $smlIntBitCnt = 0;
              
              #switch ( $smlIntBitCode ) {
              # case 2 { $smlIntBitCnt = 8 }
              # case 3 { $smlIntBitCnt = 16 }
              # case 5 { $smlIntBitCnt = 32 }
              # case 9 { $smlIntBitCnt = 64 }
              # else { if ( $debug == 1 ) {print "Invalid integer bit count [".$smlIntBitCode."]\n"; };
              # return $res;
              # }
              #}
              
              if ( $smlIntBitCode == 2 ) {
              $smlIntBitCnt = 8
              }
              elsif ( $smlIntBitCode == 3 ) {
              $smlIntBitCnt = 16
              }
              elsif ( $smlIntBitCode == 4 ) { # not conform with the SML specification!
              $smlIntBitCnt = 24
              }
              elsif ( $smlIntBitCode == 5 ) {
              $smlIntBitCnt = 32
              }
              elsif ( $smlIntBitCode == 6 ) { # not conform with the SML specification!
              $smlIntBitCnt = 40
              }
              elsif ( $smlIntBitCode == 9 ) {
              $smlIntBitCnt = 64
              }
              else {
              if ( $debug == 1 ) {print "Invalid integer bit count [".$smlIntBitCode."]\n"; };
              if ( $logging == 1 ) {print LOG "Invalid integer bit count [".$smlIntBitCode."]\n"; };
              return $res;
              }
              
              my $smlIntCharCnt = ($smlIntBitCnt/4);
              
              # check that the rest of the string is long enought for the bit count
              if ( (length($$r_obisdata)) < $smlIntCharCnt ) {
              if ( $debug == 1 ) {print "String not long enough for for detected bit count [".$smlIntCharCnt."]\n"; };
              if ( $logging == 1 ) {print LOG "String not long enough for for detected bit count [".$smlIntCharCnt."]\n"; };
              return $res;
              }
              
              # get the hex values
              my $hexval = substr($$r_obisdata,0,$smlIntCharCnt);
              $$r_obisdata = substr($$r_obisdata,$smlIntCharCnt);
              
              # if signed, get 2' complement
              if ( $smlDataType == 5 ) {
              my $hexbin = sprintf("%0${smlIntBitCnt}b",hex($hexval));
              
              if ( substr($hexbin,0,1) == 1 ) {
              #if ( $debug == 1 ) { print "2's complement \n"; }
              #if ( $logging == 1 ) { print LOG "2's complement \n"; }
              my $hexinv = sprintf("%08x",~hex($hexval));
              $res = (substr($hexinv,6,2)+1)*(-1);
              
              }
              else {
              $res = hex($hexval);
              }
              }
              else {
              $res = hex($hexval);
              }
              
              if ( $debug == 1 ) { print "[".$res."]\n";}
              if ( $logging == 1 ) { print LOG "[".$res."]\n";}
              
              return $res;
              }
              
              return $res;
              }
              
              #####################################################################
              # get SML unit string depending on value
              # DLMS Units as specified in ISO EN 62056-62 and used by SML
              # original values from unit.h in vzlogger project
              # The volkszaehler.org project
              sub getSMLUnitStr {
              
              my ($smlUnitCode) = @_;
              
              my %unitmap = (
              # code # unit #rrd # quantity #name #SI definition
              
              1 => [ "a", "g" ], # time year 52*7*24*60*60 s
              2 => [ "mo", "g" ], # time month 31*24*60*60 s
              3 => [ "wk", "g" ], # time week 7*24*60*60 s
              4 => [ "d", "g" ], # time day 24*60*60 s
              5 => [ "h", "g" ], # time hour 60*60 s
              6 => [ "min.", "g" ], # time min 60 s
              7 => [ "s", "g" ], # time (t) second s
              8 => [ "°", "g" ], # (phase) angle degree rad*180/π
              9 => [ "°C", "g" ], # temperature (T) degree celsius K-273.15
              10 => [ "currency", "g" ], # (local) currency
              11 => [ "m", "g" ], # length (l) metre m
              12 => [ "m/s", "g" ], # speed (v) metre per second m/s
              13 => [ "m³", "g" ], # volume (V) cubic metre m³
              14 => [ "m³", "g" ], # corrected volume cubic metre m³
              15 => [ "m³/h", "g" ], # volume flux cubic metre per hour m³/(60*60s)
              16 => [ "m³/h", "g" ], # corrected volume flux cubic metre per hour m³/(60*60s)
              17 => [ "m³/d", "g" ], # volume flux m³/(24*60*60s)
              18 => [ "m³/d", "g" ], # corrected volume flux m³/(24*60*60s)
              19 => [ "l", "g" ], # volume litre 10-3 m³
              20 => [ "kg", "g" ], # mass (m) kilogram
              21 => [ "N", "g" ], # force (F) newton
              22 => [ "Nm", "g" ], # energy newtonmeter J = Nm = Ws
              23 => [ "Pa", "g" ], # pressure (p) pascal N/m²
              24 => [ "bar", "g" ], # pressure (p) bar 10⁵ N/m²
              25 => [ "J", "g" ], # energy joule J = Nm = Ws
              26 => [ "J/h", "g" ], # thermal power joule per hour J/(60*60s)
              27 => [ "W", "g" ], # active power (P) watt W = J/s
              28 => [ "VA", "g" ], # apparent power (S) volt-ampere
              29 => [ "var", "g" ], # reactive power (Q) var
              30 => [ "Wh", "cdg" ], # active energy watt-hour W*(60*60s)
              31 => [ "VAh", "g" ], # apparent energy volt-ampere-hour VA*(60*60s)
              32 => [ "varh", "g" ], # reactive energy var-hour var*(60*60s)
              33 => [ "A", "g" ], # current (I) ampere A
              34 => [ "C", "g" ], # electrical charge (Q) coulomb C = As
              35 => [ "V", "g" ], # voltage (U) volt V
              36 => [ "V/m", "g" ], # electr. field strength (E) volt per metre
              37 => [ "F", "g" ], # capacitance (C) farad C/V = As/V
              38 => [ "Ω", "g" ], # resistance (R) ohm Ω = V/A
              39 => [ "Ωm²/m", "g" ], # resistivity (ρ) Ωm
              40 => [ "Wb", "g" ], # magnetic flux (Φ) weber Wb = Vs
              41 => [ "T", "g" ], # magnetic flux density (B) tesla Wb/m2
              42 => [ "A/m", "g" ], # magnetic field strength (H) ampere per metre A/m
              43 => [ "H", "g" ], # inductance (L) henry H = Wb/A
              44 => [ "Hz", "g" ], # frequency (f => ω) hertz 1/s
              45 => [ "1/(Wh)", "g" ], # R_W (Active energy meter constant or pulse value)
              46 => [ "1/(varh)", "g" ], # R_B (reactive energy meter constant or pulse value)
              47 => [ "1/(VAh)", "g" ], # R_S (apparent energy meter constant or pulse value)
              48 => [ "V²h", "g" ], # volt-squared hour ´ volt-squaredhours V²(60*60s)
              49 => [ "A²h", "g" ], # ampere-squared hour ampere-squaredhours A²(60*60s)
              50 => [ "kg/s", "g" ], # mass flux kilogram per second kg/s
              51 => [ "S => mho", "g" ], # conductance siemens 1/Ω
              52 => [ "K", "g" ], # temperature (T) kelvin
              53 => [ "1/(V²h)", "g" ], # R_U²h (Volt-squared hour meter constant or pulse value)
              54 => [ "1/(A²h)", "g" ], # R_I²h (Ampere-squared hour meter constant or pulse value)
              55 => [ "1/m³", "g" ], # R_V => meter constant or pulse value (volume)
              56 => [ "%", "g" ], # percentage %
              57 => [ "Ah", "g" ], # ampere-hours ampere-hour
              60 => [ "Wh/m³", "g" ], # energy per volume 3,6*103 J/m³
              61 => [ "J/m³", "g" ], # calorific value, wobbe
              62 => [ "Mol %", "g" ], # molar fraction of mole percent (Basic gas composition unit)
              # gas composition
              63 => [ "g/m³", "g" ], # mass density, quantity of material (Gas analysis => accompanying elements)
              64 => [ "Pa s", "g" ], # dynamic viscosity pascal second (Characteristic of gas stream)
              253 => [ "(reserved)", "g"], # reserved
              254 => [ "(other)", "g" ], # other unit
              255 => [ "(unitless)", "g"] # no unit, unitless, count
              );
              
              #print "-------- unit ".$unitmap{$smlUnitCode}[0]."\n";
              
              #print "-------- unit ".$unitmap{$smlUnitCode}."\n";
              
              my $unitarray_ref = $unitmap{$smlUnitCode};
              
              return $unitarray_ref;
              
              }
              
              #####################################################################
              
              sub knx_write {
              my ($dst,$value,$dpt,$response,$dbgmsg) = @_;
              my $bytes;
              my $apci = ($response) ? 0x40 : 0x80; # 0x40=response, 0x80=write
              # DPT 1 (1 bit) = EIS 1/7 (move=DPT 1.8, step=DPT 1.7)
              # DPT 2 (1 bit controlled) = EIS 8
              # DPT 3 (3 bit controlled) = EIS 2
              # DPT 4 (Character) = EIS 13
              # DPT 5 (8 bit unsigned value) = EIS 6 (DPT 5.1) oder EIS 14.001 (DPT 5.10)
              # DPT 6 (8 bit signed value) = EIS 14.000
              # DPT 7 (2 byte unsigned value) = EIS 10.000
              # DPT 8 (2 byte signed value) = EIS 10.001
              # DPT 9 (2 byte float value) = EIS 5
              # DPT 10 (Time) = EIS 3
              # DPT 11 (Date) = EIS 4
              # DPT 12 (4 byte unsigned value) = EIS 11.000
              # DPT 13 (4 byte signed value) = EIS 11.001
              # DPT 14 (4 byte float value) = EIS 9
              # DPT 15 (Entrance access) = EIS 12
              # DPT 16 (Character string) = EIS 15
              # $dpt = $eibgaconf{$dst}{'DPTSubId'} unless $dpt; # read dpt from eibgaconf if existing
              given ($dpt) {
              when (/^12/) { $bytes = pack ("CCL>", 0, $apci, $value); } #EIS11.000/DPT12 (4 byte unsigned)
              when (/^13/) { $bytes = pack ("CCl>", 0, $apci, $value); }
              when (/^14/) { $bytes = pack ("CCf>", 0, $apci, $value); }
              when (/^16/) { $bytes = pack ("CCa14", 0, $apci, $value); }
              when (/^17/) { $bytes = pack ("CCC", 0, $apci, $value & 0x3F); }
              when (/^20/) { $bytes = pack ("CCC", 0, $apci, $value); }
              when (/^\d\d/) { return; } # other DPT XX 15 are unhandled
              when (/^[1,2,3]/) { $bytes = pack ("CC", 0, $apci | ($value & 0x3f)); } #send 6bit small
              when (/^4/) { $bytes = pack ("CCc", 0, $apci, ord($value)); }
              when ([5,5.001]) { $bytes = pack ("CCC", 0, $apci, encode_dpt5($value)); } #EIS 6/DPT5.001 1byte
              when ([5.004,5.005,5.010]) { $bytes = pack ("CCC", 0, $apci, $value); }
              when (/^5/) { $bytes = pack ("CCC", 0, $apci, $value); }
              when (/^6/) { $bytes = pack ("CCc", 0, $apci, $value); }
              when (/^7/) { $bytes = pack ("CCS>", 0, $apci, $value); }
              when (/^8/) { $bytes = pack ("CCs>", 0, $apci, $value); }
              when (/^9/) { $bytes = pack ("CCCC", 0, $apci, encode_dpt9($value)); } #EIS5/DPT9 2byte float
              default { LOGGER('WARN',"None or unsupported DPT: $dpt sent to $dst value $value"); return; }
              }
              my $leibcon = EIBConnection->EIBSocketURL($eib_url) or return("Error opening con: $!");
              if ($leibcon->EIBOpenT_Group(str2addr($dst),1) == -1) { return("Error opening group: $!"); }
              my $res=$leibcon->EIBSendAPDU($bytes);
              $leibcon->EIBClose();
              return $res;
              
              # str2addr: Convert an EIB address string in the form "1/2/3" or "1.2.3" to an integer
              sub str2addr {
              my $str = $_[0];
              if ($str =~ /(\d+)\/(\d+)\/(\d+)/) { # logical address
              return ($1 << 11) | ($2 << 8) | $3;
              } elsif ($str =~ /(\d+)\.(\d+)\.(\d+)/) { # physical address
              return ($1 << 12) | ($2 << 8) | $3;
              } else {
              #bad
              return;
              }
              }
              
              }
              
              #####################################################################
              
              sub encode_dpt9
              {
              # 2byte signed float
              my $state = shift;
              my $data;
              my $sign = ($state <0 ? 0x8000 : 0);
              my $exp = 0;
              my $mant = 0;
              $mant = int($state * 100.0);
              while (abs($mant) > 2047)
              {
              $mant /= 2;
              $exp++;
              }
              $data = $sign | ($exp << 11) | ($mant & 0x07ff);
              return $data >> 8, $data & 0xff;
              }
              
              #####################################################################
              
              sub rrd_counter
              {
              if ($debug==1){print ("COUNTER","\n")};
              if ($logging==1){print LOG ("-- COUNTER ---","\n")};
              
              my $obisname = $_[0];
              if ($debug==1){print "obisname ".$obisname."\n";}
              if ($logging==1){print LOG "obisname ".$obisname."\n";}
              my $value = $_[1];
              if ($debug==1){print "value ".$value."\n";}
              if ($logging==1){print LOG "value ".$value."\n";}
              
              foreach (@countermodes)
              {
              my $rrdname = $obisname."_".$_."_c\.rrd";
              if ($debug==1){print "rrdname ".$rrdname."\n"};
              if ($logging==1){print LOG "----------\n"};
              if ($logging==1){print LOG "rrdname ".$rrdname."\n"};
              my $rrdfile = $rrdpath."\/".$rrdname;
              unless (-e $rrdfile)
              {
              RRDs::create ($rrdfile,"DS:value:COUNTER:".(($_*60)+600).":0:U",
              "RRA:AVERAGE:0.5:1:366",
              "RRA:AVERAGE:0.5:7:1308",
              "-s ".($_*60)); # step
              }
              my $countervalue = int($value*$_*60);
              if ($debug==1){print "[".$value."]*[".$_."]*[60] = ".$countervalue." countervalue \n";}
              if ($logging==1){print LOG "[".$value."]*[".$_."]*[60] = ".$countervalue." countervalue \n";}
              RRDs::update("$rrdfile", "N:$countervalue");
              }
              }
              
              sub rrd_derive
              {
              if ($debug==1){print ("DERIVE","\n")};
              if ($logging==1){print LOG ("-- DERIVE ---","\n")};
              
              my $obisname = $_[0];
              if ($debug==1){print "obisname ".$obisname."\n";}
              if ($logging==1){print LOG "obisname ".$obisname."\n";}
              my $value = $_[1];
              if ($debug==1){print "value ".$value."\n";}
              if ($logging==1){print LOG "value ".$value."\n";}
              
              foreach (@derivemodes)
              {
              my $rrdname = $obisname."_".$_."_d\.rrd";
              if ($debug==1){print "rrdname ".$rrdname."\n"};
              if ($logging==1){print LOG "----------\n"};
              if ($logging==1){print LOG "rrdname ".$rrdname."\n"};
              my $rrdfile = $rrdpath."\/".$rrdname;
              unless (-e $rrdfile)
              {
              RRDs::create ($rrdfile,"DS:value:DERIVE:".(($_*60)+600).":0:U",
              "RRA:AVERAGE:0.5:1:366",
              "RRA:AVERAGE:0.5:7:1308",
              "-s ".($_*60)); # step
              }
              my $derivevalue = int($value*$_*60);
              if ($debug==1){print "[".$value."]*[".$_."]*[60] = ".$derivevalue." derivevalue \n";}
              if ($logging==1){print LOG "[".$value."]*[".$_."]*[60] = ".$derivevalue." derivevalue \n";}
              RRDs::update("$rrdfile", "N:$derivevalue");
              }
              }
              
              #####################################################################
              
              sub rrd_gauge
              {
              if ($debug==1){print ("GAUGE","\n")};
              if ($logging==1){print LOG ("-- GAUGE --","\n")};
              my $obisname = $_[0];
              if ($debug==1){print "obisname ".$obisname."\n";}
              if ($logging==1){print LOG "obisname ".$obisname."\n";}
              my $value = $_[1];
              if ($debug==1){print "value ".$value."\n";}
              if ($logging==1){print LOG "value ".$value."\n";}
              my $rrdname = $obisname."_g\.rrd";
              if ($debug==1){print "rrdname ".$rrdname."\n"};
              if ($logging==1){print LOG "rrdname ".$rrdname."\n"};
              my $rrdfile = $rrdpath."\/".$rrdname;
              unless (-e $rrdfile)
              {
              RRDs::create ($rrdfile,"DS:value:GAUGE:900:0:U",
              "RRA:AVERAGE:0.5:1:2016", # 5 minutes for 7 days
              "RRA:AVERAGE:0.5:6:1488", # 30 minutes for 31 days
              "RRA:AVERAGE:0.5:12:4392", # 1 hour for 5 month
              "RRA:AVERAGE:0.5:72:7320", # 6 hours for 5 years
              "RRA:AVERAGE:0.5:2016:1308"); # 1 day for 25 years
              }
              RRDs::update("$rrdfile", "N:$value");
              }

              Kommentar

              Lädt...
              X