ich habe jetzt mal Dein Script aus deinem letzten Post (Link) genommen und angepasst
Code:
#!/usr/bin/perl # Zaehlerabfrage fuer Zaehler nach Protokoll IEC 62056-21 / OBIS # Ein Anfrage-Telegramm ist mit 300 Baud, 7 Bit, 1 Stoppbit # und gerader Paritaet zu senden. Das ist der Initialmodus von Geraeten, # die das Protokoll IEC 62056-21 implementieren. # Ein Wechsel der Geschwindigkeit ist möglich, in diesem Script aber noch nicht umgesetzt. # !!! Wiederholung nur alle 3 Minuten da der Zaehler nach Ende des Scriptes weiter sendet !!! # Basis des Scripts von volkszaehler.org / Autor: Andreas Schulze & Bugfix: Eric Schanze # DPT9 sub: makki / www.knx-user-forum.de # In dieser Version keine Anbindung an den KNX-Bus # Erweiterung um RRD,KNX-Anbindung und gezielte Wertsuche auf Wiregate: # JuMi2006 / www.knx-user-forum.de # Version: 0.1.3 # Datum: 23.04.2012 use warnings; use strict; use Device::SerialPort; use RRDs; ### KONFIGURATION ### my $device = "/dev/ttyS0"; #Port my $conf4800 = "/tmp/conf4800"; #temporäre Konfigurationsdatei für Baudwechsel my $endsign = "!"; #Letztes Zeichen im Protokoll vom Zaehler my $rrdpath = "/var/www/rrd"; #Pfad für RRDs my $counterid = "Zaehler_HZ"; #Grundname für RRDs my %obis=( "16.7"=>6, #Obis-Zahl => Anzahl der Stellen z.B.: 6 = 123.45 "32.7"=>3, "52.7"=>3, "31.7"=>6, "51.7"=>6, "71.7"=>6, "72.7"=>3, "1-0:1.8.1*255"=>10); #!!!COUNTER!!! my %countermode=("1-0:1.8.1*255"=>24); #Obiscode für Zaehlerstaende #RRD gibt Verbrauch pro Tag aus (beta) ### ENDE KONFIGURATION ### ### Seriellen Port initialisieren ####4800baud my $port = new Device::SerialPort($device) || die "can't open $device: $!"; $port->baudrate(9600) || die 'fail setting baudrate'; $port->databits(7) || die 'fail setting databits'; $port->stopbits(1) || die 'fail setting stopbits'; $port->parity("even") || die 'fail setting parity'; $port->rts_active(1); $port->dtr_active(1); $port->read_char_time(1000); # 0.5 seconds for each character $port->read_const_time(5000); # 1 second per unfulfilled "read" call $port->write_settings || die 'fail write settings'; $port->save($conf4800) || warn "Can't save $conf4800: $!\n"; ####START 300baud $port->baudrate() || die 'fail setting baudrate'; $port->databits(7) || die 'fail setting databits'; $port->stopbits(1) || die 'fail setting stopbits'; $port->parity("even") || die 'fail setting parity'; $port->dtr_active(1); $port->rts_active(1); $port->read_char_time(500); # 0.5 seconds for each character $port->read_const_time(1000); # 1 second per unfulfilled "read" call $port->write_settings || die 'fail write settings'; ### Anforderungstelegramm senden my $data="2f3f210d0a"; #Anfrage als HEX "/?!<CR><LF>" my $request = pack('H*',$data); my $num_out = $port->write($request); print $request; die "write failed\n" unless ($num_out); die "write inclomplete\n" unless ($num_out == length($request)); print "$num_out Bytes written\n"; ### Warte auf Zaehlerkennung select(undef, undef, undef, 1.5); # 1.5 Sekunden warten ### Telegramm mit ACK und neuer Geschwindigkeit senden my $data2="063030300d0a"; #ACK und neue Geschwindigkeit in HEX "<ACK>040<CR><LF>" my $baudwechsel = pack('H*',$data2); # 000 = 300baud, 040 = 4800baud my $num_out2 = $port->write($baudwechsel); print $baudwechsel; die "write failed\n" unless ($num_out2); die "write inclomplete\n" unless ($num_out2 == length($baudwechsel)); print "$num_out2 Bytes written\n"; ### Port mit neuer Geschwindigkeit intialisieren $port->restart($conf4800) || warn "Can't restart $conf4800: $!\n"; ; #$port->baudrate(300); #$port->write_settings; ### AUSLESEN my $STALL_DEFAULT=5; # how many seconds to wait for new input my $timeout=$STALL_DEFAULT; my $chars=0; my $buffer=""; while ($timeout>0) { my ($count,$saw)=$port->read(25); # Liest 25 Zeichen je Durchlauf aus if ($count > 0) { $chars+=$count; $buffer.=$saw; #print ($buffer,"\n"); # Ausgabe der eingelesenen Daten ### FILTER FOR END if ($buffer =~ /\Q$endsign\E/) # \Q \E entwertet alle Sonderzeichen dazwischen { $port->close || die "can't close $device: $!"; # Port schlieen last; # Schleife verlassen } ### ENDE FILTER FOR END } else { $timeout--; } } if ($timeout<=0) { $port->close || die "can't close $device: $!"; print "Waited $STALL_DEFAULT seconds and never saw what I wanted\n"; } print $buffer; #Nur zur Kontrolle ### FILTER FOR DATA while (my($key, $value) = each %obis) { my $obiskey = $key."("; if ($buffer =~ /\Q$obiskey\E/) # \Q \E entwertet alle Sonderzeichen dazwischen { my $pos=index($buffer,$obiskey); # Anfangsposition des OBIS-Key finden print ("Obiskey: $obiskey","\n"); # Kontrolldruck print ("Position: $pos","\n"); # Kontrolldruck print (length($obiskey),"\n"); # Kontrolldruck my $obisvalue=substr($buffer,($pos+length($key)+1),$obis{$key}); # Wert extrahieren print ($key,": ",$obisvalue,"\n"); # Kontrolldruck ### RRD-Erstellen my $obisname = "$key"; $obisname =~ tr/./-/; my $rrdname = $counterid."_".$obisname."\.rrd"; print ($rrdname,"\n"); my $rrdfile = $rrdpath."\/".$rrdname; ### RRD check COUNTER/GAUGE if (exists $countermode{$key}) { print ("COUNTER","\n"); ### COUNTER schreiben unless (-e $rrdfile) { RRDs::create ($rrdfile,"DS:value:COUNTER:86500:0:10000000000","RRA:AVERAGE:0.5:1:365","RRA:AVERAGE:0.5:7:300","-s 86400"); } ### RRD-Füllen RRDs::update("$rrdfile", "N:$obisvalue*=86400"); } else { print ("GAUGE","\n"); ###GAUGE schreiben 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"); } ### RRD-Füllen RRDs::update("$rrdfile", "N:$obisvalue"); } } } ### ENDE FILTER FOR DATA ### Log der Zaehlerausgabe #my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time); #my $timestamp = printf "%4d-%02d-%02d %02d:%02d:%02d\n",$year+1900,$mon+1,$mday,$hour,$min,$sec; #open(LOG,'>>',$file) || die "Fehler $!"; #print LOG ("\n",$year+1900,"-",$mon+1,"-",$mday," ",$hour,":",$min,":",$sec," \; ",$value); #close LOG;
Obiskey: 1-0:1.8.1*255(
Position: 83
14
1-0:1.8.1*255: 000617.072
Zaehler_HZ_1-0:1-8-1*255.rrd
COUNTER
Sieht doch nicht so schlecht aus. Eine Einbindung von GAs zum Senden der Werte hat das ganze ja noch nicht. Ich würde jetzt versuchen die channel Einträge aus dem aktuellen Script
z.B.
Code:
my @channels; #Obis-Zahl => Gruppenadresse push @channels, {name => "16.7", ga =>"6/3/1", dpt => 9 }; #akt. Leistung push @channels, {name => "32.7", ga =>"6/3/11", dpt => 9 }; #Spannung L1 push @channels, {name => "52.7", ga =>"6/3/21", dpt => 9 }; #Spannung L2 push @channels, {name => "72.7", ga =>"6/3/31", dpt => 9 }; #Spannung L3 push @channels, {name => "31.7", ga =>"6/3/10", dpt => 9 }; #Stromstaerke L1 push @channels, {name => "51.7", ga =>"6/3/20", dpt => 9 }; #Stromstaerke L2 push @channels, {name => "71.7", ga =>"6/3/30", dpt => 9 }; #Stromstarke L3 push @channels, {name => "1-0:1.8.1", ga =>"6/3/0", dpt => 9 }; #Zaehlerstand gesamt
Grüße,
Mike
Einen Kommentar schreiben: