Ankündigung

Einklappen
Keine Ankündigung bisher.

Zählerabfrage als Wiregate Plugin

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

    Genau das wollte ich am Ende damit errreichen!

    Ich hab ja selbst keinen SML-Zähler, daher ist es besser wenn es jemand macht der das vor Ort testen kann.
    Bitte auch das Ergebnis posten oder am besten gleich im SVN updaten.
    Umgezogen? Ja! ... Fertig? Nein!
    Baustelle 2.0 !

    Kommentar


      So. Feierabend für heute.
      Ich habe das sml_meter Skript soweit angepasst, dass die Daten automatisch interpretiert werden.
      Bei mir getestet und für gut befunden
      Es wäre super, wenn das sonst wer mit nem SML eHz auch noch testen könnte.

      Was ich noch nicht getestet habe sind die rrd Dateien. Das habe ich aber 1 zu 1 vom Original so übernommen.

      Wenn ich in den nächsten Tagen noch Zeit habe, werde ich mich mal mit socat befassen...

      Code:
      use warnings;
      use strict;
      use Device::SerialPort;
      use feature "switch";
      use EIBConnection;
      use RRDs;
      use Switch;
      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",  fact=>"0.001", ga =>"9/0/0", dpt =>  9, rrd_name => "zaehler_verbrauch", rrd => "c" }; #rrd: c=counter ; g=gauge
      push @obis,{obis=>"16.7.0", fact=>"",      ga =>"9/0/1", dpt =>  9, rrd_name => "zaehler_leistung",  rrd => "g" };
      push @obis,{obis=>"36.7.0", fact=>"",      ga =>"9/0/2", dpt =>  9, rrd_name => "zaehler_leistung_L1",  rrd => "g" };
      push @obis,{obis=>"56.7.0", fact=>"",      ga =>"9/0/3", dpt =>  9, rrd_name => "zaehler_leistung_L2",  rrd => "g" };
      push @obis,{obis=>"76.7.0", fact=>"",      ga =>"9/0/4", dpt =>  9, rrd_name => "zaehler_leistung_L3",  rrd => "g" };
      my @countermodes = (5,15,60,1440);    #Aufloesungen fuer COUNTER RRDs in Minuten (1440 = Tagesverbrauch)
      
      my $debug = "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
      
      #####################################################################
      # app starting here
      
      my ($x,$rawdata) = 0 ;
      my $count = 0;
      my $saw = 0;
      my $start = 0;
      
      if ($debug == 1) {print "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";}
      
      $rawdata =~ m/1B1B1B1B01010101(.*?)B1B1B1/;
      #$ra = $1;
      #print $sml."\n";
      
      if ($debug==1) {print "Step 3 - Analyze data \n";}
      
      # find OBIS values in raw data
      foreach my $obiscnt (@obis) {
      	if ( $debug == 1 ) {print "\n";}
      	my $obissearch = &obis2search($obiscnt->{obis});
      	
      	$rawdata =~ m/$obissearch(.*?)017707/;
      	my $obisdata = $1."01";
      	
      	print "found: ".$obisdata."\n";
      	
      	my $smlStatus  = "";
      	my $smlValTime = "";
      	my $smlUnit    = "";
      	my $smlScaler  = "";
      	my $smlValue   = "";
      	my $smlValueS  = "";
      	
      	## check status
      	if ( $debug == 1 ) {print "check sml status:          ";}
      	$smlStatus = &parseOBIS(\$obisdata);
      	
      	## check value time
      	if ( $debug == 1 ) {print "check sml value time:      ";}
      	$smlValTime = &parseOBIS(\$obisdata);
      	
      	## check unit
      	if ( $debug == 1 ) {print "check sml unit:            ";}
      	$smlUnit = &parseOBIS(\$obisdata);
      	
      	## check scaler
      	if ( $debug == 1 ) {print "check sml scaler:          ";}
      	$smlScaler = &parseOBIS(\$obisdata);
      	
      	## check value
      	if ( $debug == 1 ) {print "check sml value:           ";}
      	$smlValue = &parseOBIS(\$obisdata);
      	
      	## check value signature
      	if ( $debug == 1 ) {print "check sml value signature: ";}
      	$smlValueS = &parseOBIS(\$obisdata);
      
      	#print "done: ".$obisdata."\n";
      	#print  $smlStatus;
      	
      	
      	
      	# Calculate value
      	if ( $smlValue ne "" ) {
      		my $calcvalue  = ($smlValue * (10**$smlScaler));
      		my $smlUnitStr = &getSMLUnitStr($smlUnit);
      		if ( $debug == 1 ) {print "Calculated value: [".$calcvalue." ".$smlUnitStr."]\n";}
      		
      		my $dec_value = $calcvalue;
      		
      		# scale value
      		if ( looks_like_number($obiscnt->{fact}) ) {
      			$dec_value = ($calcvalue * $obiscnt->{fact});
      			if ( $debug == 1 ) {print "Final value: [".$dec_value."]\n";}
      		}
      		
      		# write rrd
      		if ($obiscnt->{rrd} eq "c") {
      			&rrd_counter ($obiscnt->{rrd_name},$dec_value)
      		}
      		
      		if ($obiscnt->{rrd} eq "g") {
      			&rrd_gauge ($obiscnt->{rrd_name},$dec_value)
      		}
      
      		# send value to bus
      		&knx_write ($obiscnt->{ga},$dec_value,$obiscnt->{dpt});
      		if ($debug == 1) {print "GA:".$obiscnt->{ga}." value:".$dec_value." DPT:".$obiscnt->{dpt}."\n";}
      	}	
      }
      
      $port->close() || warn "Serial port did not close proper!\n";
      undef $port;
      
      ## subs ##
      
      #####################################################################
      # convert OBIS to search parameter
      sub obis2search {
      
      	my ($obisid) = @_;
      	my $res = "77070100";
      	
      	if ($debug==1) { print "OBIS ID:     ".$obisid."\n";}
      		
      	foreach my $c ( split(/\./,$obisid) ) {
      		$res .= sprintf("%02X",$c);
      	}
      	
      	$res .= "FF";
      	
      	if ($debug==1) { print "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";}
      		$$r_obisdata =~ s/^..//;	# remove first 2 characters
      		return $res;
      	}
      	else {
      		#if ( $debug == 1 ) {print "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"; };
      			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; 
      					}
      		}
      		
      		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"; };
      			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"; }
      				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";}
      		
      		return $res;
      	}
      	
      	return $res;
      }
      
      #####################################################################
      # get SML unit string depending on value
      sub getSMLUnitStr {
      
      	my ($smlUnit) = @_;
      	my $res = "";
      	
      	switch ($smlUnit) {	
      		case 30 { $res = "Wh" }
      		case 27 { $res = "W"  }
      	}
      	
      	return $res;
      }
      
      #####################################################################
      
      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")};
          foreach (@countermodes)
          {
              my $obisname = $_[0];
              if ($debug==1){print $obisname." obisname \n";}
              my $value = $_[1];
              if ($debug==1){print $value." value \n";}
              my $rrdname = $obisname."_".$_."\.rrd";
              if ($debug==1){print ($rrdname,"\n")};
              my $rrdfile = $rrdpath."\/".$rrdname;
              unless (-e $rrdfile)
              {
                  RRDs::create ($rrdfile,"DS:value:COUNTER:".(($_*60)+600).":0:10000000000","RRA:AVERAGE:0.5:1:365","RRA:AVERAGE:0.5:7:300","-s ".($_*60));
              }
              my $countervalue = int($value*$_*60);
              RRDs::update("$rrdfile", "N:$countervalue");
          }
      }
      
      #####################################################################
      
      sub rrd_gauge
      {
          if ($debug==1){print ("GAUGE","\n")};
          my $obisname = $_[0];
          if ($debug==1){print $obisname." obisname \n";}
          my $value = $_[1];
          if ($debug==1){print $value." value \n";}
          my $rrdname = $obisname."\.rrd";
          if ($debug==1){print ($rrdname,"\n")};
          my $rrdfile = $rrdpath."\/".$rrdname;
          unless (-e $rrdfile)
          {
              RRDs::create ($rrdfile,"DS:value:GAUGE:900:0:10000000000","RRA:AVERAGE:0.5:1:2160","RRA:AVERAGE:0.5:5:2016","RRA:AVERAGE:0.5:15:2880","RRA:AVERAGE:0.5:60:8760");
          }
          RRDs::update("$rrdfile", "N:$value");
      }

      Kommentar


        Sieht doch sehr gut aus!

        1. Wozu socat?
        2. Wenn Du jetzt die Einheit (W/Wh) auswertest kann man auch auf gauge/counter in der config verzichten, siehe hier: https://sourceforge.net/p/openautoma...-meter.pl#l104
        Umgezogen? Ja! ... Fertig? Nein!
        Baustelle 2.0 !

        Kommentar


          Ich dachte ich hätte mal was gelesen, dass es nicht "so geschickt" ist, wenn PlugIns "warten".

          Kannst du mir das mit der rrd Geschichte noch was erklären. Ich probier nämlich gerade die Geschichte in der Cometvisu anzuzeigen, aber es wird kein Graph angezeigt.

          Kommentar


            Das ganze ist kein Plugin im eigentlichen Sinne sondern sollte per cron aufgerufen werden, funktioniert so also auch auf jedem anderen Linux-System und ist nicht WireGate abhängig, eben wegen der Timing Probleme.
            Man kann das natürlich so umbauen dass es als Plugin läuft, macht m.M.n. aber wenige Sinn.


            Zu den RRDs, versuche erstmal die Gauge-RRDs anzuzeigen, das sollte klappen. Aber dazu muss eben mindestens alle 5 Minuten das script laufen -> crontab.
            Die Counter RRDs zeigen erst was nach 2x$countermodes Minuten an. Also die Tagesverbräuche sieht man erst nach 48 Stunden, Stundenverbrauch erst nach 2 Stunden usw..
            Umgezogen? Ja! ... Fertig? Nein!
            Baustelle 2.0 !

            Kommentar


              Hallo,

              habe nun endlich mal das Jumi normalo Plugin für meinen Haushaltszähler nun endlich mal für den Wärmepumpen-Zähler mit 2 Tarifen aufgepimpt.

              Hilfestellungen gab mir Jumi damals schon.
              Wie kann ich prüfen, ob das Plugin läuft. Crontab habe ich analog eingerichtet. Ich sehe aber im Diagrammgenerator die neuen rrds nicht.
              Kann ich irgendwo in einem Log Laufzeitfehler oder dergleichen erkennen?

              Hier mal das Plugin:
              Code:
              #!/usr/bin/perl
              
              use warnings;
              use strict;
              use Device::SerialPort;
              use feature "switch";
              use EIBConnection;
              use RRDs;
              use Fcntl qw(:DEFAULT :flock);
              
              
              #0701000F0700FF = 7.0       FIXME !!! [0F]0700
              #070100010801FF = 1.8.1
              #070100010800FF = 1.8.1
              
              # Lock setzen damit Skript nur einmal startet
              
              
                open  *{0}
                      or die "What!? $0:$!";
                flock *{0}, LOCK_EX|LOCK_NB
                  or die "$0 is already running somewhere!\n";
              
              
              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/usbserial-FTFUDSF1";
              my $repeat = 20;   # Wiederholung alle x Sekunden
              my $rrdpath = "/var/www/rrd";
              my $debug = 1;
              
              my @obis;
              
              
              push @obis,{obis=>"1.8.0",  fact=>10000, ga =>"14/7/53", dpt => 14, rrd_name => "WP_Zaehler_Verbrauch", rrd => "c"   }; #rrd: c=counter ; g=gauge
              push @obis,{obis=>"7.0",    fact=>10,    ga =>"14/7/52", dpt => 9 , rrd_name => "WP_Zaehler_Leistung_Ges",  rrd => "g" };
              push @obis,{obis=>"1.8.1",    fact=>10,    ga =>"14/7/54", dpt => 14 , rrd_name => "WP_Zaehler_Leistung_Tarif1",  rrd => "c" };
              push @obis,{obis=>"1.8.2",    fact=>10,    ga =>"14/8/55", dpt => 14 , rrd_name => "WP_Zaehler_Leistung_Tarif2",  rrd => "c" };
              
              my @countermodes = (5,15,60,1440);    #Aufloesungen fuer COUNTER RRDs in Minuten (1440 = Tagesverbrauch)
              
              
              my $port = Device::SerialPort->new($device) || die $!;
              
              $port->databits(8) || die "failed setting databits";
              $port->baudrate(9600) || die "failed setting baudrate";
              $port->parity("none") || die "failed setting parity";
              $port->stopbits(1);
              $port->handshake("none");
              $port->dtr_active(0);
              $port->purge_all();
              $port->read_char_time(0);     # don't wait for each character
              $port->read_const_time(4000); # 1 second per unfulfilled "read" call
              $port->write_settings || die "cannot write settings";
              
              
              # Loop zum Datenempfang
              
              my $error=0;
              
              while ($error != 1)
              {
              
                 my ($x,$data) = 0 ;
                 my $sml = 0;
                 my $start = 0;
                 my $value = 0;
                 my $dec_value = 0;
                 my $count = 0;
                 my $saw = 0;
              
                 if ($debug == 1) {print "Step 1 - Daten holen \n";}
              
                 while ($start < 2)  # wait for second 1B1B1B1B01010101
                   {
                    ($count,$saw)=$port->read(512);   # will read 512 chars
                    if ($count == 512)       # wurden 512 chars gelesen ?
                      {
                       $x = uc(unpack('H*',$saw)); # nach hex wandeln
                       $data .= $x;
                       if ($data =~ /1B1B1B1B01010101/)  {$start ++};
                      } # if
                   }  # while
              
                 if ($debug==1) {print "Step 2 - Reg Exp 1 Datensatz zusammensetzen \n";}
                 $data =~ m/1B1B1B1B01010101(.*?)B1B1B1/;
                 $sml = $1;
              
                 print "Zaehler Haushalt: \n";
              
                 if ($debug==1) {print "Step 3 - Datensatz auswerten \n";}
              
                                  
              
                 foreach my $obiscnt (@obis)
                  {
                   # Umwandeln OBIS in HEx
              my $hc ="";
              foreach my $c (split(/\./,$obiscnt->{obis})) {
              $hc .= sprintf("%02X", $c);
              }
              my $obissearch = $hc;
                   # FF fuer Suche an  Hex-Wert anhaegne
                   $obissearch .="FF";
                   if ($debug==1) { print $obissearch."     Obis\n";}
                   $sml =~ m/$obissearch(.*?)0177/;
                   #$sml =~ m/$obiscnt->{obis}(.*?)0177/;
                   my $sml_val = $1;
              
                                      
                   if ($debug==1)  {  print $1." contains hex \n";}
              
                   #extract value
                   $sml_val =~ s/^.*52FF//;
                   $sml_val = substr($sml_val,2);
                   if ($debug == 1) {  print $sml_val." hex \n";}
                   $value = $sml_val;
              
                   $dec_value = sprintf("%d", hex($value));
                   $dec_value /= $obiscnt->{fact};
                   print $dec_value."<<<<---- Wert\n";
              
                   #  RRD-Graphen erstellen  - bei Bedarf wieder aktiv setzen
                   #if ($obis->{rrd} eq "c")
                   #   {
                   #   &rrd_counter ($obis->{rrd_name},$dec_value)
                   #   }
                   #if ($obis->{rrd} eq "g")
                   #   {
                   #   &rrd_gauge ($obis->{rrd_name},$dec_value)
                   #   }
              
                   &knx_write ($obiscnt->{ga},$dec_value,$obiscnt->{dpt});
                   if ($debug == 1) {print "GA:".$obiscnt->{ga}." Wert:".$dec_value." DPT:".$obiscnt->{dpt}."\n";}
              
                  } # foreach
              
                  sleep $repeat;
              
              } # while
              
              $port->close() || warn "Serial port did not close proper!\n";
              undef $port;
              
              ### SUBS ###
              
              
              sub rrd_counter
              {
                  if ($debug==1){print ("COUNTER","\n")};
                  foreach (@countermodes)
                  {
                      my $obisname = $_[0];
                      if ($debug==1){print $obisname." obisname \n";}
                      my $value = $_[1];
                      if ($debug==1){print $value." value \n";}
                      my $rrdname = $obisname."_".$_."\.rrd";
                      if ($debug==1){print ($rrdname,"\n")};
                      my $rrdfile = $rrdpath."\/".$rrdname;
                      unless (-e $rrdfile)
                      {
                          RRDs::create ($rrdfile,"DS:value:COUNTER:".(($_*60)+600).":0:10000000000","RRA:AVERAGE:0.5:1:365","RRA:AVERAGE:0.5:7:300","-s ".($_*60));
                      }
                      my $countervalue = int($value*$_*60);
                      RRDs::update("$rrdfile", "N:$countervalue");
                  }
              }
              
              sub rrd_gauge
              {
                  if ($debug==1){print ("GAUGE","\n")};
                  my $obisname = $_[0];
                  if ($debug==1){print $obisname." obisname \n";}
                  my $value = $_[1];
                  if ($debug==1){print $value." value \n";}
                  my $rrdname = $obisname."\.rrd";
                  if ($debug==1){print ($rrdname,"\n")};
                  my $rrdfile = $rrdpath."\/".$rrdname;
                  unless (-e $rrdfile)
                  {
                      RRDs::create ($rrdfile,"DS:value:GAUGE:900:0:10000000000","RRA:AVERAGE:0.5:1:2160","RRA:AVERAGE:0.5:5:2016","RRA:AVERAGE:0.5:15:2880","RRA:AVERAGE:0.5:60:8760");
                  }
                  RRDs::update("$rrdfile", "N:$value");
              }
              
              
              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;
              }
              Danke und GRüße,
              Lio

              Kommentar


                Zitat von lio123 Beitrag anzeigen
                Kann ich irgendwo in einem Log Laufzeitfehler oder dergleichen erkennen?
                Du könntest einfach mal das Skript direkt ausführen mit
                Code:
                perl /pfadzumskript/skriptname
                Dann müsstest du eine Ausgabe bekommen ob alles funktioniert hat oder ob Perl irgendwelche Fehler im Code gefunden hat.

                Kommentar


                  ach habe gerade gesehn, dass ich das Problem mit dem vorherigen skript auch mal im Post 331 hatte.

                  also, ich hab nun auch Kill all smlWP.pl gemacht, da er mir sagte, dass das Plugin noch sonstwo läuft.
                  Antwort war, dass da kein Prozess abgebrochen wurde.


                  Danach habe ich Cronjob deaktiviert und versucht nochmals über Kommandozeile das Plugin zu starten.

                  Danach sagt er mir, dass es noch woanderst läuft????

                  DAnke und Grüße,
                  Lio

                  Kommentar


                    Hallo
                    Ich auch immer wieder Probleme mit dem Zähler-Script hatte, das mehre liefen.
                    Jetzt starte ich mit Cron ein Bash-Schript, das überprüft ob das Script noch läuft, wenn ja wird es mit Kill beendet.
                    Code:
                       # sml_zaehler.pl starten
                       if [ "$(pidof sml_zaehler.pl)" ]
                          then
                          echo "sml_zaehler.pl laeuft noch"
                          pkill -9 sml_zaehler.pl
                          echo "sml_zaehler.pl gekillt"
                       fi
                         /var/www/myhouse/cron/sml_zaehler.pl
                    Gruß NetFritz
                    KNX & Wago 750-849 ,Wiregate u. Cometvisu, iPad 3G 64GB.
                    WP Alpha-Innotec WWC130HX (RS232-Moxa-LAN),Solaranlage für Brauchwasser und Heizung.
                    PV-Anlage = SMA Webbox2.0 , SunnyBoy 4000TL, Sharp 4kWP

                    Kommentar


                      Hallo Netfritz,

                      Du meinst, dass es ein Problem ist, dass beide Skripte laufen?
                      Aber warum eigentlich? Die sind doch ziemlich unabhängig voneinander?!?

                      Für mich seltsam ist, dass
                      1) bei Killall die Meldung kommt, dass kein Prozess beendet wurde.
                      2) die absolute Pfadangabe nicht gefunden wird:
                      Code:
                      root@wiregate534:~# killall smlwp.pl
                      smlwp.pl: Kein Prozess abgebrochen
                      root@wiregate534:~# perl /home/user smlwp.pl
                      root@wiregate534:~# perl /home/user
                      root@wiregate534:~# perl /home/user/smlwp.pl
                      Can't open perl script "/home/user/smlwp.pl": Datei oder Verzeichnis nicht gefunden
                      root@wiregate534:~# perl /home/user/smlwp.pl
                      Can't open perl script "/home/user/smlwp.pl": Datei oder Verzeichnis nicht gefunden
                      Ich habe nun mal alle Rechte an das Skript gegeben, was aber auch nichts aus macht und das laufende Skript ja auch mit eingeschränkten Rechten läuft.


                      Könnte es auch an Cron liegen? warum tauchen ausgerechnet ausschließlich bei diesen beiden jobs Pfeile auf?

                      Aber selbst wenn ich das funktionierende Skript bei Cron deaktiviere kann ich das neue Skript (smlWP.pl) nicht starten

                      Angehängte Dateien

                      Kommentar


                        Die meisten Linux-Dateisysteme sind case-sensitive
                        D.h. "smlwp.pl" ist nicht das Gleiche wie "smlWP.pl"

                        Im Screenshot heißt es smlWP.pl aber mit killall und manuellem Aufruf hatten Du smlwp.pl probiert (und die korrekte Fehlermeldung bekommen, dass es die Datei nicht gibt)

                        Wenn Du es richtig schreibst, passierst sicher auch etwas...

                        Kommentar


                          So, inzwischen zeichnen auch die rrds auf. Da war noch ein Fehler im Skript.
                          Jetzt habe ich allerdings ein Problem die Daten richtig darzustellen (weiß nicht, ob das hierhin gehört oder in die CometVisu Abteilung).

                          Im Anhang ist ein Screenshot von Verbrauch und Leistung der letzten 6h.

                          Der rote Graph (Leistung) sieht auch gut aus: 6:40 Haare gefönt passt

                          Der grüne Graph passt aber meiner Meinung nach nicht. Als Source nehme ich den counter mit 60 Minuten. Die zeitliche Zuordnung sieht aber komisch aus (1h versetzt) und die Werte sind dann doch etwas hoch.

                          Die Funktion ist aus dem original SML Skript von jumi.

                          Code:
                          sub rrd_counter
                          {
                              if ($debug==1){print ("COUNTER","\n")};
                              foreach (@countermodes)
                              {
                                  my $obisname = $_[0];
                                  if ($debug==1){print $obisname." obisname \n";}
                                  my $value = $_[1];
                                  if ($debug==1){print $value." value \n";}
                                  my $rrdname = $obisname."_".$_."_c\.rrd";
                                  if ($debug==1){print ($rrdname,"\n")};
                                  my $rrdfile = $rrdpath."\/".$rrdname;
                                  unless (-e $rrdfile)
                                  {
                                      RRDs::create ($rrdfile,"DS:value:COUNTER:".(($_*60)+600).":0:10000000000",
                          			"RRA:AVERAGE:0.5:1:366",	
                          			"RRA:AVERAGE:0.5:7:1308",
                          			"-s ".($_*60));				# step 
                                  }
                                  my $countervalue = int($value*$_*60);
                          		if ($debug==1){print $countervalue." countervalue \n";}
                                  RRDs::update("$rrdfile", "N:$countervalue");
                              }
                          }
                          Bei der Ausführung erhalte ich folgende Ausgabe (nicht passend zum Screenshot)

                          Code:
                          OBIS ID:     1.8.0
                          OBIS search: 77070100010800FF
                          found: 650000018201621E52FF590000000000723D5101
                          check sml status:          [386]
                          check sml value time:      [empty]
                          check sml unit:            [30]
                          check sml scaler:          [-1]
                          check sml value:           [7486801]
                          check sml value signature: [empty]
                          Unit config: [Wh][cg]
                          Final value: [748680.1 Wh]
                          COUNTER
                          zaehler_verbrauch obisname
                          748680.1 value
                          zaehler_verbrauch_5_c.rrd
                          224604030 countervalue
                          zaehler_verbrauch obisname
                          748680.1 value
                          zaehler_verbrauch_15_c.rrd
                          673812090 countervalue
                          zaehler_verbrauch obisname
                          748680.1 value
                          zaehler_verbrauch_60_c.rrd
                          2695248360 countervalue
                          zaehler_verbrauch obisname
                          748680.1 value
                          zaehler_verbrauch_1440_c.rrd
                          64685960640 countervalue
                          GAUGE
                          zaehler_verbrauch obisname
                          748680.1 value
                          zaehler_verbrauch_g.rrd
                          GA:9/0/0 value:748680.1 DPT:14
                          Hat irgendjemand ne Idee, woran das liegen kann?
                          Angehängte Dateien

                          Kommentar


                            Hallo
                            @lio123
                            Du meinst, dass es ein Problem ist, dass beide Skripte laufen?
                            Aber warum eigentlich? Die sind doch ziemlich unabhängig voneinander?!?
                            Nein
                            Ich meine das ein Script mehrmals läuft, das es nicht richtig beendet wurde.

                            Ein
                            "ps ax | grep .pl" zeigt Dir alle laufende Perl-Scripte an
                            dann
                            "kill -9 ProzessID" killt Dir garantiert das Script.

                            Gruß NetFritz
                            KNX & Wago 750-849 ,Wiregate u. Cometvisu, iPad 3G 64GB.
                            WP Alpha-Innotec WWC130HX (RS232-Moxa-LAN),Solaranlage für Brauchwasser und Heizung.
                            PV-Anlage = SMA Webbox2.0 , SunnyBoy 4000TL, Sharp 4kWP

                            Kommentar


                              Zitat von coolrunnings Beitrag anzeigen
                              Hat irgendjemand ne Idee, woran das liegen kann?
                              Ich beantworte mir die Frage einfach mal selber.
                              Vorher war der Verbrauch in kWh angegeben. Mein Zähler liefert aber Wh zurück. Also Faktor 1000 dazwischen. Deshalb passen die min/max Werte bei der rrd Definition nicht mehr.

                              Kommentar


                                Zitat von NetFritz Beitrag anzeigen
                                Hallo
                                Ich auch immer wieder Probleme mit dem Zähler-Script hatte, das mehre liefen.
                                Jetzt starte ich mit Cron ein Bash-Schript, das überprüft ob das Script noch läuft, wenn ja wird es mit Kill beendet.

                                [/CODE]Gruß NetFritz

                                Hallo,

                                ist das Batch Skript eine Datei, die wo liegt, oder hast Du das bei Cronjob unter "Eingabe an Befehl" geschrieben?

                                Danke und GRuß,
                                Lio

                                Kommentar

                                Lädt...
                                X