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

    Zitat von mosjka1 Beitrag anzeigen
    probiere mal

    Code:
    cat /dev/ttyUSB0 | od -tx1
    das liefert
    Code:
        0000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f8
    0000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0000040 00 00 00 ff 00 00 00 00 00 00 00 00 00 00 00 00
    0000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0000100 00 00 00 00 ff fc 00 00 00 00 00 00 00 00 00 00
    0000120 fc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0000160 00 00 ff 00 00 00 00 00 00 00 00 00 00 00 e0 00
    0000200 38 00 00 07 00 00 00 00 fc 00 00 00 f0 00 00 00
    0000220 00 00 00 00 00 00 ff 00 00 00 00 00 00 7e 00 00
    0000240 00 00 00 00 00 ff 1f 00 00 60 00 00 00 00 00 00
    0000260 00 00 00 00 00 ff 00 00 00 00 00 fc 00 00 00 00
    0000300 f8 00 00 e0 00 00 00 f8 00 00 ff 00 00 00 00 e0
    0000320 00 00 00 00 00 00 00 00 ff 00 00 00 00 00 00 00
    0000340 00 00 00 00 00 ff 00 00 00 e0 00 00 00 00 00 ff
    0000360 00 00 00 f8 00 fc 00 00 07 00 ff 00 00 00 00 f0
    0000400 00 3c 00 00 00 00 00 00 00 00 00 fe ff ff 00 00
    0000420 00 00 00 00 00 3f 00 00 00 00 00 00 00 00 00 00
    0000440 00 00 00 07 00 00 00 60 00 00 ff 00 00 00 00 00
    0000460 00 00 00 00 00 00 00 00 00 fc 00 00 00 00 00 00
    0000500 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0000520 00 00 f8 00 00 00 00 00 00 00 00 00 00 00 00 fc
    0000540 00 00 00 00 00 00 00 00 00 00 00 c0 00 00 ff 00
    0000560 00 00 00 00 00 fe 00 c0 00 00 00 00 00 00 00 00
    0000600 00 f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0000620 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0000640 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0000660 00 00 00 00 00 00 00 00 00 00 00 f8 00 00 00 00
    *
    0000720 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 00 00
    0000740 00 00 02 00 00 00 00 00 f0 00 00 00 00 00 00 00
    0000760 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0001000 00 f8 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0001020 00 00 00 fc 00 00 00 00 00 00 00 00 00 00 00 00
    0001040 00 00 00 00 00 1f 00 00 00 00 00 00 00 00 00 00
    0001060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0001100 00 00 00 fc 00 ff ff 00 00 00 f8 00 00 fe 00 60
    0001120 00 00 fe 00 ff 00 00 00 00 00 00 00 00 00 ff 00
    0001140 00 00 f0 00 00 00 f8 00 00 00 00 00 00 07 00 00
    0001160 00 ff 00 00 00 00 00 00 00 00 f0 00 00 fe 00 fe
    0001200 00 00 00 00 00 00 00 00 00 00 00 e0 00 00 00 00
    0001220 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 00
    0001240 20 00 00 00 00 00 00 00 00 00 00 60 00 00 00 00
    0001260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1f
    0001300 00 00 00 00 00 f8 00 c0 00 00 00 00 00 00 00 00
    0001320 00 00 c0 00 00 00 00 00 00 ff 00 00 00 ff 00 00
    0001340 00 00 00 00 c0 00 00 00 00 00 00 00 00 00 00 00
    0001360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0001400 00 00 f0 00 00 60 00 00 00 00 00 00 00 00 fe 00
    0001420 00 00 00 00 00 00 00 00 60 00 00 00 00 00 00 00
    0001440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0001460 00 00 10 00 00 00 00 00 e0 00 00 00 00 c0 e0 00
    ^C
    Danke

    Kommentar


      Und was sagt socat - /dev/ttyUSBehzEMHHaupt,raw,echo=0,b300,parenb=0,cs8,cst opb=1
      Umgezogen? Ja! ... Fertig? Nein!
      Baustelle 2.0 !

      Kommentar


        Zitat von JuMi2006 Beitrag anzeigen
        Und was sagt socat - /dev/ttyUSBehzEMHHaupt,raw,echo=0,b300,parenb=0,cs8,cst opb=1
        leider auch nicht richtig viel versprechend:
        Code:
        root@wiregate248:/home/user# socat - /dev/ttyUSBehzEMHHaupt,raw,echo=0,b300,parenb=0,cs8,cstopb=1 
        @W��#�i��@W��#�i��@W��#�i��@W��#�i��@W��#�i��@W��#�i��@_��#�i��@_��#�i��@_��#�i��@W^C
        root@wiregate248:/home/user# 
        root@wiregate248:/home/user# 
        root@wiregate248:/home/user# socat - /dev/ttyUSBehzEMHPhoto,raw,echo=0,b300,parenb=0,cs8,cstopb=1 
        BW����Ԥ�    �B_����Ԥ�    �B_����Ԥ�    �B_����Ԥ�    �B_����Ԥ�    �B_����Ԥ�    �^C

        Kommentar


          Nach dem Volkszähler Wiki sollten 9600 baud bei 8N1 stimmen:
          volkszaehler.org - wiki - EMH eHZ-H

          Kommentar


            Zitat von JuMi2006 Beitrag anzeigen
            Mal wieder ein Update.

            Ziemlich zusammengewürfelt aber funktioniert.

            Auf das senden auf den Bus hab ich vorerst mal verzichtet, wird wieder eingebaut. Socat hab ich noch nicht implementiert, das warte ich auch erst mal ab wie weit vzlogger auf dem WireGate unterstützt werden soll.

            Zur Konfiguration:

            device = serieller/usb-port
            conf4800 - ggf Pfad anpassen
            endsign = muss eigentlich nicht geändert werden
            rrdpath = Pfad zum RRD-Verzeichnis
            counterid = Gibt den ersten Teil der RRD-Datei-Namen an

            Die RRD werden nach dem Schema counterid_obiscode benannt, für OBIS 1.8.0 -> z.B. Zaehler_1-8-1.rrd .

            obis = auszulesender Obis-Wert und Länge des Datensatzes
            countermode = hier nochmal die Obiscodes eintragen die Zählerstände liefern, es werden Tagesverbräuche erstellt

            Das erste Auslesen sollte in der Konsole mit dem zweiten Script hier erfolgen, da wird dann einmal der Zähler ausgelesen und angezeigt welche Codes er liefert und wieviele Stellen der einzelne Obiscode hat. Das Komma wird mitgezählt.
            Das Script als *.pl ablegen und via crontab aufrufen lassen - Zyklus 5 Minuten.

            Code 1 - Hauptprogramm:
            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/ttyUSB-1-4.1";    #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.8.1"=>10);        #!!!COUNTER!!!
            
            my %countermode=("1.8.1"=>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(300)      || 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(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';
            
            
            $port->save($conf4800)     || warn "Can't save $conf4800: $!\n";
            
            ####START 300baud
            $port->baudrate(300)      || 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;
            Hier der Auslesecode fürs erste auslesen. Etwas Geduld, kann je nach Zähler bis zu 3 Minuten dauern.
            Am besten als init.pl speichern.

            Code:
            #!/usr/bin/perl
            use warnings;
            use strict;
            use Device::SerialPort;
            
            ### KONFIGURATION ###
            my $device = "/dev/ttyUSB-1-4.1";    #Port
            my $endsign = "!";                #Letztes Zeichen im Protokoll vom Zaehler
            ### ENDE KONFIGURATION ###
            
            ### Seriellen Port initialisieren
            
            ####START 300baud
            my $port = new Device::SerialPort($device) || die "can't open $device: $!";
            $port->baudrate(300)      || 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";
            
            ### 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
            tipped and coded by a linux dau on several devices ;-)

            Hallo,

            bin auch noch Linux DAU und will das jetzt auf LAN umstellen. Habe den YPORT Node von UDO aus dem Volkszähler-Wiki.
            Der sendet die Daten meiner 2 Zähler als RAW direkt ins LAN. Wie muss ich das Script umbasteln um nicht usb dort stehen zu haben sondern eben LAN (eth?)
            Wenn ich über putty auf die 192.168.178.xx:9780 zb. /!? bekomme ich schon mal die Zählerkennung.

            Wie mach ich nun weiter? Kann sich da jemand bereiterklären. (Ist auch der Landis/Gyr von Jumi

            Grüße Nico
            www.knx-Hausblog.de

            Kommentar


              Zitat von kleinklausi Beitrag anzeigen
              Nach dem Volkszähler Wiki sollten 9600 baud bei 8N1 stimmen:
              volkszaehler.org - wiki - EMH eHZ-H
              Es gibt mittlerweile von EMH Zähler die mit 9600bd, 7E1 arbeiten.

              Gruß
              Udo

              Kommentar


                Zitat von Udo1 Beitrag anzeigen
                Es gibt mittlerweile von EMH Zähler die mit 9600bd, 7E1 arbeiten.
                Danke, das werde ich ausprobieren. Komme ich aber erst die Tage dazu.

                Gruß Moritz

                Kommentar


                  Ich habe die letzten Tage ziemlich viele Ausreißer (entweder einfach nichts, oder 0) in meinen Graphen, das war ja z.B. hier ausführlich diskutiert worden. Gibt es da mittlerweile neue Erkenntnisse, bevor ich das selbst auseinandernehme?

                  Warum werden überhaupt mehrere verschiedene rrds für die unterschiedlichen Zeiten angelegt, die auch nur Average-Werte enthalten? Warum nicht ein gemeinsames, wie die update_rrd-Funktion der Wiregate-Plugins es erzeugt?

                  Edit: Das Parsen schlägt fehl, werde mich auch mal näher mit den Sourcen von Coolrunnings beschäftigen ...

                  Kommentar


                    Die Telegramme sind gelegentlich verstümmelt. Es fehlen zwischendrin an mehreren Stellen einige Bytes. Daher werden die Pattern nicht gefunden und es bleibt 0 als Wert übrig.
                    Die Frage ist, warum. Vielleicht gibt es Lesefehler, aber bei 9600, 8N1 reichen einzelne Bitfehler für dieses Fehlerbild nicht aus. Oder der Buffer der Seriellen wird nicht schnell genug ausgelesen und es gibt einen Overflow, aber das würde mich auch wundern.
                    Egal, damit muß man gelegentlich wohl rechnen, komisch nur, warum es neuerdings gehäuft auftritt. Der Lesekopf sitzt scheinbar gut.

                    Saubere Lösung wäre, die CRCs zu überprüfen und nur bei Übereinstimmung die Auswertung zu machen, ansonsten auf nächsten Rahmen warten. Mit rudimentären Perl-Kenntissen macht das bestimmt Spaß
                    Hier ein Link zur Decodierung und der Algorithmus zur CRC-Berechnung, den ich gegoogelt habe.
                    Mal weitersehen ...

                    Kommentar


                      Ich habe mir die Sache mal genauer angesehen. Die im Laufe der Zeit genannten Probleme wie ausbleibende Meßwerte, Ausreißer und mehrfach aktive Skripte lassen sich wahrscheinlich wie folgt erklären:

                      Es werden zweimal je 512 Bytes von der Seriellen gelesen und aneinandergehängt. Werden weniger als 512 Bytes gelesen, wird wiederholt (dadurch entsteht unter Umständen eine Lücke, was nicht sinnvoll ist und später schief gehen kann.) Ich habe nun beobachtet, daß es sein kann, daß minutenlang weniger als 512 Bytes gelesen werden, vermutlich wegen Timeouts.
                      Das Script kommt dann nicht aus der Schleife raus. Dann wird nach 5 Minuten die nächste Instanz gestartet, die nun gleichzeitig auf die Schnittstelle zugreift. Das verschärft die Timeout-Problematik und die gelesenen Telegramme sind nun unvollständig. Es werden keine Werte mehr im 5-Minutenraster generiert, was zu den Lücken in den rrds führt. Oder die Daten sind kaputt und es bleibt 0 als Wert übrig.
                      Irgendwann schafft es dann doch ein Skript, aus der Schleife zu kommen, und dann beenden sich zeitnah mehrere Skripte, aber unter Umständen in anderer Reihenfolge, was zu negativem Verbrauch führen kann, da ein höherer Wert zuerst gesendet wird.


                      Unten ein kleiner Auszug meiner Änderungen.
                      Ich habe read_char_time und read_const_time geändert, leider gibt es dazu keinerlei Dokumentation. Die Anzahl der gelesenen Bytes liegt aber nun fast immer richtig oder leicht drunter - viel besser als vorher.
                      Weiterhin habe ich die Schleife so geändert, daß einmal - in meinem Falle mehr als ausreichende - 800 Bytes gelesen werden (mindestens max-Rahmengröße*2 -1).
                      Ich suche nach dem Datenpaket und prüfe die Größe.
                      (Bei mir im Moment hart-kodiert, was die Sache nicht allgemeingültig macht. Besser wäre eine CRC-Prüfung, aber die ist aufwendig. Alternativ macht man nur einen groben Größenscheck. Die eigentlich gewünschten Daten sind so klein, daß man die auch in korrupten oder unvollständigen Rahmen finden wird. Also notfalls keine Prüfung.)
                      Falls die Daten ungültig sind, wiederhole ich nur eine begrenzte Anzahl, in jedem Falle muß man unter den 5 Minuten bleiben.

                      Code:
                      my $readsize = 800;       # must be at least 2x max-framesize
                      my $retry = 20;           # must be finished before next script call
                      
                      $port->read_char_time(10);    # wait for each character
                      $port->read_const_time(1000); # 1 second per unfulfilled "read" call
                      
                      # ...
                      
                      my $start = $retry;
                      while ($start > 1) {
                              $rawdata = "";
                      
                              ($count,$saw)=$port->read($readsize);  # will read n chars
                              if ($debug==1)     {print "  Read ".$count." Bytes\n";}    
                              if ($logging == 1) {print LOG "  Read ".$count." Bytes\n";}
                              # no check for count==readsize
                              $x = uc(unpack('H*',$saw)); # nach hex wandeln
                              $rawdata .= $x;
                              $rawdata =~ m/1B1B1B1B01010101(.*?)B1B1B1/;
                              # todo: check CRC of $1, optionally check for all obis
                              if (length($1) == 593) {      # hardcoded for EMH eHZ-H !!! 
                                     $start = 0;
                              } else {
                                     if ($debug==1) {print "Corrupted data, len ".length($1)."\n";}
                                     if ($logging==1) {print LOG "Corrupted data, len ".length($1)."\n";}
                                     $start -= 1;
                          }
                      }

                      Kommentar


                        Nunja das ist ein workaround, aber genau das hard codierte Zeug sollte ja vermieden werden. Da geht nun wieder das Byte-Zählen los und jeder jammert mit einem unterschiedlichem Zähler rum.

                        Ich halte das für keine so gute Idee. Mir fehlt sowohl Zähler und Zeit um das zu testen aber ich denke Du redest von der SML-Variante. Warum nicht einfach ein timeout in die Schleife einbauen ?

                        ungetestet:
                        Code:
                        my $timeout = 60;
                        my $starttime = time();
                        while ($start < 2) # wait for second 1B1B1B1B01010101 or timeout
                               my ($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 (($starttime + $timeout) < time()) {
                                    return;
                                    }
                        
                        }
                        Wie gesagt ist das ungetestet und ich hab das mit dem Forumeditor geschrieben. Weiterhin bin ich mir im Moment nicht sicher was die Serielle an der Stelle macht.

                        Mehr zum Thema read_char_time und read_const_time findest Du hier:
                        Device::SerialPort - search.cpan.org

                        Grüße
                        Umgezogen? Ja! ... Fertig? Nein!
                        Baustelle 2.0 !

                        Kommentar


                          Genau deswegen habe ich kein vollständiges Skript gepostet. Es ging mir um die Ursachenbeschreibung, die fehlte nämlich bis hierher. Sauberste Lösung ist immer noch, die CRCs auszuwerten.

                          Ha, jetzt sehe ich es auch: Read_Total = read_const_time + (read_char_time * bytes_to_read)

                          Hmm, wenn der Zähler nun mit langen Pausen zwischen den Telegrammen sendet, erklärt das allerdings einiges. Dann ist es eher verwunderlich, daß es mit bisherigem Skript bei diesem Zähler überhaupt so gut lief ...
                          Dann sollte man den Timeout deutlich aufdrehen (9 Sekunden reichen bei mir ja noch nicht ganz) und nach wenigen Runden abbrechen, um unter den 5 Minuten zu bleiben.

                          Zu Deinem Beispiel: Timeout kann man sicher so machen, aber das 2x512-Byte-Lesen macht potentiell die beschriebenen Probleme
                          (Mit gewisser Wahrscheinlichkeit hat man keinen vollständigen Rahmen, aber die Chunks sind trotzdem drin, weswegen es dann auch wieder egal ist ... zeigt nur, daß es nicht ganz sauber ist.)

                          Kommentar


                            Das Grundproblem ist dass sich die Hersteller nicht an einen Standard halten. Mal kommen die Daten alle 2 Sekunden, mal alle 10 Sekunden. Noch lustiger wird es bei DLMS/IEC62056, da kommen die Daten teilweise ohne Aufforderung, nach Aufforderung oder nach Aufforderung+ACK.

                            Gut das jetzt die Ursache bekannt ist für Deine Fehler. Bytes zählen würde ich aber dennoch vermeiden, den Job sollten die Regex übernehmen.

                            Grüße
                            Umgezogen? Ja! ... Fertig? Nein!
                            Baustelle 2.0 !

                            Kommentar


                              Pafal 20ec3gr

                              Hallo

                              Wir haben bei uns 3 Stk Pafal 20ec3gr (Haus, Studio, Wärmepumpe) in unserem Zählerschrank. Ich habe mir bei Udo (Volkszähler.org) einen USB-IR-Lesekopf bestellt. Diesen will ich an mein Wiregate anschließen und die (etwas dürftigen) Infos aus dem Zähler saugen.

                              Hier wurde ein Script beschrieben, welches als crontab läuft. Wo kann ich auf dem Wiregate einen crontab definieren?

                              Im
                              Wiki von Volkszähler.org gibt es ein Script für den Pafal 20ec3gr. Kann ich das ohne weiteres auf dem Wiregate nutzen?

                              Gleich vorweg eine Frage. Was ich bisher recherchiert habe, gibt der Zähler nur den aktuellen Zählerstand zurück. Kann ich daraus dann den aktuellen Verbrauch berechnen?
                              ---
                              Martin

                              Kommentar


                                Ich habe jetzt einen Lesekopf bekommen. Ans WG angeschlossen, kann ich diesen mittels dev/ttyUSB0 ansprechen, bzw. Infos über den Lesekopf auslesen. Daten vom Zähler bekomme ich allerdings nicht.

                                Am Raspberry Pi komme ich genau so weit wie am WG. Infos über den Kopf bekomme ich, aber Daten vom Zähler nicht.

                                Kann ich irgendwie überprüfen ob der Lesekopf aktiv ist? Muss ich die S0 Schnittstelle erst aktivieren lassen?
                                ---
                                Martin

                                Kommentar

                                Lädt...
                                X