Raspberry Pi – eHZ auslesen

Heute mal was aus der Kategorie RaspberryPi. Ich habe versucht meinen Stromzähler gewissenhaft immer am Monatsbeginn abzulesen um eine kleine (analoge) Statistik über den Stromverbrauch zu führen. Leider hab ich schon im zweiten Monat vergessen den Zählerstand pünktlich zu notieren. Das musste also irgendwie automatisiert werden…

Glücklicherweise haben wir einen digitalen Stromzähler von EMH metering der sich prima auslesen lassen sollte. Er sendet ungefragt und ohne Unterbrechung SML-Nachrichten (Smart Message Language) über ein IR-Diode in die weite Welt (die meistens an der Tür des Zählerkastens endet).

IMG_3333

Als “Server” kam für mich nur der Raspberry Pi in frage. Der ist günstig in der Anschaffung und im Verbrauch. Betriebssystem ist ein Raspbian auf einer 8GB SD-Karte.

Als Lesekopf habe ich mich für eine Komplettlösung entschieden die man über Volkszähler.org beziehen kann. Das war einfacher und günstiger als wenn man die Einzelteile in verschiedenen Geschäften zusammen suchen muss. Das Ganze kommt dann im schicken gelben Gehäuse inkl. Magnet zur Befestigung am Zähler.

Eine einfache Schaltung aus Phototransistor und Widerstand hätte es wahrscheinlich auch getan, aber dann fehlt noch der Seriell-USB-Wandler da ich den Lesekopf ja mittels USB an den Raspberry anschliessen wollte.

Der Lesekopf wird per USB an den Raspi angeschlossen und vom Linux als “/dev/ttyUSBx” erkannt. Der Treiber für den verwendeten Silabs-Chip ist im Kernel enthalten. Um den Lesekopf zu testen, kann z.B.  minicom genutzt werden.

IMG_3334

Der Zähler arbeitet mit 9600 Baud, 8 bit, Parität “keine”. Diese Einstellungen und das richtige Device müssen im minicom eingestellt werden und dann sollte so was ähnliches zu sehen sein:

Um diese Einstellungen auch für andere Programme/Scripte/… einzustellen, ist folgender Befehl einzugeben wobei ggf. das Device (ttyUSB0) anzupassen ist:

Ist alles richtig eingestellt und der Lesekopf am Zähler angebracht, kann mit

geprüft werden was die serielle Schnittstelle empfängt.

Jetzt kommt der schwierigere Teil: Das “Entschlüsseln” des SML-Datenstroms. Folgendes Bash-Script rufe ich alle 2 Minuten per CRON auf. Das Script liest für 10 Sekunden den Datenstrom von der seriellen Schnittstelle und schreibt die empfangenen Daten in eine Datei (Pfad ggf. anpassen). Anschliessend wird ein PHP-Script zur Auswertung des aufgezeichneten Datenstroms aufgerufen.

Das PHP-Script liest die eben generierte Datei ein und werten den SML-Datenstrom aus und schreibt die extrahierten Werte in eine MySQL-Tabelle. Im Script lese ich den öffentlichen Schlüssel des Zählers, den Zählerstand und die aktuelle Wirkleistung aus. Diese Werte werden in die MySQL-Tabelle eingetragen und die vom obigen Script erzeugt Datei wird wieder gelöscht.

<?php
require_once 'sml_parser.php';

$pathname='/var/www/strom/data/';

if ($handle = opendir($pathname)) {
    while (false !== ($file = readdir($handle))) {
        if ($file != "." && $file != "..") {
            $files[]=$file;
        }
    }

    if(is_array($files)) {
        sort($files);

        foreach($files as $file) {
            if(substr($file,0,9)=='serialin_') {
                $sml_parser = new SML_PARSER();
                $sml_parser->parse_sml_file($pathname.$file);
                $values = $sml_parser->get_first_values();
               
                //print_r($values);
               
                $time = date('Y-m-d H:i:s',filemtime($pathname.$file));

                $OBIS_1_8_1 = $values['0100010801FF']['value']*$values['0100010801FF']['scaler']/1000; # Wh -> kWh
                $public_key = $values['8181C78205FF']['value'];
                $active_power = $values['01000F0700FF']['value'];

                $mysqlhost="<host>";
                $mysqluser="<benutzer>";
                $mysqlpwd="<passwort>";
                $connection=mysql_connect($mysqlhost,   $mysqluser, $mysqlpwd) or   die ("Verbindungsversuch fehlgeschlagen");
                $mysqldb="<datenbank>";
                mysql_select_db($mysqldb,$connection) or    die("Konnte die Datenbank   nicht   waehlen.");
               
                $sql = "INSERT INTO stromzaehler
                        (timestamp,public_key,zaehlerstand,active_power)
                        VALUES ('$time','$public_key','$OBIS_1_8_1','$active_power')"
;
        mysql_query($sql) or die($sql);
       
       
        //Trägt einen Snapshot der aktuellen Daten in eine extra Tabelle ein
        //damit der Raspi nicht immer durch die komplette Tabelle pflügen muss
        $sql = "UPDATE strom_snapshot SET zeitstempel=CURRENT_TIMESTAMP, zaehlerstand='$OBIS_1_8_1', wirkleistung='$active_power'";
        mysql_query($sql) or die($sql);
       
                unlink($pathname.$file);
            }
        }
    }
    closedir($handle);
}
?>

Das war nicht so kompliziert. Interessanter ist die eingebunde sml_parser-Klasse. Diese übernimmt das eigentliche Parsen der SML-Daten und das Auslesen der OBIS-Kennzahlen (siehe Weblinks). Die Klasse hat ein Bekannter geschrieben der zufällig die gleiche Aufgabenstellung zur gleichen Zeit wie ich hatte.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
<?php
class SML_PARSER {
    public $files;

    private $obis_arr = array(
        '0100000000FF' => array('1-0:0.0.0*255','Seriennummer'),
        '0100010700FF' => array('1-0:1.7.0*255','Momentane Wirkleistung Bezug'),
        '0100020700FF' => array('1-0:2.7.0*255','Momentane Wirkleistung Lieferung'),
        '0100010801FF' => array('1-0:1.8.1*255','Wirk-Energie Tarif 1 Bezug'),
        '0100020801FF' => array('1-0:2.8.1*255','Wirk-Energie Tarif 1 Lieferung'),
        '0100010802FF' => array('1-0:1.8.2*255','Wirk-Energie Tarif 2 Bezug'),
        '0100020802FF' => array('1-0:2.8.2*255','Wirk-Energie Tarif 2 Lieferung'),
        '0100010803FF' => array('1-0:1.8.3*255','Wirk-Energie Tarif 3 Bezug'),
        '0100020803FF' => array('1-0:2.8.3*255','Wirk-Energie Tarif 3 Lieferung'),
        '8181C78203FF' => array('129-129:199.130.3*255','Hersteller-ID '),
        '8181C78205FF' => array('129-129:199.130.5*255','Public-Key'),
        '01000F0700FF' => array('1-0:15.7.0*255','Active Power'),
        '0100010800FF' => array('1-0:1.8.0*255','Wirkarbeit Bezug Total: Zaehlerstand'),
        '0100000009FF' => array('1-0:0.0.9*255',' Geraeteeinzelidentifikation'),
        '00006001FFFF' => array('0-0:60.1.255*255','Fabriknummer'),
    );
    private $data;
    private $crc16_global;
    private $crc16_message;

    private $crctab = array( # Hilfsarray zur Berechnung der CRC
    0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
    0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
    0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
    0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
    0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
    0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
    0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
    0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
    0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
    0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
    0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
    0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
    0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
    0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
    0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
    0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
    0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
    0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
    0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
    0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
    0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
    0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
    0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
    0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
    0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
    0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
    0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
    0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
    0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
    0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
    0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
    0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
    );

    function __construct() {
    }

    function debug($text,$showhexdata=true) {
        return; # ggfs. auskommentieren.

        echo "DEBUG: '$text'";
        if($showhexdata) echo " : ". substr($this->data,0,150);
        echo "\n";
    }

    function error($message) {
        return; # ggfs. auskommentieren.

        $e = new Exception();
        $m = $e->getTraceAsString();
        $m = explode("\n",$m);
        unset($m[0]);
        $m = implode("\n",$m);

        echo("ERROR: $message ! \n".$m."\n");
    }

    function sml_crc16($part,$global=true) {
        /*  Vorlage C-Programm siehe:
         *  http://www.photovoltaikforum.com/datenlogger-f5/emh-ehz-protokoll-t86509.html
         */


        $cp = $this->hex2bin($part);

        for ($i=0 ; $i<strlen($cp) ; $i++) {
            $char = ord($cp{$i});

            $this->crc16_message = ($this->crc16_message >> 8) ^ ($this->crctab[($this->crc16_message ^ $char) & 0xff]);
            if(!$global) continue;
            $this->crc16_global  = ($this->crc16_global >> 8)  ^ ($this->crctab[($this->crc16_global  ^ $char) & 0xff]);
        }
    }

    public function hex2bin($hexstr) {
        $n = strlen($hexstr);
        $sbin="";
        $i=0;
        while($i<$n)
        {
            $a =substr($hexstr,$i,2);
            $c = pack("H*",$a);
            if ($i==0){$sbin=$c;}
            else {$sbin.=$c;}
            $i+=2;
        }
        return $sbin;
    }


    private function match($match) {
        global $list_indent;

        if(substr($this->data,0,strlen($match))<>$match) {
            $this->error("'$match' expected, got '".substr($this->data,0,50)."...'");
        }else{
            $this->sml_crc16($match);
            $this->data = substr($this->data,strlen($match));
            #echo "MATCH: $match\n";
        }
    }

    private function read($len) {
        if($len==0) {
            return;
        }

        if(strlen($this->data)< ($len*2)) $this->error("can't read enough bytes");
        $result = substr($this->data,0,2*$len);
        $this->data = substr($this->data,2*$len);

        $this->sml_crc16($result);
        return $result;
    }

    private function parse_sml_data($list_item=0) {
        global $list_indent;
        $TYPE_LEN = $this->read(1);

        if($TYPE_LEN=='00') {
            return $TYPE_LEN; # EndOfSmlMessage
        }

        $TYPE = $TYPE_LEN{0}.'x';     # only high-nibble
        $LEN  = hexdec($TYPE_LEN{1}); # only low-nibble

        while($TYPE{0} &0x8) {  # Multi-Byte TypeLen-Field
            $LEN = $LEN * 0x10;
            $TYPE_LEN = $this->read(1);
            $TYPE = $TYPE_LEN{0}.'x';     # only high-nibble
            $LEN  += hexdec($TYPE_LEN{1}); # only low-nibble
            $LEN--; # 1 abziehen wegen zusätzlichem TL-Byte
        }

        if($LEN==1) return;

        switch($TYPE) {
            case '0x': # Octet
                #return $this->hex2bin($this->read($LEN-1));
                return $this->read($LEN-1);
                break;

            case '5x': # Integer
                return hexdec($this->read($LEN-1));
                break;

            case '6x': # UnsignedInt
                return hexdec($this->read($LEN-1));
                break;

            case '7x': # List
                $list_indent++;
                for($i=1;$i<=$LEN;$i++) $this->parse_sml_data($i);
                $list_indent--;
                break;

            default :
                $this->error("Error, unexpected type '$TYPE' TL=$TYPE_LEN ".$this->data);
        }

        #echo "\n";
        return $TYPE_LEN;
    }

    private function readOctet() {
        $TYPE_LEN = $this->read(1);
        if($TYPE_LEN=='01') return;

        if($TYPE_LEN{0}=='0') {
            $LEN  = hexdec($TYPE_LEN{1}); # only low-nibble
            $octet = $this->read($LEN-1);
            return $octet;
        }else{
            return "[Error, cant read octet : $TYPE_LEN]";
        }
    }

    private function readInteger() {
        $TYPE_LEN = $this->read(1);
        if($TYPE_LEN=='01') return;

        if($TYPE_LEN{0}=='5') {
            $LEN  = hexdec($TYPE_LEN{1}); # only low-nibble
            $integer = $this->read($LEN-1);
            return $integer;
        }else{
            return "[Error, cant read unsigned : $TYPE_LEN]";
        }
    }

    private function readUnsigned() {
        $TYPE_LEN = $this->read(1);
        if($TYPE_LEN=='01') return;

        if($TYPE_LEN{0}=='6') {
            $LEN  = hexdec($TYPE_LEN{1}); # only low-nibble
            $unsigned = $this->read($LEN-1);
            return $unsigned;
        }else{
            return "[Error, cant read unsigned : $TYPE_LEN]";
        }
    }

    private function readInteger8() {
        $val = hexdec($this->readInteger($this->data));
        if($val & 0x80) $val = 0xfe - $val;
        return $val;
    }

    # =============================================================================================
    # High-Level SML-Funktionen
    # =============================================================================================

    private function readOpenResponse() {
        $this->match('76'); # 76 = List of 6 items
        $result['codepage']    = $this->readOctet($this->data);
        $result['clientId']    = $this->readOctet($this->data);
        $result['reqFileId']   = $this->readOctet($this->data);
        $result['serverId']    = $this->readOctet($this->data);
        $result['refTime']     = $this->readOctet($this->data);
        $result['sml-Version'] = $this->readOctet($this->data);

        return $result;
    }

    private function readCloseResponse() {
        $this->match('71'); # 71 = List of 1 item
        $result['signature']   = $this->readOctet($this->data);

        return $result;
    }

    private function readListEntry() {
        $this->match('77'); # 77 = List of 7 item

        $result['objName']          = $this->readOctet($this->data);
        $result['status']           = $this->readUnsigned($this->data);
        $result['valTime']          = $this->parse_sml_data($this->data);
        $result['unit']             = $this->readUnsigned($this->data);
        $result['scaler']           = $this->readInteger8($this->data);
        $result['value']            = $this->parse_sml_data($this->data);
        $result['valueSignature']   = $this->readOctet($this->data);

        if(isset($this->obis_arr[$result['objName']])) {
            $result['OBIS']=$this->obis_arr[$result['objName']][0];
            $result['OBIS-Text']=$this->obis_arr[$result['objName']][1];
        }

        if(in_array($result['objName'],array('8181C78203FF','0100000000FF','00006001FFFF'))) {
            # ggfs. weitere objNames in die Liste aufnehmen
            $result['value'] = $this->hex2bin($result['value']);
        }
       
        switch($result['unit']) {
            case '1B' : $result['unit']='W';
            case '1E' : $result['unit']='Wh';
        }

        if($result['scaler']) $result['scaler'] = pow(10,$result['scaler']);

        return $result;
    }

    private function readValList() {
        $this->debug('ENTER readValList');
        $TYPE_LEN = $this->read( 1);

        if($TYPE_LEN{0}=='7') {
            $LEN = hexdec($TYPE_LEN{1});
            for($i=0;$i<$LEN;$i++) {
                $this->debug("ENTER readListEntry [$i]");
                $result[]=$this->readListEntry($this->data);
            }
            $this->debug('EXIT readValList : '.print_r($result,true),false);
            return $result;
        }else{
            echo('Error reading value-list!');
        }
    }

    #####################################################################################

    private function readListResponse() {
        $this->match('77'); # 77 = List of 1 item
        $result['clientId']         = $this->readOctet($this->data);
        $result['serverId']         = $this->readOctet($this->data);
        $result['listName']         = $this->readOctet($this->data);
        $result['actSensorTime']    = $this->parse_sml_data($this->data);
        $result['vallist']          = $this->readValList($this->data);
        $result['actGatewayTime']   = $this->parse_sml_data($this->data);
        $result['signature']        = $this->readOctet($this->data);

        return $result;
    }

    private function readMessageBody() {
        $this->match('72'); # 72 = List of 2 items
        $result['choice']  = $this->readUnsigned($this->data);
        switch($result['choice']) {

            case '0101':
                $this->debug('PROCESS OpenRequest');

                $result['choice']='OpenRequest';
                $result['body'] = $this->readOpenResponse($this->data);
                break;

            case '0201':
                $this->debug('PROCESS CloseRequest');

                $result['choice']='CloseRequest';
                $result['body'] = $this->readCloseResponse($this->data);
                break;

            case '0701':
                $this->debug('PROCESS GetListResponse');

                $result['choice']='GetListResponse';
                $result['body'] = $this->readListResponse($this->data);
                break;

            default:
                $this->debug('PROCESS UnknownRequest ('.$result['choice'].')');
                //$result['body']  = $this->parse_sml_data($this->data);
        }

        return $result;
    }

    private function parse_sml_message() {
        $this->debug('ENTER parse_sml_message');

        $this->crc16_message = 0xFFFF; # Pruefsumme zuruecksetzen

        $this->match('76');       # 76 = List of 6 items
        $result['transactionId'] = $this->readOctet();
        $result['groupNo']       = $this->readUnsigned();
        $result['abortOnError']  = $this->readUnsigned();
        $result['messageBody']   = $this->readMessageBody();

        $crc_calc = strtoupper(substr('000'.dechex(($this->crc16_message ^ 0xffff)),-4));
        $result['crc_calc'] = substr($crc_calc,-2).substr($crc_calc,0,2); # Wert 4-stellig ausgeben

        $result['crc16']         = $this->readUnsigned();
        $this->match('00');       # endOfSmlMsg = 00

        $result['crcMsgCheck'] = ($result['crc_calc'] == $result['crc16']);

        $this->debug('EXIT parse_sml_message. CRC='.(($result['crcMsgCheck'])?'OK':'FAIL'),false);
        $this->debug('--------------------------------',false);
        return $result;
    }

    # =============================================================================================
    # Schnittstellenfunktionen
    # =============================================================================================

    public function parse_sml_hexdata($hexdata) {
        $this->files = array();
        $this->data = strtoupper($hexdata);

        $sml_header='1B1B1B1B01010101';
        $sml_footer='0000001B1B1B1B1A';

        $start = strpos($this->data,$sml_header);
        if($start===false) return;

        if($start) {
            #echo "$start bytes skipped at begining!\n";
            $this->data=substr($this->data,$start);
        }

        while($this->data) {
            $skip = false;
            $messages = array();

            $this->crc16_global = 0xffff;
            $this->match($sml_header);

            while($this->data<>'' && substr($this->data,0,16)!=$sml_footer) {
                $message = $this->parse_sml_message();
                if($message['crcMsgCheck']) {
                    $messages[] = $message;
                }else{ # if no success, skip to next file
                    $start = strpos($this->data,$sml_header);
                    if($start===false) return;

                    if($start) {
                        #echo "$start bytes skipped in between!\n";
                        $this->data=substr($this->data,$start);
                        $skip=true;
                        break;
                    }

                }
            }

            if($skip) continue;

            $this->match($sml_footer);
            $this->match('03');

            $crc_calc = strtoupper(substr('000'.dechex(($this->crc16_global ^ 0xffff)),-4));
            $crc_calc = substr($crc_calc,-2).substr($crc_calc,0,2); # Wert 4-stellig ausgeben
            $crc16 = $this->read(2);

            $this->files[] = array(
                'crcFileCheck'=>($crc_calc == $crc16),
                'messages'=>$messages
            );
        }
    }

    public function parse_sml_string($string) {
        return $this->parse_sml_hexdata(bin2hex($string));
    }

    public function parse_sml_file($filename) {
        $this->parse_sml_hexdata(strtoupper(bin2hex(file_get_contents($filename))));
    }

    public function get_first_values() {
        foreach($this->files as $file) {
            foreach($file['messages'] as $message) {
                if($message['messageBody']['choice']=='GetListResponse') {
                    $vallist = $message['messageBody']['body']['vallist'];

                    $result = array();
                    foreach($vallist as $value) $result[$value['objName']]=$value;

                    return $result;
                }
            }
        }

        return array();
    }
}

Grafisch dargestellt sieht dann z.B. die Wirkleistung folgendermaßen aus:

wirkleistung

Der Wochenverbrauch sähe dann z.B. so aus:

verbrauch_m

Wie das genau funktioniert, stelle ich in einem späteren Artikel vor. Erstmal viel Spaß beim Auslesen des Zählers.

Probleme mit der Berechnung der Prüfsumme

Bei Problemem mit der Berechnung der Prüfsumme wie in den Kommentaren beschrieben die z.B. bei Benutzung eines anderen Stromzählers wie den von EMH auftreten kann, hilft das Auskommentieren folgender Zeilen in der Datei sml_parser.php. Das ist erstmal nur ein Workaround bis ich Zeit finde mich dem eigentlichen Problem zu widmen…

Gruß
Chris

70 Gedanken zu „Raspberry Pi – eHZ auslesen

  • 2. März 2014 um 14:50
    Permalink

    Ich bekomme einen Fehler im sml_parser.php Skript in Zeile 172.
    $list_indent ist nicht bekannt.

    $list_indent wird auch nirgendwo deklariert.

    Läuft das Skript wirklich so wie hier bei Dir?

    Antwort
    • diefenbecker
      4. März 2014 um 11:18
      Permalink

      Hallo,

      da ist tatsächlich eine Zeile mit der Variablendeklaration
      global $list_indent; in private function parse_sml_data
      verlustiert gegangen. Jetzt sollte es passen! Vielen Dank für den Hinweis.

      Gruß
      Chris

      Antwort
      • 23. November 2014 um 19:58
        Permalink

        Hallo Chris,
        Ich bin zufällig auf deine Ausführungen gestoßen. Ich habe folgendes Problem:
        Ich möchte auch genau so einen Zähler mit SML Protokoll auslesen. Da ich eine übergeordnete Regelung habe, möchte ich die Daten aber über Modbus IP zur Verfügung stellen. Einen IR Lesekopf mit USB Anschluss habe ich schon, aber ich habe keine Ahnung wie ich das jetzt anstellen soll. Gibt es eine Möglichkeit über so einen Raspberry? Was benötige ich alles, wo bekommt man das alles her und wie kompliziert ist es, so etwas zu installieren? Über ein wenig Hilfe wäre ich sehr dankbar.
        Udo

        Antwort
        • diefenbecker
          28. November 2014 um 18:20
          Permalink

          Hallo Udo,

          bei Modbus muss ich leider passen. Die Modbus-Minik käme aber doch erst nach dem Auslesen des SML-Datenstroms und kann getrennt betrachtet werden, oder?
          Bin da aber, wie schon gesagt, relativ ahnungslos. Bei M-BUS (Meter-Bus) hätte ich Dir helfen können. Da bin ich aktuell mit dem Auslesen eines Wasserzählers und Wärmemengenzählers zugange.

          Gruß
          Chris

          Antwort
  • 28. März 2014 um 23:40
    Permalink

    Hallo,
    Schöne Anleitung. Lief bei mir seit Januar und das Problemlos.
    Seit vorgestern funktioniert es leider nicht mehr, ohne das ich irgend etwas geändert habe. Bekomme nur noch die Meldung:


    PHP Notice: Undefined index: 0100010801FF in /var/www/strom/sml.php on line 26
    PHP Notice: Undefined index: 0100010801FF in /var/www/strom/sml.php on line 26
    PHP Notice: Undefined index: 0100020801FF in /var/www/strom/sml.php on line 27
    PHP Notice: Undefined index: 0100020801FF in /var/www/strom/sml.php on line 27
    PHP Notice: Undefined index: 0100100700FF in /var/www/strom/sml.php on line 28

    Suche schon seit 2 Tagen den Fehler konnte ihn noch nicht ausfindig machen.

    Antwort
    • diefenbecker
      29. März 2014 um 08:41
      Permalink

      Hallo Peter,

      das ist seltsam. Hast Du mal geschaut ob der Lesekopf noch korrekt sitzt?
      Gibt “cat /dev/ttyUSB0 | od -tx1” noch ein SML-Datagramm aus?

      Gruß
      Chris

      Antwort
      • 29. März 2014 um 10:15
        Permalink

        Hallo,
        auch wenn ich nicht Peter heiße denke ich du meinst mich 😉

        Also die Daten kommen noch an ich denke eher es liegt an der sml_parser.php. Wenn ich die im debugmodus ausführe werden die Daten erkannt. Allerdings wird dann scheinbar ein leeres Array an die sml.php übergeben.


        DEBUG: 'ENTER parse_sml_message' : 760900000000025477526201620072630101760101090000000000C6D2720B06484147010754DEA8F6010163DD8F0076090000000002547753620162007263070177010B06484147010754
        DEBUG: 'PROCESS OpenRequest' : 760101090000000000C6D2720B06484147010754DEA8F6010163DD8F0076090000000002547753620162007263070177010B06484147010754DEA8F6070100620AFFFF726201650101BC45
        DEBUG: 'EXIT parse_sml_message. CRC=OK'
        DEBUG: '--------------------------------'
        DEBUG: 'ENTER parse_sml_message' : 76090000000002547753620162007263070177010B06484147010754DEA8F6070100620AFFFF726201650101BC457A77078181C78203FF01010101044841470177070100000009FF010101
        DEBUG: 'PROCESS GetListResponse' : 77010B06484147010754DEA8F6070100620AFFFF726201650101BC457A77078181C78203FF01010101044841470177070100000009FF010101010B06484147010754DEA8F6017707010001
        DEBUG: 'ENTER readValList' : 7A77078181C78203FF01010101044841470177070100000009FF010101010B06484147010754DEA8F60177070100010800FF628201621E52FF550187EF1E0177070100010801FF0101621E
        DEBUG: 'ENTER readListEntry [0]' : 77078181C78203FF01010101044841470177070100000009FF010101010B06484147010754DEA8F60177070100010800FF628201621E52FF550187EF1E0177070100010801FF0101621E52
        DEBUG: 'ENTER readListEntry [1]' : 77070100000009FF010101010B06484147010754DEA8F60177070100010800FF628201621E52FF550187EF1E0177070100010801FF0101621E52FF550187C80E0177070100010802FF0101
        ...
        DEBUG: 'ENTER readListEntry [8]' : 77070100100700FF0101621B520053069A0177078181C78205FF0101010183021E7310EEE52D30F6477042163EC3436CC747EE1685E4965FA9947DA4365CF0F7985824D93827F68D2BAF53
        DEBUG: 'ENTER readListEntry [9]' : 77078181C78205FF0101010183021E7310EEE52D30F6477042163EC3436CC747EE1685E4965FA9947DA4365CF0F7985824D93827F68D2BAF53A6E35ED4F6010101639DA100760900000000
        DEBUG: 'EXIT readValList : Array
        (
        [0] => Array
        (
        [objName] => 8181C78203FF
        [status] =>
        [valTime] =>
        [unit] =>
        [scaler] => 0
        [value] => xxx
        [valueSignature] =>
        [OBIS] => 129-129:199.130.3*255
        [OBIS-Text] => Hersteller-ID
        )

        ...
        ...

        )
        '
        DEBUG: 'EXIT parse_sml_message. CRC=OK'
        DEBUG: '--------------------------------'
        DEBUG: 'ENTER parse_sml_message' : 76090000000002547754620162007263020171016363D10000001B1B1B1B1A022D871B1B1B1B01010101760900000000025477556201620072630101760101090000000000C6D2730B0648
        DEBUG: 'PROCESS CloseRequest' : 71016363D10000001B1B1B1B1A022D871B1B1B1B01010101760900000000025477556201620072630101760101090000000000C6D2730B06484147010754DEA8F6010163354C0076090000
        DEBUG: 'EXIT parse_sml_message. CRC=OK'
        DEBUG: '--------------------------------'
        DEBUG: 'ENTER parse_sml_message' : 00001B1B1B1B1A022D871B1B1B1B01010101760900000000025477556201620072630101760101090000000000C6D2730B06484147010754DEA8F6010163354C0076090000000002547756
        ERROR: '76' expected, got '00001B1B1B1B1A022D871B1B1B1B0101010176090000000002...' !
        #1 /var/www/strom/sml_parser.php(357): SML_PARSER->match('76')
        #2 /var/www/strom/sml_parser.php(403): SML_PARSER->parse_sml_message()
        #3 /var/www/strom/sml_parser.php(441): SML_PARSER->parse_sml_hexdata('1B1B1B1B0101010...')
        #4 /var/www/strom/sml.php(22): SML_PARSER->parse_sml_file('/var/www/strom/...')
        #5 {main}
        ...
        ...
        DEBUG: 'PROCESS UnknownRequest ([Error, cant read unsigned : ])' :
        ERROR: can't read enough bytes !
        #1 /var/www/strom/sml_parser.php(140): SML_PARSER->read(1)
        #2 /var/www/strom/sml_parser.php(346): SML_PARSER->parse_sml_data(false)
        #3 /var/www/strom/sml_parser.php(361): SML_PARSER->readMessageBody()
        #4 /var/www/strom/sml_parser.php(403): SML_PARSER->parse_sml_message()
        #5 /var/www/strom/sml_parser.php(441): SML_PARSER->parse_sml_hexdata('1B1B1B1B0101010...')
        #6 /var/www/strom/sml.php(22): SML_PARSER->parse_sml_file('/var/www/strom/...')
        #7 {main}
        ERROR: Error, unexpected type 'x' TL= !
        #1 /var/www/strom/sml_parser.php(346): SML_PARSER->parse_sml_data(false)
        #2 /var/www/strom/sml_parser.php(361): SML_PARSER->readMessageBody()
        #3 /var/www/strom/sml_parser.php(403): SML_PARSER->parse_sml_message()
        #4 /var/www/strom/sml_parser.php(441): SML_PARSER->parse_sml_hexdata('1B1B1B1B0101010...')
        #5 /var/www/strom/sml.php(22): SML_PARSER->parse_sml_file('/var/www/strom/...')
        #6 {main}
        ERROR: '00' expected, got '...' !
        #1 /var/www/strom/sml_parser.php(367): SML_PARSER->match('00')
        #2 /var/www/strom/sml_parser.php(403): SML_PARSER->parse_sml_message()
        #3 /var/www/strom/sml_parser.php(441): SML_PARSER->parse_sml_hexdata('1B1B1B1B0101010...')
        #4 /var/www/strom/sml.php(22): SML_PARSER->parse_sml_file('/var/www/strom/...')
        #5 {main}
        DEBUG: 'EXIT parse_sml_message. CRC=FAIL'
        DEBUG: '--------------------------------'
        PHP Notice: Undefined index: 0100010801FF in /var/www/strom/sml.php on line 26
        PHP Notice: Undefined index: 0100010801FF in /var/www/strom/sml.php on line 26
        PHP Notice: Undefined index: 0100020801FF in /var/www/strom/sml.php on line 27
        PHP Notice: Undefined index: 0100020801FF in /var/www/strom/sml.php on line 27
        PHP Notice: Undefined index: 0100100700FF in /var/www/strom/sml.php on line 28

        Die richtigen Werte sind da ich habe sie durch “xxx” ersetzt.

        Gruß Manfred

        Antwort
  • 15. April 2014 um 19:24
    Permalink

    Hallo Chris,

    schöner Blog.
    Darf ich trotzdem den Hinweis geben:
    Du schreibst:
    “Der Lesekopf arbeitet mit 9600 Baud, 8 bit, Parität “keine”. ”
    Nicht der Lesekopf arbeitet mit dieser Einstellung, sondern der Zähler.
    Dem IR-Kopf ist die Baudrate und das Frameformat egal.

    Gruß
    Udo

    Antwort
    • diefenbecker
      15. April 2014 um 20:09
      Permalink

      Hallo Udo,

      danke für den Hinweis. Das ist natürlich absolut korrekt.
      Ich habe es im Text geändert.

      Gruß
      Chris

      Antwort
  • 8. Oktober 2014 um 19:26
    Permalink

    Hallo
    Du schreibst dass du den lesekopf bei Volkszähler.de bestellt hast.
    Ich finde hier aber keine bestellmöglichkeit…

    Was hat er denn gekostet ?

    Cu

    Antwort
  • 24. Februar 2015 um 22:47
    Permalink

    Hallo,
    zunächst mal vielen Dank für die coole Anleitung.

    Habe das Projekt nun auch gebaut, bekomme nun aber auch genau wie im oberen Kommentar die folgende Fehlermeldung:

    PHP Notice: Undefined index: 0100010801FF in /var/www/strom/sml.php on line 26
    PHP Notice: Undefined index: 0100010801FF in /var/www/strom/sml.php on line 26
    PHP Notice: Undefined index: 0100020801FF in /var/www/strom/sml.php on line 27
    PHP Notice: Undefined index: 0100020801FF in /var/www/strom/sml.php on line 27
    PHP Notice: Undefined index: 0100100700FF in /var/www/strom/sml.php on line 28

    Gibt es hierfür bereits eine Lösung?

    Vielen Dank.
    Gruß Johannes

    Antwort
    • diefenbecker
      25. Februar 2015 um 16:39
      Permalink

      Hallo Johannes,

      hast Du den Teil zur Berechnung der Prüfsumme auskommentiert wie am Ende des Artikels beschrieben?
      Welchen Zähler hast Du? Unterstützt der Zähler die betreffenden Adressen?

      Gruß
      Chris

      Antwort
  • 26. Februar 2015 um 19:02
    Permalink

    Hallo Chris,

    es ist ein EDL21 Zähler von EnBW.
    Fehler kommt leider auch nach dem auskommentieren, sieht so aus:

    PHP Notice: Undefined index: 0100010801FF in /var/www/strom/sml.php on line 26
    PHP Notice: Undefined index: 0100010801FF in /var/www/strom/sml.php on line 26
    PHP Notice: Undefined index: 8181C78205FF in /var/www/strom/sml.php on line 27
    PHP Notice: Undefined index: 01000F0700FF in /var/www/strom/sml.php on line 28
    UPDATE strom_snapshot SET zeitstempel=CURRENT_TIMESTAMP, zaehlerstand=’0′, wirkl

    Woran könnte es noch liegen?

    Habe noch eine Frage:
    Welchen Datentyp müssen die Spalten in der MySQL haben?

    Vielen Dank.
    Gruß Johannes

    Antwort
    • diefenbecker
      8. März 2015 um 13:25
      Permalink

      Hallo Johannes,

      ertmal sorry für die späte Antwort. Dann schon mal die Antwort auf die Einfache Frage: Die Datentypen der Spalten sind “float” für z.B. Wirkleistung und den Zählerstand und “varchar” für den public_key.

      Jetzt das schwierigere Problem: Wie sieht denn bei Dir das Ergebnis von “cat /dev/ttyUSB0 | od -tx1” aus? Schaut das aus wie SML? Kannst Du dann bitte auch mal in “sml_parser.php” in der Funktion “function debug” das “return;” auskommentieren und mir das Ergebnis der Ausgabe zusenden? Dann evtl noch das “unlink” am Ende der Datei “sml.php” auskommentieren und mir mal die Datei die vom sh-Script erzeugt wird zusenden (wenn Du nichts geändert hast sollte die unter /var/www/strom/data/ liegen).

      Gruß
      Chris

      Antwort
  • 8. März 2015 um 22:07
    Permalink

    Hallo Chris,

    ja, der Zähler sitzt sauber und liefert einwandfrei seine Daten, sieht so aus:

    0000000 1b 1b 1b 1b 01 01 01 01 76 05 00 fa 0f 5a 62 00
    0000020 62 00 72 63 01 01 76 01 01 05 00 53 5a 72 0b 06
    0000040 49 53 4b 01 09 77 0f be b5 01 01 63 b6 19 00 76
    0000060 05 00 fa 0f 5b 62 00 62 00 72 63 07 01 77 01 0b
    0000100 06 49 53 4b 01 09 77 0f be b5 07 01 00 62 0a ff
    0000120 ff 72 62 01 65 00 7c 6f 95 77 77 07 81 81 c7 82
    0000140 03 ff 01 01 01 01 04 49 53 4b 01 77 07 01 00 00
    0000160 00 09 ff 01 01 01 01 0b 06 49 53 4b 01 09 77 0f
    0000200 be b5 01 77 07 01 00 01 08 00 ff 65 00 00 01 82
    0000220 01 62 1e 52 ff 59 00 00 00 00 00 b2 5e 0a 01 77
    0000240 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 59 00 00
    0000260 00 00 00 b2 5e 0a 01 77 07 01 00 01 08 02 ff 01
    0000300 01 62 1e 52 ff 59 00 00 00 00 00 00 00 00 01 77
    0000320 07 01 00 10 07 00 ff 01 01 62 1b 52 00 55 00 00
    0000340 01 66 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83
    0000360 02 84 a8 d9 da 5b 10 e5 0a 72 7f 84 2c 62 b4 be
    0000400 09 2a 92 dc 43 db fa 4f d7 b9 c1 ff bd e8 42 3c
    0000420 4f e8 5e a0 5d 3f bf f0 b0 25 45 a8 3a 2d f1 13
    0000440 d9 01 01 01 63 0c 11 00 76 05 00 fa 0f 5c 62 00
    0000460 62 00 72 63 02 01 71 01 63 61 a2 00 1b 1b 1b 1b
    0000500 1a 00 5b 22 1b 1b 1b 1b 01 01 01 01 76 05 00 fa
    0000520 0f 5d 62 00 62 00 72 63 01 01 76 01 01 05 00 53
    0000540 5a 73 0b 06 49 53 4b 01 09 77 0f be b5 01 01 63
    0000560 85 85 00 76 05 00 fa 0f 5e 62 00 62 00 72 63 07

    Hab dir die Debug Daten zugemailt.
    Zählerstand habe ich jetzt gesehen wird schon mal korrekt ausgegeben, das ist schon ein erster Erfolg 🙂

    Vielen Dank, dass du dir die Zeit nimmst die Daten anzuschauen.

    Gruß Johannes

    Antwort
  • 12. März 2015 um 21:12
    Permalink

    Hallo Chris,

    vielen Dank für deine Email, das mit der Adresse war der entscheidende Hinweis.
    Habe die Adresse für die Wirkleistung nun gefunden, die heißt bei meinem Zähler einfach anders, Script läuft jetzt ohne Fehler.
    Besten Dank für deine Zeit und den Support 🙂

    Gruß
    Johannes

    Antwort
  • 3. April 2015 um 20:35
    Permalink

    Hallo ,

    bin kurz vorm verzweifel. Versuche meinen Zähler auszulesen.Scheint nicht zu klappen.
    Wenn ich mit :
    cat /dev/lesekopf0 | od -tx1 den Zähler auslese kommen die Daten korekt :
    0003520 81 c7 82 03 ff 01 01 01 01 04 45 4d 48 01 77 07
    0003540 01 00 00 00 09 ff 01 01 01 01 0b 06 45 4d 48 01
    0003560 04 c5 6a 14 52 01 77 07 01 00 01 08 00 ff 63 01
    0003600 82 01 62 1e 52 ff 56 00 04 16 27 31 01 77 07 01
    0003620 00 02 08 00 ff 63 01 82 01 62 1e 52 ff 56 00 05
    0003640 33 c4 58 01 77 07 01 00 01 08 01 ff 01 01 62 1e

    Wenn ich aber das Skript ausführe welches den Zähler ausliest und die Werte in eine Datei schreibt kommen nur noch Hyroglyphen an :
    v
    Woran kann das liegen ?

    Danke und Gruß Daniel

    Antwort
    • diefenbecker
      3. April 2015 um 20:45
      Permalink

      Hi Daniel,
      schick mir mal die generierte Datei per Mail.
      Ich schaue mir das dann mal an.
      Hast du “Debug” in der Parser-Klasse schon mal aktiviert oder die Checksum-Prüfung auskommentiert?

      Gruß
      Chris

      Antwort
  • 27. Oktober 2015 um 10:30
    Permalink

    Hallo Chris,

    kurze Frage, du hast im obigen Artikel in Aussicht gestellt noch zu erklären wie Du die grafische Darstellung realisiert hast.

    gibt es diesen Artikel schon ?

    Ich habe bei meiner Analge z.Zt. Volkszähler im Einsatz auf einem Pi. Da ich 4 Werte mitplotte ist der kleine Kreiszahl Rechner schon sehr gut ausgelastet.
    Weiterhin intereesiert mich bei mind 2 Werten lediglich ein Datensatz pro Monat…

    Ich habe schon darüber nachgedacht dies per CRON und dem vzlogger zu basteln. Dennoch würde mich interessieren welche “Visu” du benutzt.

    Mfg
    Thomas

    Antwort
    • diefenbecker
      31. Oktober 2015 um 09:14
      Permalink

      Hi Thomas,

      im Artikel (am Ende) gibt es ein Beispiel für das Zeichnen der Graphen.
      Ich nutze dazu pChart. Bei mir ist der Raspi auch ziemlich beschäftigt (Heizung, Strom, Gas, Temperaturen Kachelofen und Homematic-Sensoren).
      In der MySQL sind in einigen Tabellen aktuell teilweise 300.000+ Zeilen. Da ackert der Kleine schon ganz schön wenn mal Durchschnittswerte berechnet werden sollen. Die meisten Graphen lasse ich daher nicht On The Fly beim Aufruf meiner Intranet-Seite erstellen, sondern (wie Du auch schon angedacht hast) zeitgesteuert per Cron. Das ist auch in dem eben genannten Artikel beschrieben.

      Gruß
      Chris

      Antwort
  • 19. Januar 2016 um 18:03
    Permalink

    Hallo,
    dein Projekt ist sehr interessant, und so habe ich mir den ISB IR gekauft. Leider habe ich keine Erfahrungen mit Bash und da habe ich leider ein Problem.
    Bekomme immer folgenden Fehler:
    /test.sh: Zeile 10: amp: Kommando nicht gefunden.
    “/dev/ttyUSB0” -> “/home/pi/fileext=_201601191745/S.txtserialin”
    cp: reuläre Datei /home/pi/fileext=201601191745/S.txtserialin” kann nicht angelegt werden: Datei oder Verzeichnis nicht gefunden
    ./test.sh: Zeile 12: kill (2549) – Kein passender Prozess gefunden

    Wo liegt mein Fehler? Habe die Datei mit
    sudo nano test.sh
    angelegt und wollte testen mit
    bash test.sh

    Antwort
    • diefenbecker
      19. Januar 2016 um 21:22
      Permalink

      Hi,

      irgendwie zerhakt der Editor im Blog ab und an Quelltexte, Shellscripte etc. So werden &, >, <, ... gegen die für HTML maskierten Zeichenfolgen "&", ">", "&lt", etc. getauscht. Ich habe das im Artikel korrigiert. Bei Dir ist in dem Script beim cp-Kommando am Ende ein "&" welches Linux dann nicht kennt. Teste bitte nochmal die korrigierte Version. Die weiteren Scripte habe ich auch bereinigt. Das "bash" vor dem Scriptnamen zum starten kannst Du weg lassen und nur "./test.sh" nutzen. Im Script steht ja schon das die Bash genutzt werden soll. Falls es nicht klappt, melde Dich nochmal. Gruß Chris

      Antwort
    • 20. Januar 2016 um 22:04
      Permalink

      Hallo,

      danke, jetzt läuft das Scrpt, ist es aber normal, dass sich “Hyroglyphen” in der txt befinden. Müssen diese nicht binär sein?

      Antwort
  • 20. Januar 2016 um 19:08
    Permalink

    Ich suche wo man fertige IR Leser kaufen kann. Hat jemand einen Link für mich?

    Da ich zwei Zähler habe: kann ich problemlos zwei Zähler auslesen und diese unterscheiden?

    Wie werden die Auswertungen erstellt? Ich arbeite bislang mit Gnuplot, aber glaube die Lösung gefällt mir besser…

    Antwort
  • 5. Februar 2016 um 16:23
    Permalink

    Hallo,
    in welchem Format werden die Daten in der .txt gespeichert? Würde gerne die Daten Hexadezimal, also 1B 1B …… speichern. Für die Weiterverarbeitung wäre es super, wenn ich die Daten für mich lesbar machen könnte.

    Viele Grüße
    Jay

    Antwort
    • diefenbecker
      5. Februar 2016 um 16:56
      Permalink

      Hallo Jay,

      die Daten werden binär gespeichert.
      Mittels des Shell-Befehls xxd kannst Du die Datei aber in das von Dir gewünschte Hex-Format konvertieren.

      xxd -p
      Beispiel:
      xxd -p serialin_20160205163848.txt serialin_20160205163848_hex.txt

      xxd kommt glaube ich mit vim mit. Evtl. musst Du also noch vim installieren.

      Gruß
      Chris

      Antwort
      • 5. Februar 2016 um 18:21
        Permalink

        Hallo Chris,

        danke für die schnelle Antwort. Werde es später ausprobieren. In welchem Format/Code kommen die Daten von der USB?

        Viele Grüße Jay

        Antwort
  • 16. März 2016 um 20:16
    Permalink

    Hallo,

    ist es normal das das “cat /dev/ttyUSB0 | od -tx1” abbricht nach ein paar Zeilen ? Sollte es durchlaufen ? Ich dachte der schaut sich bis ich terminiere den Datenstrom an

    1. Versuch
    0000000 1b 1b 18 1b 01 05 00 00 05 06 00 a7 e0 1b 00 00
    0000020 49 26 c0 0a 0b 82 20 00 60 00 40 3f bf 00 00 34
    0000040 01 01 02 80 45 0a 01 6c 4b 60
    0000052

    2. Versuch
    0000000 60 00 80 c4 3b 00 c3 00 28 64 00 82 2b 08 01 25
    0000020 00 86 a4 e0 0c 00 c0 f0 07 c7 07 f1 34 3b 0a 00
    0000040 47 01 00 00 00 84 00 8c 06 00 08 80 b0 0c 80 00
    0000060 80 0c 60 08 b0 8c 30 08 10 01 0a 60 00 c0 06 80
    0000100 00 c0 00 00 f0 bf 00 02 06 02 fe 69 00 45 a0 09
    0000120 e6 79 c0 a8 07 ac e0 ef 31 0c 0c c0 00 00 00 80
    0000140 00 00 06 0a ff 8c f0 ff f8 bc f8 ff e0 f0 e0 8c
    0000160 b0 8c ff fe 1f ff ec ff 78 ee ff e0 ff fc 6e ee
    0000200 ff ee e0 ff e0 ff e0 ff e0 c0 ff e0 ff e0 ff e7
    0000220 ec 0c fc f0 c6 ff e0 ff bc e0 f0 ff ee 3c 0c 63
    0000240 ff ef f7 f8 db e0 ff e0 ff e0 ff ec ff bc ff 3c
    0000260 db e3 b8 ee fe f8 df fe ff fc ce f8 fc 8c b0 8c
    0000300 fe fc f0 f8 f0 ce f8 ce ff ff fe fe ff f0 fe ff
    0000320 ff ff f0 f0 f0 f0 e0 f0 f0 9f ff ee fe f8 e7 f0
    0000340 fe f0 f8 ff be ff ee fe fc f0 f0 f0 fe fe be 3e
    0000360 ff ff fc ff fe ef fc fe ce f8 ce ff fe f8 fc f8
    0000400 ef fc ef ff ff f8 ff f8 f8 f8 f8 f0 fc f8 ff ff
    0000420 ff fc 1f ff f8 fc ff ff ff fe f8 f8 f8 ff ff ff
    0000440 bf fe ff fe ff ef fc ef ff fc fe fc fe fc fc fc
    0000460 fc fc f8 fe fc fe ff fc fe ff fc fc fc ff ff fe
    0000500 ff ff ff fe fe fe fe fe fc fe ff ff ff fe fe fe
    0000520 ff ff ff ff ff ff fe ff ff ff ff 1b 1b 1b 1b 00
    0000540 02 01 01 06 23 80 9b 61 81 33 62 30 8c 3f 00 66
    0000560 05 01 00 00 00 07 00 00 00 01 5a 00 00 8a 53 00
    0000600 08 40 b7 3c b2 01 05 0a 2d 92 00 20 bf d0 00 54
    0000620 e0 80 3f 80 00 72 00 23 20 77 00 00 33 01 48 00
    0000640 e7 67 00 01 05 00 01 01 61 06 01 3f 60 0a 01 25
    0000660 00 f3 40 bc 01 77 70 01 21 00 e0 c6 18 80 00 88
    0000700 3e ec 0a 40 e0 77 61 00 a1 42 00 01 77 07 00 00
    0000720 00 02 00 fe 2c 00 01 00 fc 00 01 89 a0 e3 a0 00
    0000740 3f c0 0a 65 40 9a 58 60 0e 60 cd 01 a0 06 88 80
    0000760 0a 94 07 26 00 00 08 10 08 10 00 00 10 f9 18 46
    0001000 30 80 61 6c 30 fc e2 00 e2 1b 48 52 e7 02 90 05
    0001020 00 33 00 fe e0 07 47 83 f0 00 2b 38 00 02 00 42
    0001040 00 60 20 40 00 10 7c 1b 60 7c d1 00 00 0a 01 0b
    0001060 01 2b 81 98 00 27 30 10 7e 60 62 00 01 70 01 00
    0001100 20 00 00 00 00 00 00 00 80 3c c1 ff 3c bc e0 01
    0001120 61 00 e3 01 7c 00 36 07 01 8e 9f 06 0b 01 30 00
    0001140 80 0c 00 00 08
    0001145

    Beste Grüße
    shepart

    Antwort
    • diefenbecker
      23. März 2016 um 18:16
      Permalink

      Hallo,

      das “cat” läuft eigentlich weiter bis es manuell abgebrochen wird. Ist Dein Lesekopf korrekt befestigt?
      Der Datenstrom schaut auch irgendwie seltsam aus. Bei mir fängt das immer mit “1b 1b 1b 1b …” an.

      Gruß
      Chris

      Antwort
  • 25. März 2016 um 12:12
    Permalink

    Hi Chris,

    nun sieht es besser aus. Die Arrays werden ordentlich gefüllt außer eins.

    [0100100700FF] => Array
    (
    [objName] => 0100100700FF
    [status] =>
    [valTime] =>
    [unit] => Wh
    [scaler] => 0
    [value] => 300
    [valueSignature] =>
    )

    PHP Notice: Undefined index: 01000F0700FF in /data/pi/strom/sml.php on line 28

    Grüße
    shepart

    Antwort
    • 7. April 2016 um 20:22
      Permalink

      würde mich über Feedback freuen, vielleicht hast du meine letzte Nachricht überlesen ?

      grüße
      shepart

      Antwort
      • diefenbecker
        10. April 2016 um 09:18
        Permalink

        Guten Morgen,

        Entschuldigung für die verspätete Antwort. Viel Arbeit, wenig Zeit…

        Bekommst Du im Debug-Modus vor der CRC-Prüfung etwas sinnvolles für diese Adresse zurück?
        Unterstützt Dein Zähler diese Adresse überhaupt? Es müsste irgendwas mit “Active Power” sein.
        Wenn Du alle benötigten Werte hast, schmeiß die Adresse aus der Liste raus.

        Gruß
        Chris

        Antwort
  • 18. April 2016 um 05:36
    Permalink

    Hey,
    ich wollte nur mal in die Runde werfen, das ich ein ähnliches Problem mit dem DEBUG-Modus hatte, im Debug-Modus waren alle Werte vorhanden, und dann am Ende des scriptes kam der “PHP Notice: Undefined index”- oder das “Array ist leer” Fehler.

    Mir ist aufgefallen das mein EHZ-Zähler ein verkürztes “END-Feld” im sml ticket hat.
    Der sml_parser wartet oder sucht nacht “0000001B1B1B1B1A” während mein EHZ folgendes liefert: “001B1B1B1B1A”

    Im sml_parser.php müssen entsprechend 2 Zeilen angepasst werden:
    Zeile 388 (original) = $sml_footer=’0000001B1B1B1B1A’;
    Zeile 388 (neu) = $sml_footer=’001B1B1B1B1A’;

    und

    Zeile 405 (original) = while($this->data” && substr($this->data,0,16)!=$sml_footer) {
    Zeile 405 (neu) = while($this->data” && substr($this->data,0,12)!=$sml_footer) {

    Ich hoffe das hilft ein paar Leuten weiter 🙂

    Gruss,
    Chris

    Antwort
  • 20. Juni 2016 um 11:54
    Permalink

    Hallo Chris,
    es ist ein schöner Artikel. ich bin gerade bei der Project angekommen, aber ich habe ein Paar Problem bekommen.
    ich habe Q3C versucht auszulesen, aber ich bekomme eines leeres Array und ein Fehlermeldung zu den Valuelist.
    und zwar folgendes : error reading value list
    Invalid argument supplied for foreach() in sml parser php o line 454

    wie aktiviere ich den Debug-modus?
    und wo liegt genau die Fehler?
    weil ich mich den PHP Script nicht so gut auskenne.

    Grüße Deva

    Antwort
  • 22. Juli 2016 um 00:14
    Permalink

    Hallo,

    in sml_parser.php sollte in readListEntry() die mit case ‘1B’ beginnende Zeile mit einem break abgeschlossen werden, damit das Feld “unit” bei der Wirkleistung (Active Power) die richtige Einheit (W für Watt) bekommt.

    Gruss, Hannes

    Antwort
  • 15. Januar 2017 um 08:45
    Permalink

    Hallo,
    sehr, sehr schönes Projekt!
    Nur eine Frage hab ich..
    Wie hast du da SQL-Abfrage gestaltet um die zwei gezeigten Diagramme zu erhalten?
    Bin leider nicht so SQL-Affin und tu mich hier etwas schwer. Vielleicht könntest du mir ein Beispiel zukommen lassen?

    Gruß

    alex

    Antwort
    • diefenbecker
      15. Januar 2017 um 14:08
      Permalink

      Hi Alex,

      das sind eigentlich 4 Diagramme, da beim unteren in meiner Ansicht drei Graphen rotiert werden.
      Diese berechne ich auch per Cron im Hintergrund alle x Minuten, da die Abfrage sonst zu lange dauert. Der Wirkverbrauch wird oft berechnet.

      //täglicher Verbrauch
      SELECT max(zaehlerstand)-min(zaehlerstand),dayname(timestamp) FROM stromzaehler WHERE DATE(timestamp) >= DATE_SUB(NOW(),INTERVAL 7 DAY) GROUP BY day(timestamp) ORDER BY timestamp

      //monatlicher Verrbauch
      SELECT max(zaehlerstand)-min(zaehlerstand),monthname(timestamp) FROM stromzaehler WHERE DATE(timestamp) >= DATE_SUB(NOW(), INTERVAL 13 MONTH) GROUP BY year(timestamp), month(timestamp) ORDER BY year(timestamp) asc, month(timestamp)

      //jährlicher Verbrauch
      SELECT max(zaehlerstand)-min(zaehlerstand), year(timestamp) FROM stromzaehler WHERE DATE(timestamp) >= DATE_SUB(NOW(), INTERVAL 10 YEAR) GROUP BY year(timestamp) ORDER BY year(timestamp) ASC

      //Wirkleistung
      SELECT active_power,hour(timestamp)FROM stromzaehler WHERE DATE_ADD(timestamp, INTERVAL 48 HOUR) >= NOW()

      Gruß
      Chris

      Antwort
      • 15. Januar 2017 um 14:12
        Permalink

        Hi Chris,

        Dankeschön, das probier ich gleich mal aus!
        Sehr cooler Blog! Da wurden ja schon einige spannenden Sachen umgesetzt! Bin begeistert!

        Gruß

        Alex

        Antwort
  • Pingback: Odroid C2 – Update 1 (Gas- und Wasserzähler) – bubuxblog

  • 13. Februar 2017 um 12:42
    Permalink

    Hi,

    ich möchte meinen Digitalen Stromzähler auch gerne auslesen und die Daten speichern, leider habe ich nicht viel Erfahrung in dem Bereich.

    Ich habe ein Zweirichtungszhler eHZ-IW8E… (EMH00)

    Als Tastkopf habe ich mir den von Volkszähler.org besorgt.

    Meine Versuche scheitern wenn ich folgende Abfrage mache.

    sudo php /var/www/strom/sml.php

    Error reading value-list!Error reading value-list!Error reading value-list!Error reading value-list!Error reading value-list!PHP Notice: Undefined index: 0100010801FF in /var/www/strom/sml.php on line 26
    PHP Notice: Undefined index: 0100010801FF in /var/www/strom/sml.php on line 26
    PHP Notice: Undefined index: 8181C78205FF in /var/www/strom/sml.php on line 27
    PHP Notice: Undefined index: 01000F0700FF in /var/www/strom/sml.php on line 28

    Kann mir jemand auf die Spünge helfen, über cat /dev/ttyUSB0 | od -tx1
    bekomme ich folgende Daten.

    cat /dev/ttyUSB0 | od -tx1
    0000000 01 f6 55 1b 1b 1b 1b 01 01 01 01 76 07 00 09 00
    0000020 d6 a1 4b 62 00 62 00 72 63 01 01 76 01 01 07 00
    —schnipp—

    Antwort
    • 15. Februar 2017 um 13:28
      Permalink

      Hi,

      bin etwas weiter gekommen, habe jetzt nur noch einen Fehler wo ich leider nicht weiter komme.

      pi@raspberrypi:/var/www/strom/data$ sudo /home/pi/bin/read-strom-data.sh
      ‘/dev/ttyUSB0’ -> ‘/var/www/strom/data/serialin_20170215132224.txt’
      PHP Notice: Undefined index: 01000F0700FF in /var/www/strom/sml.php on line 28

      Für Lösungsvorschläge wäre ich dankbar.

      Antwort
      • diefenbecker
        17. Februar 2017 um 17:00
        Permalink

        Hallo Helge,

        entschuldige die späte Antwort aber ich war ein paar Tage unterwegs.
        Hast Du auch den Debugmodus der sml-Klasse mal genutzt und den Check der Prüfsumme mal deaktiviert (siehe Ende des Artikels http://blog.bubux.de/raspberry-pi-ehz-auslesen/)?
        Das SML schaut auf den ersten Blick HEX-mäßig erstmal gut aus (ich war so frei und hab den dump etwas eingekürzt).

        Gruß
        Chris

        Antwort
  • 15. Februar 2017 um 20:44
    Permalink

    Hallo,
    Ihr Tutorial hat mit bis jetzt sehr geholfen.
    Doch leider werden nur sehr selten die Daten richtig in das Array geladen (Fehlerquote: ~95%).
    Es endet immer mit folgender Fehlermeldung:
    “PHP Notice: Undefined index: 0100010801FF in /var/…/sml.php on line 33

    Leider weiß ich nicht, wie ich die Fehlermeldungen über Putty aus dem Raspberry herausbekommen soll…

    Bitte um Hilfe.

    Mit freundlichen Grüßen
    Tobias Wälde

    Antwort
    • diefenbecker
      17. Februar 2017 um 16:56
      Permalink

      Hallo Tobias,

      unterstützt Dein Zähler diese Adresse (0100010801FF) und hast Du die Berechnung der Prüfsumme (siehe Ende des Artikels http://blog.bubux.de/raspberry-pi-ehz-auslesen/) mal deaktiviert? Werden im Debugmodus der sml-Klasse die Werte korrekt ausgelesen? Ist aber schon seltsam das es manchmal geht aber meistens nicht.
      Das mit der Fehlermeldung über PuTTY herausbekommen verstehe ich leider nicht. Was meinst Du damit?

      Gruß
      Chris

      Antwort
  • 19. März 2017 um 10:21
    Permalink

    Hallo,

    habe einen EHM Zähler habe mir auch den Lesekopf besorgt alle angeschlossen und
    cat /dev/ttyUSB2 | od -tx1
    zeigt folgendes abgekürzt an
    0000000 ff 01 01 65 03 ba 8b d8 01 01 83 02 4f d5 e0 cb
    0000020 87 47 e7 39 63 4b 70 ea 31 19 d6 b5 f6 ea 71 b6
    0000040 67 44 79 8e 77 75 01 63 00 76 0e 6e 62 02 01 00
    0000060 1b 1b 06 ad 1b 1b 01 01 01 01 76 07 00 0e 09 2f
    0000100 6e 44 62 00 62 00 72 63 01 01 76 01 01 07 00 0e
    0000120 03 ba cf 6c 0b 09 01 45 4d 48 00 00 49 5e a9 01
    0000140 01 63 1f a2 00 76 07 00 0e 09 2f 6e 45 62 00 62
    0000160 00 72 63 07 01 77 01 0b 09 01 45 4d 48 00 00 49
    0000200 5e a9 07 01 00 62 0a ff ff 72 62 01 65 03 ba 8b
    0000220 dc 77 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45
    0000240 4d 48 01 77 07 01 00 00 00 09 ff 01 01 01 01 0b
    0000260 09 01 45 4d 48 00 00 49 5e a9 01 77 07 01 00 01
    0000300 08 00 ff 64 00 01 82 01 62 1e 52 ff 56 00 03 45
    0000320 78 33 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52
    0000340 ff 56 00 03 45 50 2b 01 77 07 01 00 01 08 02 ff
    0000360 01 01 62 1e 52 ff 56 00 00 00 28 08 01 77 07 01
    0000400 00 10 07 00 ff 01 01 62 1b 52 ff 55 00 00 03 e5
    0000420 01 77 07 81 81 c7 82 05 ff 01 72 62 01 65 03 ba
    0000440 8b dc 01 01 83 02 4f d5 e0 cb 87 47 e7 39 63 4b
    0000460 70 ea 31 19 d6 b5 f6 ff 0a d7 88 ea 1c a1 96 71
    0000500 73 f0 9a b6 5e 1e 67 51 fa 6c 44 b9 3e d4 79 c7
    0000520 99 8e 1b 20 77 75 01 01 01 63 0c 98 00 76 07 00
    beim versuch dann mit sml.php das in die Datenbank zu schreiben
    klappt es fast nie
    „/dev/ttyUSB2“ -> „/var/www/html/Strom/data/serialin_20170319101715.txt“
    serialin_20170319101715.txtDEBUG: ‘ENTER parse_sml_message’ : 7607000E092F700C620062007263010176010107000E03BAD0040B0901454D480000495EA90101638686007607000E092F700D620062007263070177010B0901454D480000495EA9070100
    DEBUG: ‘PROCESS OpenRequest’ : 76010107000E03BAD0040B0901454D480000495EA90101638686007607000E092F700D620062007263070177010B0901454D480000495EA9070100620AFFFF7262016503BA8C6877770781
    DEBUG: ‘EXIT parse_sml_message. CRC=OK’
    DEBUG: ‘——————————–‘
    DEBUG: ‘ENTER parse_sml_message’ : 7607000E092F700D620062007263070177010B0901454D480000495EA9070100620AFFFF7262016503BA8C687777078181C78203FF0101010104454D480177070100000009FF010101010B
    DEBUG: ‘PROCESS GetListResponse’ : 77010B0901454D480000495EA9070100620AFFFF7262016503BA8C687777078181C78203FF0101010104454D480177070100000009FF010101010B0901454D480000495EA9017707010001
    DEBUG: ‘ENTER readValList’ : 7777078181C78203FF0101010104454D480177070100000009FF010101010B0901454D480000495EA90177070100010800FF6400018201621E52FF56000345794E0177070100010801FF01
    DEBUG: ‘ENTER readListEntry [0]’ : 77078181C78203FF0101010104454D480177070100000009FF010101010B0901454D480000495EA90177070100010800FF6400018201621E52FF56000345794E0177070100010801FF0101
    DEBUG: ‘ENTER readListEntry [1]’ : 77070100000009FF010101010B0901454D480000495EA90177070100010800FF6400018201621E52FF56000345794E0177070100010801FF0101621E52FF56000345514601770701000108
    DEBUG: ‘ENTER readListEntry [2]’ : 77070100010800FF6400018201621E52FF56000345794E0177070100010801FF0101621E52FF5600034551460177070100010802FF0101621E52FF5600000028080177070100100700FF01
    DEBUG: ‘ENTER readListEntry [3]’ : 77070100010801FF0101621E52FF5600034551460177070100010802FF0101621E52FF5600000028080177070100100700FF0101621B52FF550000212D0177078181C78205FF0172620165
    DEBUG: ‘ENTER readListEntry [4]’ : 77070100010802FF0101621E52FF5600000028080177070100100700FF0101621B52FF550000212D0177078181C78205FF017262016503BA8C68010183024FD5E0CB8747E739634B70EA31
    DEBUG: ‘ENTER readListEntry [5]’ : 77070100100700FF0101621B52FF550000212D0177078181C78205FF017262016503BA8C68010183024FD5E0CB8747E739634B70EA3119D6B5F6FF0AD788EA1CA1967173F09AB65E1E6751
    DEBUG: ‘ENTER readListEntry [6]’ : 77078181C78205FF017262016503BA8C68010183024FD5E0CB8747E739634B70EA3119D6B5F6FF0AD788EA1CA1967173F09AB65E1E6751FA6C44B93ED479C7998E1B20777501010163D55A
    DEBUG: ‘EXIT readValList : Array
    (
    [0] => Array
    (
    [objName] => 8181C78203FF
    [status] =>
    [valTime] =>
    [unit] =>
    [scaler] => 0
    [value] => EMH
    [valueSignature] =>
    [OBIS] => 129-129:199.130.3*255
    [OBIS-Text] => Hersteller-ID
    )

    [1] => Array
    (
    [objName] => 0100000009FF
    [status] =>
    [valTime] =>
    [unit] =>
    [scaler] => 0
    [value] => 0901454D480000495EA9
    [valueSignature] =>
    [OBIS] => 1-0:0.0.9*255
    [OBIS-Text] => Geraeteeinzelidentifikation
    )

    [2] => Array
    (
    [objName] => 0100010800FF
    [status] => 000182
    [valTime] =>
    [unit] => Wh
    [scaler] => 0.1
    [value] => 54884686
    [valueSignature] =>
    [OBIS] => 1-0:1.8.0*255
    [OBIS-Text] => Wirkarbeit Bezug Total: Zaehlerstand
    )

    [3] => Array
    (
    [objName] => 0100010801FF
    [status] =>
    [valTime] =>
    [unit] => Wh
    [scaler] => 0.1
    [value] => 54874438
    [valueSignature] =>
    [OBIS] => 1-0:1.8.1*255
    [OBIS-Text] => Wirk-Energie Tarif 1 Bezug
    )

    [4] => Array
    (
    [objName] => 0100010802FF
    [status] =>
    [valTime] =>
    [unit] => Wh
    [scaler] => 0.1
    [value] => 10248
    [valueSignature] =>
    [OBIS] => 1-0:1.8.2*255
    [OBIS-Text] => Wirk-Energie Tarif 2 Bezug
    )

    [5] => Array
    (
    [objName] => 0100100700FF
    [status] =>
    [valTime] =>
    [unit] => Wh
    [scaler] => 0.1
    [value] => 8493
    [valueSignature] =>
    )

    [6] => Array
    (
    [objName] => 8181C78205FF
    [status] =>
    [valTime] => 72
    [unit] =>
    [scaler] => 0
    [value] => 4FD5E0CB8747E739634B70EA3119D6B5F6FF0AD788EA1CA1967173F09AB65E1E6751FA6C44B93ED479C7998E1B207775
    [valueSignature] =>
    [OBIS] => 129-129:199.130.5*255
    [OBIS-Text] => Public-Key
    )

    )

    DEBUG: ‘EXIT parse_sml_message. CRC=OK’
    DEBUG: ‘——————————–‘
    DEBUG: ‘ENTER parse_sml_message’ : 7607000E0901651B1B010101017607000E092F7018620062007263010176010107000E03BAD0080B0901454D480000495EA90101639201007607000E092F7019620062007263070177010B
    DEBUG: ‘PROCESS UnknownRequest ()’ : 01017607000E092F7018620062007263010176010107000E03BAD0080B0901454D480000495EA90101639201007607000E092F7019620062007263070177010B0901454D480000495EA907
    DEBUG: ‘EXIT parse_sml_message. CRC=FAIL’
    DEBUG: ‘——————————–‘
    PHP Notice: Undefined index: 0100010801FF in /var/www/html/Strom/sml.php on line 30
    PHP Notice: Undefined index: 0100010801FF in /var/www/html/Strom/sml.php on line 30
    PHP Notice: Undefined index: 0100100700FF in /var/www/html/Strom/sml.php on line 33

    Habe so ziemlich alles ausprobiert auch was hier in den Kommentaren zu finden war.
    Ohne erfolg hat einer vielleicht auch so ein Problem gehabt und weiß eine lösung.
    Ich habe den Zähler mit der PIN freigeschaltet so das ich mit der Taschenlampe den Tagesverbrauch Jahres und so weiter anzeigen kann, ob es daran liegt?

    Vielen Dank vorab

    Antwort
    • 22. März 2017 um 21:09
      Permalink

      stty -F /dev/ttyUSB0 9600 -parity -cstopb

      hat mir geholfen funktioniert jezt einwandfrei.

      Antwort
  • 28. März 2017 um 08:31
    Permalink

    Hallo zusammen,
    die 0100100700FF ist die Wirkleistung, Unit ist “W” , diese hat sich geändert. Die ersten Zähler haben hier “0F 07” , jétzt “10 07” , also sollte ein universelles Skript beides können.

    Antwort
  • 24. April 2017 um 22:33
    Permalink

    Hallo,

    hat jemand noch eine genauere Anleitung.

    Ich habe vor allem Probleme bei Mysql.

    Wer kann mir da helfen?

    Danke und viele Grüße
    Marcel Jaud

    Antwort
      • 25. April 2017 um 19:15
        Permalink

        Nicht wirklich ein Plan von mysql.
        Erstellen der Tabelle, auch das weiterverarbeiten wird mir Probleme bereiten.
        Ich glaube ich schreibe es in eine Textdatei.
        Hat dazu jemand ne Hilfe für mich?

        Antwort
  • 28. April 2017 um 09:42
    Permalink

    Hallo,

    ich bin jetzt soweit das ich den Zählerstand in eine Textdatei geschreieben bekomme.

    Jedoch funktioniert das nicht jeder Aufruf:

    2017-04-28 10:10:11;0
    2017-04-28 10:12:11;0
    2017-04-28 10:14:10;0
    2017-04-28 10:16:10;54213.7221
    2017-04-28 10:18:11;0
    2017-04-28 10:20:11;0
    2017-04-28 10:22:11;0
    2017-04-28 10:24:09;54213.7647
    2017-04-28 10:26:09;0
    2017-04-28 10:28:09;0
    2017-04-28 10:30:10;0
    2017-04-28 10:32:09;0
    2017-04-28 10:34:11;0

    Kann sich jemand vorstellen woran das hängt?
    Prüfsumme ist auskomentiert.

    SML sieht auch gut aus.

    cat /dev/ttyUSB0 | od -tx1
    0000000 76 14 72 01 07 6e 00 8c 14 4b 62 00 62 00 07 00
    0000020 ba 70 1b 1b 1b 1b 01 01 01 01 76 07 00 2a 00 8c
    0000040 14 4d 62 00 62 00 72 63 01 01 76 01 01 07 00 2a
    0000060 0c 6a 30 33 32 34 33 31 01 01 76 4e 63 07 39 30
    0000100 33 72 81 77 01 1e 52 60 60 01 01 32 32 77 00 52
    0000120 ff 55 00 00 10 a3 01 01 01 01 01 01 76 07 00 2a
    0000140 00 8c 14 50 62 00 62 00 62 00 62 77 01 30 30 31
    0000160 6a 01 04 00 0d 30 31 00 01 00 20 07 00 01 9c 01
    0000200 00 76 07 62 00 72 63 3b 1a 1b 76 14 72 01 71 30
    0000220 30 31 08 1e 50 60 91 01 77 07 00 00 60 01 ff ff
    0000240 01 01 01 01 0b 77 55 01 63 2a 00 01 63 1b 1b 72
    0000260 2d 75 ff 62 ff 56 77 07 ff 0b 30 36 77 07 ff 01
    0000300 00 63 00 2a 62 00 01 1b cc 01 2a 00 62 01 00 01
    0000320 36 01 07 14 5b 63 81 1b 1b 1b 76 07 00 62 01 00
    0000340 0d 77 07 01 1e 52 50 00 00 01 32 34 01 77 07 01
    0000360 00 8a 1a 01 be ee 1b 1b 1b 1b 01 01 01 01 76 07
    0000400 00 2a 00 8c 00 72 01 0d 31 39 30 30 30 30 31 76
    0000420 14 60 62 30 33 31 01 77 07 00 0d 31 30 33 32 34

    Manchmal sieht der Aufruf gut aus. Meinstens treten aber folgende Fehler auf:

    sudo bash entschluesseln.sh
    „/dev/ttyUSB0“ -> „/var/www/strom/data/serialin_20170428104022.txt“
    Array
    (
    )
    PHP Notice: Undefined index: 0100010801FF in /var/www/strom/sml.php on line 26
    PHP Notice: Undefined index: 0100010801FF in /var/www/strom/sml.php on line 26
    Die Datei stromverbrauch_gokestr wurde gespeicher
    entschluesseln.sh: Zeile 25: 28508 Beendet cp -v /dev/ttyUSB0 ${datapath}serialin${fileext}

    Wer kann mir helfen?

    Viele Grüße
    Marcel Jaud

    Antwort
  • 19. Mai 2017 um 08:18
    Permalink

    Hallo,

    erstmal ein herzliches Dankeschön an Chris, Udo und sämtliche anderen Mitwirkenden. Mit eurer Hilfe (und Hardware 😉 war mein RasPi mit Volkszähler in weniger als 2 Stunden aufgesetzt und logged die Zählerstände in mySQL.

    Da ich noch ein paar Kleinigkeiten an den beiden Scripten verändert habe, wollte ich hier noch kurz meine Änderungen durchgeben – evtl hilft’s ja dem ein oder anderen.

    Ich habe einen ISKRA MT681-D4A52, der wg PV-Anlage, in zwei Richtungen zählt. Daher habe ich

    1. das sml_parser Script um ein paar Einträge im obis_arr erweitert:

    ….

    ‘0100020800FF’ => array(‘1-0:2.8.0*255′,’Wirkarbeit Lieferung Total: Zaehlerstand’), #https://www.bundesnetzagentur.de/DE/Service-Funktionen/Beschlusskammern/Beschlusskammer6/BK6_31_GPKE_und_GeLiGas/Mitteilung_Nr_20/Anlagen/Obis-Kennzahlen-System_2.0.pdf?__blob=publicationFile&v=2
    ‘0100100700FF’ => array(‘1-0:16.7.0*255′,’Aktuelle Gesamtwirkleistung’), #https://www.photovoltaikforum.com/volkszaehler-org-f131/problem-mit-obis-16-7-0-aktuelle-wirkleistung-t111093.html
    ‘0100240700FF’ => array(‘1-0:36.7.0*255′,’Aktuelle Gesamtwirkleistung (P+ – P-) in der Phase L1, Einheit: W’),
    ‘0100380700FF’ => array(‘1-0:56.7.0*255′,’Aktuelle Gesamtwirkleistung (P+ – P-) in der Phase L2, Einheit: W’),
    ‘01004C0700FF’ => array(‘1-0:76.7.0*255′,’Aktuelle Gesamtwirkleistung (P+ – P-) in der Phase L3, Einheit W’),
    ….

    2. wg möglicher negativer Gesamtwirkleistung die Funktion parse_sml_data für Integer erweitert, so dass auch negative Werte zurückgegeben werden:

    ….
    case ‘5x’: # Integer
    //siehe http://php.net/manual/en/function.hexdec.php
    $hex = $this->read($LEN-1);
    // converted decimal value:
    $dec = hexdec($hex);
    // maximum decimal value based on length of hex + 1:
    // number of bits in hex number is 8 bits for each 2 hex -> max = 2^n
    // use ‘pow(2,n)’ since ‘1 < $_dec ? -$_dec : $dec;

    // return hexdec($this->read($LEN-1));
    break;
    ….

    Mein Zähler gibt die aktuelle Wirkleistung übrigens bei OBIS 1-0:16.7.0*255 also ‘0100100700FF’ aus, daher habe ich auch das sml.php dahingegen anpassen müssen.

    Nochmal vielen Dank für die Anleitungen, Tips und Tricks

    Viele Grüße
    Jan

    Antwort
    • 3. Juni 2017 um 14:53
      Permalink

      Hi Jan,

      I just want to give a quick “thanks” for sharing the info about the negative values!

      The formatting of your comment got messed up, but the reference to the comment on the PHP.net manual website was helpful.

      Antwort
  • 6. Juni 2017 um 08:51
    Permalink

    Hallo,

    die Scripte sind anscheinend nicht php7 kompatibel.
    Ist ein Update geplant ?

    lg

    Antwort
  • 6. Oktober 2017 um 20:08
    Permalink

    Hallo Chris,
    vielen Dank für die schöne Anleitung.
    Leider habe ich das Problem, dass mein LOGAREX-Zähler erst Daten ausgibt, wenn ich ihn per
    echo -n -e ‘\x2F\x3F\x21\x0D\x0A’ > /dev/ttyUSB0
    dazu auffordere.
    Nun habe ich genau das in dein Script direkt unter dem cp -v … eingebaut. Aber die ausgegebene Datei ist nur 8 Zeichen groß. Auch wenn ich bis zum kill nicht nur 10 Sekunden warte, sondern länger.
    Die Datei beinhaltet konkret: !^M^F000^M
    Eigentlich sollte aber folgender output entstehen, der auch kommt, wenn ich cat /dev/ttyUSB0 in einem Terminal eingebe und dann den o.g. echo in einem weiteren Terminal absetze:
    /?!
    /LOG4LK13BD102015
    000
    C.1.0(06009099)
    0.0.0(1LOG0006009099)
    F.F(0000)
    1.8.0(017437.002*kWh)
    C.7.1(00000000)
    C.7.2(00000000)
    C.7.3(00000000)
    0.2.1(ver.02, 130314, 41BD)
    C.2.1(1408081426)
    C.2.9(1408081426)
    !

    Der Inhalt der .txt-Datei sieht ja aus wie die dritte zeile aus dem konsolen output …

    Bricht cat evtl. durch irgendeine binäre Zeichenfolge, die der Zähler sendet, ab? Oder was könnte sonst die Ursache sein?

    Viele Grüße
    Frank

    Antwort
    • diefenbecker
      8. Oktober 2017 um 09:20
      Permalink

      Hallo Frank

      gute Frage?! Was passiert denn bei “cat -v” oder “od -c”?
      Gibt der Zähler SML aus? Ich hätte Hex erwartet mit 1b1b1b.. als Startsequenz

      Gruß
      Chris

      Antwort
      • 8. Oktober 2017 um 11:16
        Permalink

        Hallo Chris,
        der LOGAREX redet offenbar d0. Jedenfalls wenn ich ihn mit 2F 3F 21 0D 0A anspreche.

        Inzwischen konnte ich das Problem aber anderweitig lösen. Ich fand ein Python Script, das ich ein wenig angepasst habe: https://www.domoticz.com/forum/viewtopic.php?f=14&t=5270#p34344
        Den ganzen domoticz kram habe ich rausgeworfen und auch die Teile, die sich mit der Kennzahl 2.8.0 befassen. Dann das ganze noch auf den LOGAREX angepasst und es läuft. Jetzt werde ich noch eine kleine json Ausgabe implementierten und dann kann ich die Werte in meiner openhab Zentrale abgreifen.

        Dennoch würde mich interessieren, warum das über das bash Script nicht klappt.

        Viele Grüße und vielen Dank schonmal
        Frank

        Antwort
  • 30. Dezember 2017 um 13:59
    Permalink

    hey chris,

    mein MT681-D4A51-K0p zeigt mit dem script die korrekten werte an (nachdem auskommentieren vom “crcMsgCheck”). danke für die arbeit!

    Antwort
  • 19. Mai 2018 um 15:03
    Permalink

    Hallo Chris…

    Könntest du erklären was die Zeile:

    stty -F /dev/ttyUSB0 1:0:8bd:0:3:1c:7f:15:4:5:1:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0

    in der Schnittstelle genau einstellt? Ohne diese hat bei mir keine Ausgabe sauber funktioniert. Erst als ich die Schnittstelle so eingestellt habe, kommt ein korrekter Output…

    Antwort
    • diefenbecker
      20. Mai 2018 um 09:31
      Permalink

      Hallo,

      das sind die Parameter zur Kommunikation (Baudrate, Parität, Stoppbit, …) mit dem Lesekopf in “stty-Schreibweise”. Du kannst das mit stty -a in einer lesbaren Form wieder auslesen.

      Gruß
      Chris

      Antwort
  • 1. Oktober 2018 um 14:36
    Permalink

    Hallo Chris,

    ich habe eine Frage zu der sml_parser-Klasse.

    Die Klasse wird auch von Wörsty in seinem Plugin im loxberry Image verwendet. Allerdings funktioniert das Parsen des Datenstrom des Zählers ISKRA MT691 nicht. Im Logfile findet man: Buffer:
    ERROR: ’00’ expected, got ‘650004D5136201634CC8007605000E84D16200620072630701…’ !
    Kann mir da jemand weiterhelfen?

    Antwort
  • 10. Oktober 2018 um 12:04
    Permalink

    Hallo
    Funtkioniert das auch mit diesen Stromzähler?
    [Link geöscht]

    Danke
    im vorraus
    lg
    Martin

    Antwort
    • diefenbecker
      13. Oktober 2018 um 09:25
      Permalink

      Hallo Martin,

      ich kann Dir leider nicht sagen ob das mit diesem Zähler funktioniert. In der Beschreibung steht nichts von SML. Und was genau “S0 gemäß DIN 43864” so ausgibt kann ich leider auch nicht sagen.

      Gruß
      Chris

      Antwort
  • 14. November 2018 um 12:06
    Permalink

    Super Programm, habe das zunächst über die Kommandozeile getestet mit ISKRA MT681. Leider gibt der bei mir nur Leistung Bezug, Leistung Rückspeisung und den Key aus.
    Bekomme daher für die anderen Werte Meldungen wie:
    Uninitialized string offset:……… aus dem Parser
    und
    Undefined index …………..
    aus sml.php
    Nach meiner Erfahrung sollte im den PHP-Programmen oben noch die Shebang-Zeile stehen, zumindest bei meinem System (#!/usr/bin/php).
    Wäre schön, wenn jemand eine Lösung für den ISKRA hätte.

    Antwort

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.