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

    #46
    Ich kenn das Protokoll nicht, schwer zu sagen aus der Ferne, aber ein bisschen was wird man schon ändern müssen.

    Versuchs erstmal so wie in dem RFID-Plugin - das gibt ganz simpel in Hex zurück, welche happen da überhaupt kommen. Wenns gut läuft, landets alles in einem Telegramm, dann sieht man weiter..

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

    Kommentar


      #47
      Hab das jetzt mal eingestellt. der SOCAT ist grün

      Das Plugin soweit abgeändert mit meinen Daten.
      Zur Ausgabe habe ich im letzten Abschnitt verständnisprobleme,
      deshalb gelöscht und angepasst. Ziel ist den String als Rückgabewert
      in der Plugin Übersicht abzulesen. -da steht jetzt aber nix
      das ist zum Teil gut, aber halt ohne ergebnis????

      # Plugin R.S-Systems RFID-Reader to KNX


      ##################
      ### DEFINITION ###
      ##################

      my $socknum = 5; # Eindeutige Nummer des Sockets +1

      # Eigenen Aufruf-Zyklus setzen (Initialisierung/zyklisches prüfen)
      $plugin_info{$plugname.'_cycle'} = 300;

      my $recv_ip = "192.168.2.255"; # Empfangsport (UDP, wie in Socket-Einstellungen)
      my $recv_port = "50011"; # Empfangsport (UDP, wie in Socket-Einstellungen)
      my %rfid_ga;
      $rfid_ga{'30343136323c3634373a20'} = '11/2/1'; # Gruppenadresse auf die bei dieser RFID gesendet wird
      #.. usw.
      my $interval = 30; # Sendeintervall für RFIDs in Reichweite in Sekunden

      #######################
      ### ENDE DEFINITION ###
      #######################

      # Hauptverarbeitung
      # or ($fh and eof($socket[$socknum]))
      if (!$socket[$socknum]) { # socket erstellen
      if (defined $socket[$socknum]) { #debug
      if ($socket[$socknum]->opened) { $socket[$socknum]->close(); }
      undef $socket[$socknum];
      } #debug
      $socksel->remove($socket[$socknum]);
      $socket[$socknum] = IO::Socket::INET->new(LocalPort => $recv_port,
      Proto => "udp",
      LocalAddr => $recv_ip
      )
      or return ("open of $recv_ip : $recv_port failed: $!");
      $socksel->add($socket[$socknum]); # add socket to select
      $plugin_socket_subscribe{$socket[$socknum]} = $plugname; # subscribe plugin
      return "opened UDP-Socket $socknum";
      }
      elsif ($fh) { # Read from UDP-Socket
      my $buf;
      recv($fh,$buf,255,0);
      next if(!$buf || length($buf) < 2); # Bogus messages
      my $bufhex = $buf;
      $bufhex =~ s/(.)/sprintf("%x",ord($1))/eg;
      if (time() - $plugin_info{$plugname.'_rfidlast_'.$bufhex} < $interval) {
      # repeated
      knx_write( "12/2/20" , $bufhex, 9 );
      return;
      }
      }

      return;

      Kommentar


        #48
        Ähm, der KNX-write ist mal nix, von vorne:

        Code:
        # Plugin zum Hexdump empfangener UDP-Daten
        
        ##################
        ### DEFINITION ###
        ##################
        
        my $socknum = 5; # Eindeutige Nummer des Sockets
        
        # Eigenen Aufruf-Zyklus setzen (Initialisierung/zyklisches prüfen)
        $plugin_info{$plugname.'_cycle'} = 3600;
        
        my $recv_ip = "192.168.2.255"; # Empfangsport (UDP, wie in Socket-Einstellungen)
        my $recv_port = "50011"; # Empfangsport (UDP, wie in Socket-Einstellungen)
        
        #######################
        ### ENDE DEFINITION ###
        #######################
        
        # Hauptverarbeitung
        # or ($fh and eof($socket[$socknum]))
        if (!$socket[$socknum]) { # socket erstellen
          $socket[$socknum] = IO::Socket::INET->new(LocalPort => $recv_port, Proto => "udp", LocalAddr => $recv_ip )
            or return ("open of $recv_ip : $recv_port failed: $!");
          $socksel->add($socket[$socknum]); # add socket to select
          $plugin_socket_subscribe{$socket[$socknum]} = $plugname; # subscribe plugin
          return "opened UDP-Socket $socknum";
        }
        elsif ($fh) { # Read from UDP-Socket
          my $buf;
          recv($fh,$buf,255,0);
          my $bufhex = $buf;
          $bufhex =~ s/(.)/sprintf("%x",ord($1))/eg;
          return "Received $buf HEXdump: $bufhex";
        }
        
        return; # cyclic call
        Der socat-Eintrag(screenshot?) muss natürlich dazupassen! In diesem Fall Broadcast aufs LAN, das er grün ist heisst noch nicht das er die Daten an den richtigen schickt

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

        Kommentar


          #49
          F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
          0 S root 32104 1 0 80 0 - 1075 - 18:58 ? 00:00:00 /usr/bin/socat -u /dev/usbserial-1-4,raw udp-datagram:192.168.2.255:50011,bind=:50012,reuseaddr ,broadcast


          Na klar!
          Angehängte Dateien

          Kommentar


            #50
            huch! wie hält man das wieder an?

            erste Zeile im Plugin "Return;" schreiben?

            EDL TEST_cycle3600EDL TEST_last1325790656.48292EDL TEST_resultReceived HEXdump: 1eEDL TEST_rfidlast_ 5d461325786691.29115EDL TEST_rfidlast_ 5d46441325786812.99741EDL TEST_rfidlast_00001325786799.86727EDL TEST_rfidlast_00011325786865.98999EDL TEST_rfidlast_0011325786932.04128EDL TEST_rfidlast_001a1325786748.29116EDL TEST_rfidlast_001a31325786681.79558EDL TEST_rfidlast_004c671325786845.73635EDL TEST_rfidlast_0097f1325786714.14367EDL TEST_rfidlast_017771325786800.47096EDL TEST_rfidlast_01801325786717.69914EDL TEST_rfidlast_01811325786721.25858EDL T

            EDIT: ja das wars.
            Also Die Daten kommen im WG an, könnte jetzt nachher probieren den SOCAT, soweit ins richtige Script einzubinden. Der Code muss aber weiter unten in einer Schleife angepasst werden, dazu melde ich mich aber nochmal.

            ach was wichtiges am Rande: EOL=XX? Bedeutet / bewirkt genau was?

            Kommentar


              #51
              den socat abschalten dürfte am einfachsten sein, den Rest versteh ich nicht, was mir das nun sagen soll, woher das stammt, ...

              Es gibt hier ein wirklich praktisches Code einfügen, dann kann man das auch lesen..

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

              Kommentar


                #52
                [INFORMATION]
                DL TEST_rfidlast_ 5d461325786691.29115EDL TEST_rfidlast_ 5d46441325786812.99741EDL TEST_rfidlast_00001325786799.86727EDL TEST_rfidlast_00011325786865.98999EDL TEST_rfidlast_0011325786932.04128EDL TEST_rfidlast_001a1325786748.29116EDL TEST_rfidlast_001a31325786681.79558EDL TEST_rfidlast_004c671325786845.73635EDL TEST_rfidlast_0097f1325786714.14367EDL TEST_rfidlast_017771325786800.47096EDL TEST_rfidlast_01801325786717.69914EDL TEST_rfidlast_01811325786721.25858EDL TEST_rfidlast_01821325786798.09559EDL TEST_rfidlast_01a1311325786868.94438EDL TEST_rfidlast_01a5111325786935.01513EDL TEST_rfidlast_01b1b1325786763.21966EDL TEST_rfidlast_01b1b1b1325786696.07834EDL TEST_rfidlast_04c671325786928.48361EDL TEST_rfidlast_04c676a1325786720.0739

                [/INFORMATION]


                im editor wurde mir das so angezeigt

                bei EDL TEST_rfidlast_04c676a ist "04c676a" der Hexcode der SML-Nachricht-den habe ich heute auswendig gelernt

                Die Daten kommen im WG an, könnte jetzt nachher probieren den SOCAT, soweit ins richtige Script einzubinden. Der Code muss aber weiter unten in einer Schleife angepasst werden, dazu melde ich mich aber nochmal.

                ach was wichtiges am Rande: EOL=XX? Bedeutet / bewirkt genau was?
                Angehängte Dateien

                Kommentar


                  #53
                  Das rfid_last_XXX kommt aber definitiv nicht aus dem von mir geposteten, das ist schlicht MischMaschMurks..
                  Das RFID-Plugin liest nun RFID-Transponder, ich meinte das eher als Beispiel, sicher nicht 1:1..

                  EOL (Datensatz/Zeilenende) wäre nur dann interessant, wenn es ein fixes Zeichen dafür gibt. Dan würde einem der socat jeden Datensatz hübsch in ein Paket packen, ansonsten muss man sich die Schnipsel halt im Plugin selbst zusammensetzen.

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

                  Kommentar


                    #54
                    Hab das jetz noch mal frisch gemacht und 1:1 reinkopiert, weils n.m.I. schon passen würde.

                    Das Ergebnis im Bild.

                    Un hier mal den String:
                    Code:
                    1B1B1B1B01010101760700090129E1D262006200726301
                    0176010107000900514B460B06454D4801027152C87D010163A
                    55000760700090129E1D3620062007263070177010B06454D480
                    1027152C87D0172620165005139477777078181C78203FF01010
                    10104454D480177070100000009FF010101010B06454D4801027
                    152C87D0177070100010800FF63018201621E52FF560000C6966
                    60177070100010801FF0101621E52FF560000C69666017707010
                    0010802FF0101621E52FF56000000000001770701000F0700FF0
                    101621B52FF5500003D1A0177078181C78205FF0101010183025
                    590B4D1321AB69C538768156DACA7993A95576468864D78FDC1
                    21CC754507953C4B255CA3D3E5AF112F92940ADD46C40101016
                    3F73700760700090129E1D66200620072630201710163C868000
                    01B1B1B1[B][COLOR=Red]B1[/COLOR][/B]A01AEC4
                    1B1B1B deutet auf einen Start/Ende hin könnte man auf die rot markierte Stelle nicht EOL setzen?

                    Das sind jetzt >255 zeichen -> ein problem?
                    Angehängte Dateien

                    Kommentar


                      #55
                      Ich habe inzwischen aus dem example/sml_server aus der libehz ein Standalone-Programm zum Auslesen der Werte erstellt was nicht mehr auf Hex-Parsing beruht sonder nativ SML/Obis spricht. Dadurch funktioniert das Auslesen sofort, auch bei meinem vorher problematischem PV-Einspeisezähler.

                      Ich lasse das jetzt allerdings vom Cron direkt in ein rrd schreiben ohne "Umweg" über ein WG Plugin (auch weil ich das Senden auf den Bus nie benutzt habe, sondern nur das RRD). Bei Interesse kann ich den (C-)Code hier gern posten. Wenn man die Werte auf dem Bus braucht kann man das Binary ja auch per "system" aus dem Plugin aufrufen...

                      Kommentar


                        #56
                        Posten: gerne. Vielleicht kann ich das ja ein bisschen komfortabel zusammenpacken.. Ich hab zwar (noch? Hallo eon, §21b EnWG..) keinen passenden Zähler aber die werden kommen;
                        Insofern finde ich das Thema relativ spannend und das WG bietet sich dafür ja dringend an

                        Hatte da auch eine libsml entdeckt, sieht ganz gut aus..
                        Ob nun in C, PHP oder Perl ist denke ich sekundär, solange es am Ende des Tages einfach funktioniert..

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

                        Kommentar


                          #57
                          Du könntest ggf den Messstellenbetreiber wechseln. Das muss ja nicht die EON sein.
                          Derzeit zwischen Kistenauspacken und Garten anlegen.
                          Baublog im Profil.

                          Kommentar


                            #58
                            Naja, ich selbst hab da jetzt nicht so die Not, da ich seinerzeit eon zwei Zähler mit S0-Schnittstelle aus den Rippen geknabbert habe Die laufen am Binäreingang, fertig..

                            Aber für andere ist das Thema IMHO durchaus sehr interessant und für SML macht man auch nicht "mal eben" eine Webabfrage auf anderen Lösungen

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

                            Kommentar


                              #59
                              Die Werte brauch auch ich momentan nicht auf dem Bus
                              RRD-solange wie möglich reicht mir aus.
                              Es sollte nachher nur auf dem WG weiterlaufen

                              Ein sei bemerkt: Zähler ist nicht gleich Zähler und NEtzbetreiber nicht gleich Netzbetrieber. Es verhält sich so, wie die Anzahl der nicht gewollten von Uhren in der Küche:Null Brain

                              Empfehlung: Beim NB nachfragen, ob's eine Zählerauswahl gibt und dann auf HAGER setzen. Denn die sind offen und bieten Doku online an, und aus der Hardware kommt gleich was brauchbares raus.

                              Kommentar


                                #60
                                Ok, hier meine sml_server.c:
                                Code:
                                // Copyright 2011 Juri Glass, Mathias Runge, Nadim El Sayed
                                // DAI-Labor, TU-Berlin
                                //
                                // This is derived from the sample sml_server.c in libSML
                                //
                                // libSML is free software: you can redistribute it and/or modify
                                // it under the terms of the GNU General Public License as published by
                                // the Free Software Foundation, either version 3 of the License, or
                                // (at your option) any later version.
                                //
                                // libSML is distributed in the hope that it will be useful,
                                // but WITHOUT ANY WARRANTY; without even the implied warranty of
                                // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                                // GNU General Public License for more details.
                                //
                                // You should have received a copy of the GNU General Public License
                                // along with libSML.  If not, see <http://www.gnu.org/licenses/>.
                                
                                #include <stdio.h>
                                #include <fcntl.h>
                                #include <unistd.h>
                                #include <errno.h>
                                #include <termios.h>
                                #include <stdlib.h>
                                #include <string.h>
                                #include <sys/ioctl.h>
                                #include <sys/time.h>
                                
                                #include <math.h>
                                
                                #include <netdb.h>
                                #include <sys/socket.h>
                                
                                #include <signal.h>
                                
                                #include <sml/sml_file.h>
                                #include <sml/sml_transport.h>
                                
                                
                                #include "unit.h"
                                
                                int i;
                                
                                int serial_port_open(const char* device) {
                                        int bits;
                                        struct termios config;
                                        memset(&config, 0, sizeof(config));
                                
                                        int fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
                                        if (fd < 0) {
                                                printf("error: open(%s): %s\n", device, strerror(errno));
                                                return -1;
                                        }
                                
                                        // set RTS
                                        ioctl(fd, TIOCMGET, &bits);
                                        bits |= TIOCM_RTS;
                                        ioctl(fd, TIOCMSET, &bits);
                                
                                        tcgetattr( fd, &config ) ;
                                
                                        // set 8-N-1
                                        config.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
                                        config.c_oflag &= ~OPOST;
                                        config.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
                                        config.c_cflag &= ~(CSIZE | PARENB | PARODD | CSTOPB);
                                        config.c_cflag |= CS8;
                                
                                        // set speed to 9600 baud
                                        cfsetispeed( &config, B9600);
                                        cfsetospeed( &config, B9600);
                                
                                        tcsetattr(fd, TCSANOW, &config);
                                        return fd;
                                }
                                
                                void transport_receiver(unsigned char *buffer, size_t buffer_len) {
                                        // the buffer contains the whole message, with transport escape sequences.
                                        // these escape sequences are stripped here.
                                        sml_file *file = sml_file_parse(buffer + 8, buffer_len - 16);
                                        // the sml file is parsed now
                                
                                        for (i = 0; i < file->messages_len; i++) {
                                                sml_message *message = file->messages[i];
                                
                                                if (*message->message_body->tag == SML_MESSAGE_GET_LIST_RESPONSE) {
                                                        sml_list *entry;
                                                        sml_get_list_response *body;
                                
                                                        body = (sml_get_list_response *) message->message_body->data;
                                
                                                        for (entry = body->val_list; entry != NULL; entry = entry->next) { /* linked list */
                                
                                                                int unit = (entry->unit) ? *entry->unit : 0;
                                                                double value;
                                
                                                                switch (entry->value->type) {
                                                                        case 0x51: value = *entry->value->data.int8; break;
                                                                        case 0x52: value = *entry->value->data.int16; break;
                                                                        case 0x54: value = *entry->value->data.int32; break;
                                                                        case 0x58: value = *entry->value->data.int64; break;
                                                                        case 0x61: value = *entry->value->data.uint8; break;
                                                                        case 0x62: value = *entry->value->data.uint16; break;
                                                                        case 0x64: value = *entry->value->data.uint32; break;
                                                                        case 0x68: value = *entry->value->data.uint64; break;
                                
                                                                        default:
                                                                                // fprintf(stderr, "Unknown value type: %x", entry->value->type);
                                                                                value = 0;
                                                                }
                                
                                                                /* apply scaler */
                                                                //value *= pow(10, scaler); requires additional includes from obis library that has unmet dependencies
                                                                value *= 0.0001; // using fixed scalar for now, works with Hager eHZ
                                
                                                                if (value) {
                                                                        printf("%.2f %s\n", value, dlms_get_unit(unit));
                                                                }
                                                        }
                                                exit(0); // processed first message - exit
                                                }
                                        }
                                
                                        // free the malloc'd memory
                                        sml_file_free(file);
                                }
                                
                                int main(int argc, char **argv) {
                                        // this example assumes that a EDL21 meter sending SML messages via a
                                        // serial device. Use serial device name as input parameter, i.e. /dev/ttyUSB1
                                        char *device = argv[1];
                                        int fd = serial_port_open(device);
                                
                                        if (fd > 0) {
                                                // listen on the serial device, this call is blocking.
                                                sml_transport_listen(fd, &transport_receiver);
                                                close(fd);
                                        }
                                
                                        return 0;
                                }
                                Die benötigt noch (für die Einheiten) eine unit.h im gleichen Verzeichnis, die habe ich aus dem vzlogger Projekt genommen:

                                Code:
                                /**
                                 * DLMS Units as specified in ISO EN 62056-62 and used by SML
                                 *
                                 * @package vzlogger
                                 * @copyright Copyright (c) 2011, The volkszaehler.org project
                                 * @license http://www.gnu.org/licenses/gpl.txt GNU Public License
                                 * @author Steffen Vogel <info@steffenvogel.de>
                                 */
                                /*
                                 * This file is part of volkzaehler.org
                                 *
                                 * volkzaehler.org is free software: you can redistribute it and/or modify
                                 * it under the terms of the GNU General Public License as published by
                                 * the Free Software Foundation, either version 3 of the License, or
                                 * any later version.
                                 *
                                 * volkzaehler.org is distributed in the hope that it will be useful,
                                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                                 * GNU General Public License for more details.
                                 *
                                 * You should have received a copy of the GNU General Public License
                                 * along with volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
                                 */
                                
                                typedef struct {
                                    char code;
                                    char *unit;
                                } dlms_unit_t;
                                
                                /**
                                 * Static lookup table
                                 */
                                dlms_unit_t dlms_units[] = {
                                // code, unit        // Quantity            Unit name        SI definition (comment)
                                //=====================================================================================================
                                {1, "a"},        // time                year            52*7*24*60*60 s
                                {2, "mo"},        // time                month            31*24*60*60 s
                                {3, "wk"},        // time                week            7*24*60*60 s
                                {4, "d"},        // time                day            24*60*60 s
                                {5, "h"},        // time                hour            60*60 s
                                {6, "min."},        // time                min            60 s
                                {7, "s"},        // time (t)            second            s
                                {8, "°"},        // (phase) angle        degree            rad*180/π
                                {9, "°C"},        // temperature (T)        degree celsius        K-273.15
                                {10, "currency"},    // (local) currency
                                {11, "m"},        // length (l)            metre            m
                                {12, "m/s"},        // speed (v)            metre per second    m/s
                                {13, "m³"},        // volume (V)            cubic metre        m³
                                {14, "m³"},        // corrected volume        cubic metre        m³
                                {15, "m³/h"},        // volume flux            cubic metre per hour     m³/(60*60s)
                                {16, "m³/h"},        // corrected volume flux    cubic metre per hour     m³/(60*60s)
                                {17, "m³/d"},        // volume flux                        m³/(24*60*60s)
                                {18, "m³/d"},        // corrected volume flux                m³/(24*60*60s)
                                {19, "l"},        // volume            litre            10-3 m³
                                {20, "kg"},        // mass (m)            kilogram
                                {21, "N"},        // force (F)            newton
                                {22, "Nm"},        // energy            newtonmeter        J = Nm = Ws
                                {23, "Pa"},        // pressure (p)            pascal            N/m²
                                {24, "bar"},        // pressure (p)            bar            10⁵ N/m²
                                {25, "J"},        // energy            joule            J = Nm = Ws
                                {26, "J/h"},        // thermal power        joule per hour        J/(60*60s)
                                {27, "W"},        // active power (P)        watt            W = J/s
                                {28, "VA"},        // apparent power (S)        volt-ampere
                                {29, "var"},        // reactive power (Q)        var
                                {30, "Wh"},        // active energy        watt-hour        W*(60*60s)
                                {31, "VAh"},        // apparent energy        volt-ampere-hour    VA*(60*60s)
                                {32, "varh"},        // reactive energy        var-hour        var*(60*60s)
                                {33, "A"},        // current (I)            ampere            A
                                {34, "C"},        // electrical charge (Q)    coulomb            C = As
                                {35, "V"},        // voltage (U)            volt            V
                                {36, "V/m"},        // electr. field strength (E)    volt per metre
                                {37, "F"},        // capacitance (C)        farad            C/V = As/V
                                {38, "Ω"},        // resistance (R)        ohm            Ω = V/A
                                {39, "Ωm²/m"},        // resistivity (ρ)        Ωm
                                {40, "Wb"},        // magnetic flux (Φ)        weber            Wb = Vs
                                {41, "T"},        // magnetic flux density (B)    tesla            Wb/m2
                                {42, "A/m"},        // magnetic field strength (H)    ampere per metre    A/m
                                {43, "H"},        // inductance (L)        henry            H = Wb/A
                                {44, "Hz"},        // frequency (f, ω)        hertz            1/s
                                {45, "1/(Wh)"},        // R_W                            (Active energy meter constant or pulse value)
                                {46, "1/(varh)"},    // R_B                            (reactive energy meter constant or pulse value)
                                {47, "1/(VAh)"},    // R_S                            (apparent energy meter constant or pulse value)
                                {48, "V²h"},        // volt-squared hour        volt-squaredhours    V²(60*60s)
                                {49, "A²h"},        // ampere-squared hour        ampere-squaredhours    A²(60*60s)
                                {50, "kg/s"},        // mass flux            kilogram per second    kg/s
                                {51, "S, mho"},        // conductance siemens                    1/Ω
                                {52, "K"},        // temperature (T)        kelvin
                                {53, "1/(V²h)"},    // R_U²h                        (Volt-squared hour meter constant or pulse value)
                                {54, "1/(A²h)"},    // R_I²h                        (Ampere-squared hour meter constant or pulse value)
                                {55, "1/m³"},        // R_V, meter constant or pulse value (volume)
                                {56, "%"},        // percentage            %
                                {57, "Ah"},        // ampere-hours            ampere-hour
                                {60, "Wh/m³"},        // energy per volume                    3,6*103 J/m³
                                {61, "J/m³"},        // calorific value, wobbe
                                {62, "Mol %"},        // molar fraction of        mole percent        (Basic gas composition unit)
                                            // gas composition  
                                {63, "g/m³"},        // mass density, quantity of material            (Gas analysis, accompanying elements)
                                {64, "Pa s"},        // dynamic viscosity pascal second            (Characteristic of gas stream)
                                {253, "(reserved)"},    // reserved
                                {254, "(other)"},    // other unit
                                {255, "(unitless)"},    // no unit, unitless, count
                                {}            // stop condition for iterator
                                };
                                    
                                char * dlms_get_unit(unsigned char code) {
                                    dlms_unit_t *it = dlms_units;
                                    do { /* linear search */
                                        if (it->code == code) {
                                            return it->unit;
                                        }
                                    } while ((++it)->code);
                                    
                                    return NULL; /* not found */
                                }
                                Das kompiliert dann mit dem Makefile der libsml/example

                                liefert dann bei mir folgendes bei Aufruf:
                                Code:
                                root@wiregate467:/usr/local/src/libsml/examples# /usr/local/bin/sml_server /dev/ttyUSB-1-4.7
                                12771.70 Wh
                                611.28 W
                                root@wiregate467:/usr/local/src/libsml/examples# /usr/local/bin/sml_server /dev/ttyUSB-1-4.5
                                6772.06 Wh
                                35.37 W
                                root@wiregate467:/usr/local/src/libsml/examples# /usr/local/bin/sml_server /dev/ttyUSB-1-4.6
                                1587.30 Wh
                                4.35 W
                                erste Zeile ist der abolsute Zählerstand und die zweite Zeile ist die Durchschnittslast der letzten (10/15?) Minuten. Es kann sein dass einige Zähler noch mehr ausspucken, dann werden es mehr als 2 Zeilen.

                                Kommentar

                                Lädt...
                                X