[vz-dev] vzlogger: wieder ein bug im d0-parser
Thorben Thuermer
r00t at constancy.org
Thu Jan 10 23:01:30 CET 2013
Hallo,
habe gerade mit einem user im irc einen neuen bug in vzlogger analysiert.
das problem ist, das fuer einen d0-zaehler (Elster A1350) immer zwei
verschiedene werte zusammen auf den kanal geloggt wurden.
der korrekte, und ein anderer, der eigentlich eine andere OBIS-id hat.
die analyse ergab dann:
der zaehler sendet am anfang des telegramms:
0000000: 2f41 4242 345c 4056 352e 3230 2039 3036 /ABB4\@V5.20 906
0000010: 3036 3839 330d 0a02 3332 2e37 2e30 2832 06893...32.7.0(2
d.h. die start-zeile, dann \r\n (0x0d, 0x0a), dann ein byte: 0x02,
und erst dann die ascii-ziffern der ersten obis-ID.
0x02 ist laut doku des zaehlerherstellers in "<STX>" "start of text" marker.
das problem ist nun, das vzlogger davon nix weiss, und dieses byte zur
obis-id zaehlt:
src/protocols/d0.c:
204 case IDENTIFICATION: /* IDENTIFICATION has 16 bytes */
205 if (byte == '\r' || byte == '\n') { /* detect line end */
207 context = OBIS_CODE; /* set new context: IDENTIFICATION -> OBIS_CODE */
215 case OBIS_CODE:
216 if ((byte != '\n') && (byte != '\r'))
218 if (byte == '(') {
222 context = VALUE;
223 }
224 else obis_code[byte_iterator++] = byte;
254 case END_LINE:
258 print(log_debug, "Parsed reading (OBIS code=%s, value=%s, unit=%s)", mtr, obis_code, value, unit);
260 obis_parse(obis_code, &rds[number_of_tuples].identifier.obis);
dies ergibt dann in strace die schoene ausgabe:
[pid 5124] write(1, "[Jan 10 21:27:04][mtr0] Parsed reading (OBIS code=\00232.7.0, value=237.3, unit=V)\n", 80) = 80
(man beachte das \002, das in einem terminal wohl einfach verschwinden wuerde)
und weiter:
src/obis.c:
106 int obis_parse(const char *str, obis_id_t *id) {
121 for (int i = 0; i < len; i++) {
122 byte = str[i];
124 if (isdigit(byte)) {
127 else {
128 if (byte == '-' && field < A) { /* end of field A */
140 else {
141 return ERR;
d.h., wenn das erste byte auf nix matcht (was bei 0x02 vorkommt),
dann schreibt obis_parse nix in den rueckgabepuffer und liefert ERR zurueck,
aber wie wir oben sehen:
src/protocols/d0.c:
260 obis_parse(obis_code, &rds[number_of_tuples].identifier.obis);
wird der rueckgabewert ignoriert!
wir haben jetzt also nicht initialisierte daten fuer den obis-identifier...!
und im fall dieses users waren diese daten immer 0xff, bzw. 255:
[mtr0] Reading: id=255-255:255.255.255*255 value=237.30 ts=1357849624.292"
weiter dann:
src/threads.c
82 /* insert readings into channel queues */
83 foreach(mapping->channels, ch, channel_t) {
88 if (reading_id_compare(mtr->protocol, rds[i].identifier, ch->identifier) == 0) {
93 print(log_info, "Adding reading to queue (value=%.2f ts=%.3f)", ch, rds[i].value, tvtod(rds[i].time))
94 reading_t *rd = buffer_push(&ch->buffer, &rds[i]);
src/reading.c:
54 int reading_id_compare(meter_protocol_t protocol, reading_id_t a, reading_id_t b) {
56 case meter_protocol_d0:
58 return obis_compare(a.obis, b.obis);
src/obis.c:
177 int obis_compare(obis_id_t a, obis_id_t b) {
178 for (int i = 0; i < 6; i++) {
179 if (a.raw[i] == b.raw[i] || a.raw[i] == 0xff || b.raw[i] == 0xff ) {
180 continue; /* skip on wildcard or equal */
190 return 0; /* equal */
durch diese (etwas zweifelhafte?!) wildcard-logik matcht die fehlerhaft
geparsete id dann immer, und wird fuer jeden channel submitted!
soweit die analyse...
- Thorben
More information about the volkszaehler-dev
mailing list