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

    Jetzt läuft es...

    ...sogar richtig schnell.

    Hallo JuMi,

    habe Dein Script von gestern mit der Abfrage aus der 0.1.6 verheiratet und kann meine Daten mit der schnellen Geschwindigkeit aus dem Elster AS1440 auslesen. Er updatet mir jetzt auch am Gesamtstand sofort die erste Kommastelle. Werde das jetzt ne Weile beobachten!
    Evtl. verhält sich da mein Zähler etwas anders wie Deiner. Ein Problem mit meinem Auslesekopf (ist der USB Lese- Schreibekopf von volkszaehler.org) konnte ich auch nicht feststellen. Besten Dank nochmals für Deine / eure Unterstützung. Werde mich jetzt mal wieder um die WP (eBus) kümmern

    Grüße

    Frank

    Kommentar


      Zitat von mikeeyy Beitrag anzeigen
      na ja. mein Problem ist ja immer noch, dass mein Zähler alle 10 Sekunden selber sendet...
      Hallo Mike,

      jetzt muss ich gestehen dass ich Deinen Beitrag mit Frank verwechselt habe ... ich erinnere mich wieder ... Sorry
      Aber Du hattest zusätzlich noch die "beiden" Zähler in einem oder wie war das?
      Ich hätte da evtl. eine Idee wie das gehen könnte. Man müsste da nur ein paar Zeilen schieben ... Ich versuche das die Tage mal.

      Eigentlich müssten wir einfach nur die while-Schleife 2x durchlaufen so dass wir das
      Code:
      if ($buffer =~ /\Q$endsign\E/)
      zweimal erreichen.
      Damit ist gewährleistet dass wir den vollständigen Datensatz erhalten haben. Die Verarbeitung danach ist dann quasi analog zu den neuesten Scripten.


      @Frank
      Die Probleme waren eher sporadisch, aber gut wenn es geht!
      Schieb das doch mal ins SVN wenn es geht ... ich hab nämlich wegen ebus keine Zeit (Lust)
      Umgezogen? Ja! ... Fertig? Nein!
      Baustelle 2.0 !

      Kommentar


        Zitat von JuMi2006 Beitrag anzeigen

        jetzt muss ich gestehen dass ich Deinen Beitrag mit Frank verwechselt habe ... ich erinnere mich wieder ... Sorry
        Aber Du hattest zusätzlich noch die "beiden" Zähler in einem oder wie war das?
        Hallo JuMi,

        kein Problem ;-) Bei der Vielzahl von Anfragen hier kann man schon mal den Überblick verlieren.

        Ich habe tatsächlich zwei Zähler die gekoppelt sind. Wobei der Zähler mit dem seriellen Anschluss aber auch die Infos vom zweiten Zähler mitliefert.

        Siehe auch der Output vom alten Script hier:

        0-0:96.1.0*255(050551428442)
        1-0:1.8.0*255(003253.186*kWh) -> Zähler 1
        1-0:1.8.1*255(000615.455*kWh)
        1-0:1.8.2*255(002637.732*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(001360*W)
        0-0:17.0.0*255(0085*A)
        0-0:96.3.10*255(1)
        0-1:96.1.0*255(05055142844)
        1-1:1.8.0*255(001216.858*kWh)(13-02-13 09:00:53) -> Zähler 2
        1-1:1.8.1*255(001216.859*kWh)(13-02-13 09:00:53)
        1-1:1.8.2*255(000000.000*kWh)(13-02-13 09:00:53)
        1-1:1.8.3*255(000000.000*kWh)(13-02-13 09:00:53)
        1-1:1.8.4*255(000000.000*kWh)(13-02-13 09:00:53)
        1-1:2.8.0*255(000000.000*kWh)(13-02-13 09:00:53)
        1-1:2.8.1*255(000000.000*kWh)(13-02-13 09:00:53)
        1-1:2.8.2*255(000000.000*kWh)(13-02-13 09:00:53)
        1-1:2.8.3*255(000000.000*kWh)(13-02-13 09:00:53)
        1-1:2.8.4*255(000000.000*kWh)(13-02-13 09:00:53)
        0-1:96.14.0*255(01)(13-02-13 09:00:53)
        1-1:15.7.0*255(000000*W)(13-02-13 09:00:53)
        0-1:17.0.0*255(0000*A)
        0-1:96.3.10*255(1)

        mit Deinem alten Script bekomme ich bereits alle Daten von beiden Zähler in den $buffer rein. Beispielhaft für Zähler 1 lautet das Ergebnis dann:

        Obiskey: 1-0:1.8.1*255(
        Position: 83
        14
        1-0:1.8.1*255: 000617.072 und landet im rrd. Im alten Script gibt es aber die GA Implementierung noch nicht und du hast dort mit $buffer Variablen gearbeitet. Im aktuellen Script dagegen mit @buffer Variablen. Ich kann den Teil für das Auslesen nicht ohne Fehler vom alten Script in das neue Übernehmen. Hier bräuchte ich mal noch einen Denkanstoß.

        Grüße,
        Mike

        Kommentar


          Nur mal kurz zwischendrin:

          Code:
          1-1:1.8.0*255(001216.858*kWh)
          Müssten wir erstmal per RegEx zerlegen:

          1-1
          1.8.0
          001216.858
          kWh
          Umgezogen? Ja! ... Fertig? Nein!
          Baustelle 2.0 !

          Kommentar


            hat doch hier schon ganz gut funktioniert

            Code:
            my $obisvalue=substr($buffer,($pos+length($key)+1),$obis{$key});
            wie gesagt.. perl ist echt nicht mein thema.. ich taste mich hier nur vorsichtig durch den dschungel..

            Kommentar


              Nur so am Rande, die verwendeten DPTs sind ungeeignet..

              Zitat von JuMi2006 Beitrag anzeigen
              ...
              ja das liegt am DPT9 ... der ist für sowas zu ungenau. Die RRDs werden glücklicherweise direkt im Plugin erstellt.
              Ich hab mein Script auf DPT14 umgestellt, ist allerdings noch nicht im SVN
              Hmm, das liegt aber primär daran, das DPT9 (ein [recht stranger] !float!) für Zähler-Werte schlicht völlig ungeeignet ist!

              Das wäre wohl lieber ein DPT7 (unsigned 2Byte/16Bit, Überlauf bei 65.535 beachten) oder DPT12 geworden (unsigned 4Byte/32Bit, Überlauf bei 4.294.967.295 beachten) , oder?

              DPT14 (4byte IEEE float ist im Kern genauso ungeeignet, da fällt es nur nicht so schnell auf aber es wird über kurz oder lang zu komischen Phänomenen kommen weil der Zählerstand eine Ganzzahl ist und bleibt..

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

              Kommentar


                Im modernen eHz ist der Zählerstand im besten Fall ein float mit der Auflösung von 0.001 kWh. Im schlechtesten Fall hat er eine Auflösung von 0.1 kWh.
                Damit bleibt das float und eigentlich kommt da sinnig nur DPT14 raus.
                Das DPT9 Müll ist haben wir ja gemerkt .

                Grüße

                EDIT
                Da Frank das neuere script mit den erweiterten DPTs verheiratet hat, kann man sich den DPT ja aussuchen .
                Die Version liegt seit gestern im SVN.
                Umgezogen? Ja! ... Fertig? Nein!
                Baustelle 2.0 !

                Kommentar


                  Nochmal, mit Verlaub, DPT9/14 ist für nen Zählerstand ganz einfach falsch..
                  Das sollte ein integer sein..

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

                  Kommentar


                    Nochmal .

                    Warum? Wenn der Zählerstand nunmal kein integer ist sondern float - dann behandle ich den auch als float.
                    Im RRD-tool wird er ja spätestens nach der Multiplikation mit step wieder ein integer. Falls Du das Problem mit dem COUNTER-RRD meinst. Ich wills ja verstehen, aber ich sehe da wirklich keinen Grund.

                    Btw. selbst ABB nutzt DPT14 für den Zählerstand.

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

                    Kommentar


                      Also meine ABB bieten mir nur 2 oder 4Byte signed/unsigned int an (DPT 7/8/12/13)
                      Das Problem mit dem Float im allgemeinen und dem DPT9/14 (IEE754) im speziellen ist das der hoppeln kann, weil er etwas verdichtet (was in der Natur der Sache liegt, weil auch modernste CPUs eigentlich nur INT kennen, FLOAT ist nur eine spielform der Auflösung und Rechen-Methode)
                      Das muss nicht schlecht sein, ist es auch nicht, aber bei einem Counter mit geringem increment in der dritten Nachkommastelle kann das ziemlich blöd ausgehen.. (Chris M. hatte das mal sehr anschaulich erklärt aber den Beitrag finde ich gerade nicht mehr; Kern der Sache, wenn man den Float als 16/32bit/DPT9/iEEE754, Perl/Python/C 4x rumrechnet können sechs verschiedene Werte rauskommen..)

                      Wenns wirklich als float rauskommt plädiere ich für int($wert*1000) -> ins RRD /1000

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

                      Kommentar


                        Zitat von makki Beitrag anzeigen
                        Wenns wirklich als float rauskommt plädiere ich für int($wert*1000) -> ins RRD /1000
                        Passiert ja so ähnlich:
                        Code:
                        int($wert*rrd_step) -> ins RRD /rrd_step
                        Na ich beobachte das mal .

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

                        Kommentar


                          So ... jetzt auch für SML. Läuft derzeit bei Lio ... er wird berichten.
                          Das ganze ist KEIN WireGate Plugin sondern ein simples Perl-Script dass über crontab aufgerufen wird.

                          Grüße

                          Code:
                          #!/usr/bin/perl
                          # Autor: JuMi2006 / www.knx-user-forum.de
                          # knx_write sub: makki / www.knx-user-forum.de
                          # Version: 0.1
                          # Datum: 19.02.2013
                          
                          use warnings;
                          use strict;
                          use Device::SerialPort;
                          use feature "switch";
                          use EIBConnection;
                          use RRDs;
                          
                          #0701000F0700FF = 7.0       FIXME !!! [0F]0700
                          #070100010801FF = 1.8.1
                          
                          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/ttyUSB-1-4";
                          my $rrdpath = "/var/www/rrd";
                          
                          my @obis;
                          push @obis,{obis=>"1.8.0",  fact=>10000, ga =>"14/8/1", dpt => 14, rrd_name => "Zaehler_Verbrauch", rrd => "c"   }; #rrd: c=counter ; g=gauge
                          push @obis,{obis=>"7.0",    fact=>10,    ga =>"14/8/0", dpt => 9 , rrd_name => "Zaehler_Leistung",  rrd => "g" };
                          my @countermodes = (5,15,60,1440);    #Aufloesungen fuer COUNTER RRDs in Minuten (1440 = Tagesverbrauch)
                          
                          
                          my $debug = "";
                          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
                          
                          
                          my ($x,$data);
                          my $start = 0;
                          while ($start < 2) { # wait for second 1B1B1B1B01010101
                                 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 ++};
                                 }
                          }
                          
                          $data =~ m/1B1B1B1B01010101(.*?)B1B1B1/;
                          my $sml = $1;
                          #print $1."\n";
                          
                          foreach my $obis (@obis)
                          {
                          $obis->{obis} =~ s/\./0/g;
                          $obis->{obis} .= "FF";
                          if ($debug==1){print $obis->{obis}." Obis\n";}
                          $sml =~ m/$obis->{obis}(.*?)0177/;
                          if ($debug==1){print $1." contains hex \n";}
                          my $sml_val = $1;
                          #extract value
                          $sml_val =~ s/^.*52FF//;
                          $sml_val = substr($sml_val,2);
                          print $sml_val." hex \n";
                          my $value = $sml_val;
                          my $dec_value = sprintf("%d", hex($value));
                          $dec_value /= $obis->{fact};
                          print $dec_value."<<<<---- Wert\n";
                          
                          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 ($obis->{ga},$dec_value,$obis->{dpt});
                          print "GA:".$obis->{ga}." Wert:".$dec_value." DPT:".$obis->{dpt}."\n";
                          }
                          
                          
                          ### 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;
                          }
                          Umgezogen? Ja! ... Fertig? Nein!
                          Baustelle 2.0 !

                          Kommentar


                            Hi JuMi,

                            warum wandelst Du die Ausgabe vor der Weiterverarbeitung in HEX um? Bei mir tut es leider nix.. keine Ausgabe..

                            Grüße,
                            Mike

                            Kommentar


                              @Mike:

                              Du bist noch nicht dran
                              Aber der Weg könnte ähnlich sein. Hex brauchts nur bei SML.
                              Ich versuch die Tage mal was für Dich.

                              Grüße

                              Du mit Deinem Zwitter

                              EDIT:
                              @Mike: Kommen die Daten vom zweiten Zähler wirklich mit dem Timestamp wie gepostet raus?
                              Was sagt hterm zu Deinem Zähler? Gibt es dort das Ausrufezeichen "!" als Zeichen fürs Datensatzende?
                              Umgezogen? Ja! ... Fertig? Nein!
                              Baustelle 2.0 !

                              Kommentar


                                you made my day!

                                Ich bastel seit zwei Wochen mit dem vzlogger und der middleware an einer vernünftigen Übertragung zum Bus. Bei tty und perl hörte es dann aber auf.
                                Besten Dank für die Arbeit!!

                                Grüße
                                Gunnar

                                Kommentar

                                Lädt...
                                X