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 mikeeyy Beitrag anzeigen
    Sieht doch schon besser aus...
    ...und erklärt, warum Hyperterminal gereicht hat :-)
    Wenn keine Umschaltung der Geschwindigkeit nötig ist und die Werte als Klartext kommen, funktioniert sogar diese Uraltsoftware :-)
    Gruß, Carsten

    Kommentar


      Ok.. jetzt habe ich im eigentlichen Zähler Script den Eintrag angepasst an

      my $baudrate = 9600;

      da passiert jetzt aber auch nicht viel mehr. output hier:

      root@wiregate723:/home/user# perl acm.pl
      substr outside of string at acm.pl line 70.
      root@wiregate723:/home/user

      unter /var/www/rrd gibt es auch keine weiteren RRDs

      EDIT:

      den Eintrag %channels habe ich angepasst

      "1-0:1.8.0"=>"12/1/0" #Zaehlerstand gesamt

      Kommentar


        Poste mal das ganze script.
        Besser vielleicht gleich eine Revision vorher aus dem SVN nehmen. Vielleicht reicht es dort überall die 300 baud gegen 9600 baud auszutauschen. Das sollte nur in 2 Zeilen der Fall sein die die socat Abfrage machen.

        Gruß
        Umgezogen? Ja! ... Fertig? Nein!
        Baustelle 2.0 !

        Kommentar


          Zitat von JuMi2006 Beitrag anzeigen
          Herrlich ...ja wozu gibt es denn Normen bitteschön? Bei sowas könnt ich ko**** ... genau wie meine blöde ..
          Jaja, so ist das leider.. Auch wenn ich gerne über KNX mosere; da klopft jemand auf die Finger und guckt das auch was zusammenpasst

          Mein Zähler hat nur klich-klack (evtl. einfacher?) aber wenn was zum packen gibt-> insistieren

          Makki
          EIB/KNX & WireGate & HS3, Russound,mpd,vdr,DM8000, DALI, DMX
          -> Bitte KEINE PNs!

          Kommentar


            Hier meine aktuell genutzte Version. Dabei handelt es sich um die SVN Version, welche entsprechend den vorherigen Posts angepasst wurde


            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 umgesetzt.
            # Basis des Scripts von volkszaehler.org / Autor: Andreas Schulze & Bugfix: Eric Schanze
            # DPT9 sub: makki / [URL="http://www.knx-user-forum.de"]www.knx-user-forum.de[/URL]
            # Baudwechsel: panzaeron / [URL="http://www.knx-user-forum.de"]www.knx-user-forum.de[/URL]
            # Erweiterung um RRD,KNX-Anbindung und gezielte Wertsuche auf Wiregate: 
            # JuMi2006 / [URL="http://www.knx-user-forum.de"]www.knx-user-forum.de[/URL]
            # Version: 0.1.6
            # Datum: 16.08.2012
            
            use warnings;
            use strict;
            use RRDs;
            
            ### KONFIGURATION ###
            
            my $device = "/dev/ttyS0";    #Port
            my $rrdpath = "/var/www/rrd";        #Pfad fuer RRDs
            my $counterid = "test";            #Grundname fuer RRDs
            my $baudrate = 9600;            #Baudrate fuer Zaehlerauslesung "auto" oder 300,600,etc
            my %channels = (            #Obis-Zahl => Gruppenadresse
                    "16.7"=>"12/1/1",    #akt. Leistung
                    "32.7"=>"12/1/11",    #Spannung L1
                    "52.7"=>"12/1/21",    #Spannung L2
                    "31.7"=>"12/1/10",    #Stromstaerke L1
                    "51.7"=>"12/1/20",    #Stromstaerke L2
                    "71.7"=>"12/1/30",    #Stromstarke L3
                    "72.7"=>"12/1/32",    #Spannung L3
                    "1-0:1.8.0"=>"12/1/0"    #Zaehlerstand gesamt
                            );
            my @countermodes = (5,15,60,1440);    #Aufloesungen fuer COUNTER RRDs in Minuten (1440 = Tagesverbrauch)
            my $debug = 0;
            
            ### ENDE KONFIGURATION ###
            #Je nach Geschwindigkeit andere Befehle an Zaehler senden
            
            my %speedrate = (            
                    "300"=>"'\x06\x30\x30\x30\x0d\x0a'",
                    "600"=>"'\x06\x30\x31\x30\x0d\x0a'",
                    "1200"=>"'\x06\x30\x32\x30\x0d\x0a'",
                    "2400"=>"'\x06\x30\x33\x30\x0d\x0a'",
                    "4800"=>"'\x06\x30\x34\x30\x0d\x0a'",
                    "9600"=>"'\x06\x30\x35\x30\x0d\x0a'"
                    );
            my %speedrate_auto = (            
                    "0"=>"'\x06\x30\x30\x30\x0d\x0a'",
                    "1"=>"'\x06\x30\x31\x30\x0d\x0a'",
                    "2"=>"'\x06\x30\x32\x30\x0d\x0a'",
                    "3"=>"'\x06\x30\x33\x30\x0d\x0a'",
                    "4"=>"'\x06\x30\x34\x30\x0d\x0a'",
                    "5"=>"'\x06\x30\x35\x30\x0d\x0a'"
                    );
            my %baud = (            
                    "0"=>"300",
                    "1"=>"600",
                    "2"=>"1200",
                    "3"=>"2400",
                    "4"=>"4800",
                    "5"=>"9600"
                    );
            
            ### DATEN EMPFANGEN ###
            
            ### Anfrage Senden ###
            my $id = qx(echo '\x2f\x3f\x21\x0d\x0a' | socat -T1 - $device,raw,echo=0,b300,parenb=1,parodd=0,cs7,cstopb=0);
            my $speedcode =  substr($id,4,1);
            my $ack = $speedrate{$baudrate};
            
            ### Zählerkennung auswerten - Geschwindigkeit ermitteln ###
            if ($baudrate eq "auto")
            {
            $ack = $speedrate_auto{$speedcode};
            $baudrate = $baud{$speedcode};
            }
            else
            {
            $ack = $speedrate{$baudrate};
            }
            
            if ($debug==1){print ($id,"\n")};
            if ($debug==1){print ($baudrate,"\n")};
            
            select(undef, undef, undef, 1); 
            ### Abfrage starten ###
            my @buffer = qx(echo $ack | socat -t1 - $device,raw,echo=0,b300,parenb=1,parodd=0,cs7,cstopb=0; socat -T 1 - $device,raw,echo=0,b$baudrate,parenb=1,parodd=0,cs7,cstopb=0 );
            if ($debug==1){print (@buffer,"\n")};
            ### AUSWERTUNG ###
            foreach (@buffer)
            {
                foreach my $obis(%channels)
                {
                my $obiskey = $obis."\(";
                if ($_ =~ /\Q$obiskey\E/)
                {
                $_  =~ m/[^(]+\(([^*]+)\*([^)]+)/;
                my $value = $1;
                my $unit = $2;
                my $ga = $channels{$obis};
                if ($debug==1){print ($obis,"\n")};
                if ($debug==1){print ($value,"\n")};
                if ($debug==1){print ($unit,"\n")};
                if ($debug==1){print ($ga,"\n")};
                if ($unit =~ /\Qh\E/)
                {
                &rrd_counter ($obis,$value)
                }
                else
                {
                &rrd_gauge ($obis,$value)
                }
                &knx_write ($ga,$value);
                }
                }
            }
            
            ### SUBS ###
            
            sub rrd_counter
            {
            if ($debug==1){print ("COUNTER","\n")};
            foreach (@countermodes)
            {
            my $obisname = $_[0];
            my $value = $_[1];
            $obisname =~ tr/./-/;
            my $rrdname = $counterid."_".$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];
            my $value = $_[1];
            $obisname =~ tr/./-/;
            my $rrdname = $counterid."_".$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
            {
            ### Wert in DPT9 umwandeln und in Konsole ausgeben
            my @hexdec = encode_dpt9($_[1]);
            my $hexval = sprintf("%x", $hexdec[0]) . " " . sprintf("%x", $hexdec[1]);
            #print ($hexval,"\n");
            system("groupwrite ip:localhost $_[0] $hexval");
            }
            
            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;
            }



            Grüße,
            Mike

            Kommentar


              Hallo Mike,

              sei so Gut und pack das in Code-Tags (das Symbol mit der Raute) das liest sich einfach besser.
              Ein Problem ist mir gestern Abend noch aufgefallen, Dein Zähler fragt mehrere Werte ab oder? Du hast z.B. die 1.8.0 zweimal mit unterschiedlichen Ständen, das wird hier ohne Codeänderung sicherlich zu Problemen führen.

              Wie zuverlässig arbeitet denn das init.pl?

              Als Code probiere mal das hier:
              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 umgesetzt.
              # Basis des Scripts von volkszaehler.org / Autor: Andreas Schulze & Bugfix: Eric Schanze
              # DPT9 sub: makki / www.knx-user-forum.de
              # Baudwechsel: panzaeron / www.knx-user-forum.de
              # Erweiterung um RRD,KNX-Anbindung und gezielte Wertsuche auf Wiregate: 
              # JuMi2006 / www.knx-user-forum.de
              # Version: 0.1.6
              # Datum: 16.08.2012
              
              use warnings;
              use strict;
              use RRDs;
              
              ### KONFIGURATION ###
              
              my $device = "/dev/ttyS0"; #Port
              my $rrdpath = "/var/www/rrd"; #Pfad fuer RRDs
              my $counterid = "test"; #Grundname fuer RRDs
              my $baudrate = 9600; #Baudrate fuer Zaehlerauslesung "auto" oder 300,600,etc
              my %channels = ( #Obis-Zahl => Gruppenadresse
              "15.7.0"=>"12/1/1", #akt. Leistung
              "17.0.0"=>"12/1/11", #akt. Stromstärke ?
              "1.8.0"=>"12/1/0" #Zaehlerstand gesamt
              );
              my @countermodes = (5,15,60,1440); #Aufloesungen fuer COUNTER RRDs in Minuten (1440 = Tagesverbrauch)
              my $debug = 0;
              
              ### ENDE KONFIGURATION ###
              #Je nach Geschwindigkeit andere Befehle an Zaehler senden
              
              my %speedrate = ( 
              "300"=>"'\x06\x30\x30\x30\x0d\x0a'",
              "600"=>"'\x06\x30\x31\x30\x0d\x0a'",
              "1200"=>"'\x06\x30\x32\x30\x0d\x0a'",
              "2400"=>"'\x06\x30\x33\x30\x0d\x0a'",
              "4800"=>"'\x06\x30\x34\x30\x0d\x0a'",
              "9600"=>"'\x06\x30\x35\x30\x0d\x0a'"
              );
              my %speedrate_auto = ( 
              "0"=>"'\x06\x30\x30\x30\x0d\x0a'",
              "1"=>"'\x06\x30\x31\x30\x0d\x0a'",
              "2"=>"'\x06\x30\x32\x30\x0d\x0a'",
              "3"=>"'\x06\x30\x33\x30\x0d\x0a'",
              "4"=>"'\x06\x30\x34\x30\x0d\x0a'",
              "5"=>"'\x06\x30\x35\x30\x0d\x0a'"
              );
              my %baud = ( 
              "0"=>"300",
              "1"=>"600",
              "2"=>"1200",
              "3"=>"2400",
              "4"=>"4800",
              "5"=>"9600"
              );
              
              ### DATEN EMPFANGEN ###
              
              ### Anfrage Senden ###
              my $id = qx(echo '\x2f\x3f\x21\x0d\x0a' | socat -T1 - $device,raw,echo=0,b9600,parenb=1,parodd=0,cs7,csto pb=0);
              my $speedcode = substr($id,4,1);
              my $ack = $speedrate{$baudrate};
              
              ### Zählerkennung auswerten - Geschwindigkeit ermitteln ###
              if ($baudrate eq "auto")
              {
              $ack = $speedrate_auto{$speedcode};
              $baudrate = $baud{$speedcode};
              }
              else
              {
              $ack = $speedrate{$baudrate};
              }
              
              if ($debug==1){print ($id,"\n")};
              if ($debug==1){print ($baudrate,"\n")};
              
              select(undef, undef, undef, 1); 
              ### Abfrage starten ###
              my @buffer = qx(echo $ack | socat -t1 - $device,raw,echo=0,b9600,parenb=1,parodd=0,cs7,csto pb=0; socat -T 1 - $device,raw,echo=0,b$baudrate,parenb=1,parodd=0,cs 7,cstopb=0 );
              if ($debug==1){print (@buffer,"\n")};
              ### AUSWERTUNG ###
              foreach (@buffer)
              {
              foreach my $obis(%channels)
              {
              my $obiskey = $obis."\(";
              if ($_ =~ /\Q$obiskey\E/)
              {
              $_ =~ m/[^(]+\(([^*]+)\*([^)]+)/;
              my $value = $1;
              my $unit = $2;
              my $ga = $channels{$obis};
              if ($debug==1){print ($obis,"\n")};
              if ($debug==1){print ($value,"\n")};
              if ($debug==1){print ($unit,"\n")};
              if ($debug==1){print ($ga,"\n")};
              if ($unit =~ /\Qh\E/)
              {
              &rrd_counter ($obis,$value)
              }
              else
              {
              &rrd_gauge ($obis,$value)
              }
              &knx_write ($ga,$value);
              }
              }
              }
              
              ### SUBS ###
              
              sub rrd_counter
              {
              if ($debug==1){print ("COUNTER","\n")};
              foreach (@countermodes)
              {
              my $obisname = $_[0];
              my $value = $_[1];
              $obisname =~ tr/./-/;
              my $rrdname = $counterid."_".$obisname."_".$_."\.rrd";
              if ($debug==1){print ($rrdname,"\n")};
              my $rrdfile = $rrdpath."\/".$rrdname;
              unless (-e $rrdfile)
              {
              RRDs::create ($rrdfile,"DS:value:COUNTER:".(($_*60)+600).":0:10 000000000","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];
              my $value = $_[1];
              $obisname =~ tr/./-/;
              my $rrdname = $counterid."_".$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
              {
              ### Wert in DPT9 umwandeln und in Konsole ausgeben
              my @hexdec = encode_dpt9($_[1]);
              my $hexval = sprintf("%x", $hexdec[0]) . " " . sprintf("%x", $hexdec[1]);
              #print ($hexval,"\n");
              system("groupwrite ip:localhost $_[0] $hexval");
              }
              
              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;
              }
              Umgezogen? Ja! ... Fertig? Nein!
              Baustelle 2.0 !

              Kommentar


                Hallo JuMi,

                in Deinem Code haben sich ein paar Fehler (Leerzeichen) bei den socat Zeilen eingeschlichen. Habe ich bereinigt. Code sieht jetzt so aus:

                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 umgesetzt.
                # Basis des Scripts von volkszaehler.org / Autor: Andreas Schulze & Bugfix: Eric Schanze
                # DPT9 sub: makki / www.knx-user-forum.de
                # Baudwechsel: panzaeron / www.knx-user-forum.de
                # Erweiterung um RRD,KNX-Anbindung und gezielte Wertsuche auf Wiregate: 
                # JuMi2006 / www.knx-user-forum.de
                # Version: 0.1.6
                # Datum: 16.08.2012
                
                use warnings;
                use strict;
                use RRDs;
                
                ### KONFIGURATION ###
                
                my $device = "/dev/ttyS0"; #Port
                my $rrdpath = "/var/www/rrd"; #Pfad fuer RRDs
                my $counterid = "test"; #Grundname fuer RRDs
                my $baudrate = 9600; #Baudrate fuer Zaehlerauslesung "auto" oder 300,600,etc
                my %channels = ( #Obis-Zahl => Gruppenadresse
                "15.7.0"=>"12/1/1", #akt. Leistung
                "17.0.0"=>"12/1/11", #akt. Stromstärke ?
                "1.8.0"=>"12/1/0" #Zaehlerstand gesamt
                );
                my @countermodes = (5,15,60,1440); #Aufloesungen fuer COUNTER RRDs in Minuten (1440 = Tagesverbrauch)
                my $debug = 0;
                
                ### ENDE KONFIGURATION ###
                #Je nach Geschwindigkeit andere Befehle an Zaehler senden
                
                my %speedrate = ( 
                "300"=>"'\x06\x30\x30\x30\x0d\x0a'",
                "600"=>"'\x06\x30\x31\x30\x0d\x0a'",
                "1200"=>"'\x06\x30\x32\x30\x0d\x0a'",
                "2400"=>"'\x06\x30\x33\x30\x0d\x0a'",
                "4800"=>"'\x06\x30\x34\x30\x0d\x0a'",
                "9600"=>"'\x06\x30\x35\x30\x0d\x0a'"
                );
                my %speedrate_auto = ( 
                "0"=>"'\x06\x30\x30\x30\x0d\x0a'",
                "1"=>"'\x06\x30\x31\x30\x0d\x0a'",
                "2"=>"'\x06\x30\x32\x30\x0d\x0a'",
                "3"=>"'\x06\x30\x33\x30\x0d\x0a'",
                "4"=>"'\x06\x30\x34\x30\x0d\x0a'",
                "5"=>"'\x06\x30\x35\x30\x0d\x0a'"
                );
                my %baud = ( 
                "0"=>"300",
                "1"=>"600",
                "2"=>"1200",
                "3"=>"2400",
                "4"=>"4800",
                "5"=>"9600"
                );
                
                ### DATEN EMPFANGEN ###
                
                ### Anfrage Senden ###
                my $id = qx(echo '\x2f\x3f\x21\x0d\x0a' | socat -T1 - $device,raw,echo=0,b9600,parenb=1,parodd=0,cs7,cstopb=0);
                my $speedcode = substr($id,4,1);
                my $ack = $speedrate{$baudrate};
                
                ### Zählerkennung auswerten - Geschwindigkeit ermitteln ###
                if ($baudrate eq "auto")
                {
                $ack = $speedrate_auto{$speedcode};
                $baudrate = $baud{$speedcode};
                }
                else
                {
                $ack = $speedrate{$baudrate};
                }
                
                if ($debug==1){print ($id,"\n")};
                if ($debug==1){print ($baudrate,"\n")};
                
                select(undef, undef, undef, 1); 
                ### Abfrage starten ###
                my @buffer = qx(echo $ack | socat -t1 - $device,raw,echo=0,b9600,parenb=1,parodd=0,cs7,cstopb=0; socat -T 1 - $device,raw,echo=0,b$baudrate,parenb=1,parodd=0,cs7,cstopb=0 );
                if ($debug==1){print (@buffer,"\n")};
                ### AUSWERTUNG ###
                foreach (@buffer)
                {
                foreach my $obis(%channels)
                {
                my $obiskey = $obis."\(";
                if ($_ =~ /\Q$obiskey\E/)
                {
                $_ =~ m/[^(]+\(([^*]+)\*([^)]+)/;
                my $value = $1;
                my $unit = $2;
                my $ga = $channels{$obis};
                if ($debug==1){print ($obis,"\n")};
                if ($debug==1){print ($value,"\n")};
                if ($debug==1){print ($unit,"\n")};
                if ($debug==1){print ($ga,"\n")};
                if ($unit =~ /\Qh\E/)
                {
                &rrd_counter ($obis,$value)
                }
                else
                {
                &rrd_gauge ($obis,$value)
                }
                &knx_write ($ga,$value);
                }
                }
                }
                
                ### SUBS ###
                
                sub rrd_counter
                {
                if ($debug==1){print ("COUNTER","\n")};
                foreach (@countermodes)
                {
                my $obisname = $_[0];
                my $value = $_[1];
                $obisname =~ tr/./-/;
                my $rrdname = $counterid."_".$obisname."_".$_."\.rrd";
                if ($debug==1){print ($rrdname,"\n")};
                my $rrdfile = $rrdpath."\/".$rrdname;
                unless (-e $rrdfile)
                {
                RRDs::create ($rrdfile,"DS:value:COUNTER:".(($_*60)+600).":0:10 000000000","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];
                my $value = $_[1];
                $obisname =~ tr/./-/;
                my $rrdname = $counterid."_".$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
                {
                ### Wert in DPT9 umwandeln und in Konsole ausgeben
                my @hexdec = encode_dpt9($_[1]);
                my $hexval = sprintf("%x", $hexdec[0]) . " " . sprintf("%x", $hexdec[1]);
                #print ($hexval,"\n");
                system("groupwrite ip:localhost $_[0] $hexval");
                }
                
                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;
                }
                und der Output so:

                root@wiregate723:/home/user# perl acm1.pl
                substr outside of string at acm1.pl line 65.
                root@wiregate723:/home/user#


                unter /var/www/rrd ist auch nichts neues zu finden.

                Und Du hast Recht. Es handelt sich um zwei Zähler. Einer für den Hausstrom und einer für die Wärmepumpe. Wobei der Hausstromzähler via internem Zähler Bus an den WP Zähler angebunden ist, da dieser die Daten via GPRS an meine Stadtwerke sendet.

                EDIT:
                das init.pl script läuft stabil. kann ich beliebig starten und das läuft sauber durch.


                Grüße,
                Mike

                Kommentar


                  Zitat von mikeeyy Beitrag anzeigen
                  Hallo JuMi,

                  in Deinem Code haben sich ein paar Fehler (Leerzeichen) bei den socat Zeilen eingeschlichen. Habe ich bereinigt. Code sieht jetzt so aus:
                  Ja ich hatte aus dem Forum kopiert, da passiert sowas eben wenn man es nicht sauber als CODE taggt.

                  Zitat von mikeeyy Beitrag anzeigen
                  root@wiregate723:/home/user# perl acm1.pl
                  substr outside of string at acm1.pl line 65.
                  root@wiregate723:/home/user#
                  O.K. da weiß ich wo der Fehler liegt, sollte aber trotzdem weiter durchlaufen.

                  Zitat von mikeeyy Beitrag anzeigen
                  Und Du hast Recht. Es handelt sich um zwei Zähler. Einer für den Hausstrom und einer für die Wärmepumpe. Wobei der Hausstromzähler via internem Zähler Bus an den WP Zähler angebunden ist, da dieser die Daten via GPRS an meine Stadtwerke sendet.
                  Das wird hässlich!

                  Zitat von mikeeyy Beitrag anzeigen
                  das init.pl script läuft stabil. kann ich beliebig starten und das läuft sauber durch.
                  Bitte einmal posten, dann kann ich darauf basierend mal eine Revision vorher vllt. was machen.


                  Was mir noch nicht klar ist wie man die 2-in-1 Zählergeschichte vernünftig trennt.


                  Gruß
                  Umgezogen? Ja! ... Fertig? Nein!
                  Baustelle 2.0 !

                  Kommentar


                    hier mein aktuelles init.pl script

                    Code:
                    #!/usr/bin/perl
                    use warnings;
                    use strict;
                    use Device::SerialPort;
                    
                    ### KONFIGURATION ###
                    my $device = "/dev/ttyS0";	#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(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->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

                    Hinsichtlich der Trennung der beiden Zähler...

                    Die Infos von Zähler eins beginnen mit 1-0:

                    1-0:1.8.0*255(002281.998*kWh)
                    1-0:1.8.1*255(000436.461*kWh)
                    1-0:1.8.2*255(001845.537*kWh)
                    1-0:2.8.0*255(000000.226*kWh)
                    1-0:2.8.1*255(000000.226*kWh)
                    1-0:2.8.2*255(000000.000*kWh)

                    Die von Zähler zwei mit 1-1:

                    1-1:1.8.0*255(000902.070*kWh)(13-01-02 12:00:06)

                    ich würde mir (naiv) folgende Lösung vorstellen. Für die Aufbereitung der Charts muss ich ja eh wissen welcher Zähler für was ist (Hausstrom oder WP). Das müsste ich also im Script hinterlegen. Zähler eins (Hausstrom) hätte damit die idZ=0, Zähler (WP) zwei die idZ=1. Es werden gesamt also zwei Zähler hinterlegt. Wenn mehrere Zähler im Script eingebunden werden, müssten zwei Zählerstände ausgelesen und verarbeitet werden. Das Script liest also im Zähler Output 1-id:1.8.0 und fängt mit id=0 an. Das ganze kann ich vielleicht in Form einer Schleife erfolgen..
                    id=0
                    if id<idZ then auslesen von 1-id:1.8.0
                    id=id+1
                    return

                    das ganze wird so lange gemacht bis id=idZ und damit alle Zähler erschlagen sind. abhängig von vom wert von id wird ein extra chart erstellt.

                    Soweit meine Theorie :-)

                    Kommentar


                      Ja sowas müsste man tun ...

                      Das hier könnte so klappen, das ist die Vorgängerversion:
                      Code:
                      use warnings;
                      use strict;
                      use RRDs;
                      
                      ### KONFIGURATION ###
                      my $device = "/dev/ttyS0"; #Port
                      my $rrdpath = "/var/www/rrd"; #Pfad fuer RRDs
                      my $counterid = "test"; #Grundname fuer RRDs
                      my $baudrate = "9600";			#Baudrate fuer Zaehlerauslesung
                      my %channels = ( #Obis-Zahl => Gruppenadresse
                      "15.7.0"=>"12/1/1", #akt. Leistung
                      "17.0.0"=>"12/1/11", #akt. Stromstärke ?
                      "1.8.0"=>"12/1/0" #Zaehlerstand gesamt
                      );
                      my @countermodes = (5,15,60,1440);	#Aufloesungen fuer COUNTER RRDs in Minuten (1440 = Tagesverbrauch)
                      
                      ### ENDE KONFIGURATION ###
                      
                      my %speedrate = (			#Je nach Geschwindigkeit andere Befehel an Zaehler senden
                      		"300"=>"'\x06\x30\x30\x30\x0d\x0a'",
                      		"600"=>"'\x06\x30\x31\x30\x0d\x0a'",
                      		"1200"=>"'\x06\x30\x32\x30\x0d\x0a'",
                      		"2400"=>"'\x06\x30\x33\x30\x0d\x0a'",
                      		"4800"=>"'\x06\x30\x34\x30\x0d\x0a'",
                      		"9600"=>"'\x06\x30\x35\x30\x0d\x0a'"
                      		);
                      		
                      my $ack = $speedrate{$baudrate};
                      print ($baudrate,"->",$ack);
                      
                      ### DATEN EMPFANGEN ###
                      my @buffer = qx(echo '\x2f\x3f\x21\x0d\x0a' | socat -T 1 - $device,raw,echo=0,b9600,parenb=1,parodd=0,cs7,cstopb=0; sleep 1; echo $ack | socat -T 1 - $device,raw,echo=0,b9600,parenb=1,parodd=0,cs7,cstopb=0; socat -T 1 - $device,raw,echo=0,b$baudrate,parenb=1,parodd=0,cs7,cstopb=0);
                      print @buffer;
                      
                      foreach (@buffer)
                      {
                      	foreach my $obis(%channels)
                      	{
                      	my $obiskey = $obis."\(";
                      	if ($_ =~ /\Q$obiskey\E/)
                      	{
                      	$_  =~ m/[^(]+\(([^*]+)\*([^)]+)/;
                      	my $value = $1;
                      	my $unit = $2;
                      	my $ga = $channels{$obis};
                      	print ($obis,"\n");
                      	print ($value,"\n");
                      	print ($unit,"\n");
                      	print ($ga,"\n");
                      	if ($unit =~ /\Qh\E/)
                      	{
                      	&rrd_counter ($obis,$value)
                      	}
                      	else
                      	{
                      	&rrd_gauge ($obis,$value)
                      	}
                      	&knx_write ($ga,$value);
                      	}
                      	}
                      }
                      
                      ### SUBS ###
                      
                      sub rrd_counter
                      {
                      print ("COUNTER","\n");
                      foreach (@countermodes)
                      {
                      my $obisname = $_[0];
                      my $value = $_[1];
                      $obisname =~ tr/./-/;
                      my $rrdname = $counterid."_".$obisname."_".$_."\.rrd";
                      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
                      {
                      print ("GAUGE","\n");
                      my $obisname = $_[0];
                      my $value = $_[1];
                      $obisname =~ tr/./-/;
                      my $rrdname = $counterid."_".$obisname."\.rrd";
                      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
                      {
                      ### Wert in DPT9 umwandeln und in Konsole ausgeben
                      my @hexdec = encode_dpt9($_[1]);
                      my $hexval = sprintf("%x", $hexdec[0]) . " " . sprintf("%x", $hexdec[1]);
                      print ($hexval,"\n");
                      system("groupwrite ip:localhost $_[0] $hexval");
                      }
                      
                      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;
                      }
                      Umgezogen? Ja! ... Fertig? Nein!
                      Baustelle 2.0 !

                      Kommentar


                        da kommt nix...

                        ich habe den Teil DATEN EMPFANGEN mal zusammengekürzt, einfach um zu sehen ob überhaupt was ausgelesen werden kann...

                        Code:
                        ### DATEN EMPFANGEN ###
                        my @buffer = qx(echo '\x2f\x3f\x21\x0d\x0a' | socat -T 1 - $device,raw,echo=0,b9600,parenb=1,parodd=0,cs7,cstopb=0[SIZE="6"][B])[/B][/SIZE];
                        print @buffer;
                        Output:

                        root@wiregate723:/home/user# perl acm2.pl
                        9600->'050
                        'root@wiregate723:/home/user#

                        Kommentar


                          ist der Eintrag korrekt?

                          echo '\x2f\x3f\x21\x0d\x0a'

                          für den ttyS0 Anschluss?

                          habe den echo Eintrag im Code mal wie folgt ersetzt

                          Code:
                          ### DATEN EMPFANGEN ###
                          my @buffer = qx(echo '$device' | socat -T 1 - $device,raw,echo=0,b9600,parenb=1,parodd=0,cs7,cstopb=0; sleep 1; echo $ack | socat -T 1 - $device,raw,echo=0,b9600,parenb=1,parodd=0,cs7,cstopb=0; socat -T 1 - $device,raw,echo=0,b9600,parenb=1,parodd=0,cs7,cstopb=0);
                          print @buffer;
                          Output jetzt

                          'root@wiregate723:/home/user# perl acm2.pl
                          9600->'050
                          '/ACE5ACE4KGPRS

                          0-0:96.1.0*255(05055xxxxxxxxxxxxx)
                          1-0:1.8.0*255(002288.902*kWh)
                          1-0:1.8.1*255(000436.461*kWh)
                          1-0:1.8.2*255(001852.441*kWh)
                          1-0:2.8.0*255(000000.226*kWh)
                          1-0:2.8.1*255(000000.226*kWh)
                          1-0:2.8.2*255(000000.000*kWh)
                          0-0:96.14.0*255(02)
                          1-0:15.7.0*255(006290*W)
                          0-0:17.0.0*255(0085*A)
                          0-0:96.3.10*255(1)
                          0-1:96.1.0*255(05055yyyyyyyyyyyyy)
                          1-1:1.8.0*255(000902.370*kWh)(13-01-02 14:00:09)
                          1-1:1.8.1*255(000902.371*kWh)(13-01-02 14:00:09)
                          1-1:1.8.2*255(000000.000*kWh)(13-01-02 14:00:09)
                          1-1:1.8.3*255(000000.000*kWh)(13-01-02 14:00:09)
                          1-1:1.8.4*255(000000.000*kWh)(13-01-02 14:00:09)
                          1-1:2.8.0*255(000000.000*kWh)(13-01-02 14:00:09)
                          1-1:2.8.1*255(000000.000*kWh)(13-01-02 14:00:09)
                          1-1:2.8.2*255(000000.000*kWh)(13-01-02 14:00:09)
                          1-1:2.8.3*255(000000.000*kWh)(13-01-02 14:00:09)
                          1-1:2.8.4*255(000000.000*kWh)(13-01-02 14:00:09)
                          0-1:96.14.0*255(01)(13-01-02 14:00:09)
                          1-1:15.7.0*255(000000*W)(13-01-02 14:00:09)
                          0-1:17.0.0*255(0000*A)
                          0-1:96.3.10*255(1)
                          !

                          EDIT:
                          da der Zähler die Daten selber in Intervallen sendet, muss ich das script ggf. mehrmals ausführen, um den richtigen Zeitpunkt für die Datenerfassung zu erwischen... sonst ist der Output tatsächlich leer..

                          Kommentar


                            Wenn der Zähler wirklich von alleine sendet dann macht das mit dem Script hier keinen Sinn mehr. Dafür hast Du aber schonmal ne gute Vorlage für was eigenes über socat (Webmin->Socketverbindungen).

                            Deinem Zähler scheint es egal zu sein ob er aktiv abgefragt wird oder nicht.

                            Das '\x2f\x3f\x21\x0d\x0a' durch $device zu ersetzen macht keinen Sinn, hat also nicht zur Datenabfrage beigetragen. Das ist nichts weiter als die in HEX verpackte Abfrageinitialisierung. Da die nicht mehr kommt scheint die Ihm egal zu sein denn er sendet trotzdem.

                            Ein Zwitter aus SML und IEC62056 mit 2 Zählerständen

                            Ganz ehrlich hier fehlt im Moment die Zeit da richtig drauf einzugehen. Im Kenr würde ich folgendes sagen:

                            - Socketverbindung herstellen
                            - Plugin machen und auf Socket subscriben
                            - im Plugin dann bei ankommenden Daten gucken ob der gesamte Datensatz kommt oder ob socat mal lustig ein par Zeichen ausspuckt
                            - Daten ggf. zusammensetzen.
                            - Daten verarbeiten

                            Sorry aber das ist hier wirklich speziell, ne schnelle Lösung hab ich dafür nicht, bin aber bereit zu helfen.

                            Gruß Mirko
                            Umgezogen? Ja! ... Fertig? Nein!
                            Baustelle 2.0 !

                            Kommentar


                              Hallo Mirko,

                              danke dennoch für die bisherige Unterstützung. Ich werde mich mal weiter an dem Script probieren. Meine Anforderungen sind eigentlich gering. Der Zählerstand vom WP Zähler reicht und dann auch nur als Zahl. Chart brauche ich gar nicht.So ich Fortschritte machen sollte, stelle ich diese hier ein.

                              Grüße,
                              Mike

                              Kommentar


                                Naja so schwer ist es ja nicht ... momentan hab ich bloss einfach keine Zeit da tiefer einzusteigen ... die Charts/RRDs fallen da eher mit ab bzw. kann man sich dann ja auch aus der GA erzeugen lassen.

                                Wie gesagt guck mal ob du mit socket_subscribe was machen kannst...da finden sich viele Beispielplugins hier!

                                Gruß
                                Umgezogen? Ja! ... Fertig? Nein!
                                Baustelle 2.0 !

                                Kommentar

                                Lädt...
                                X