From 11763b2f226c2842fa4c27b9f13075d246de7ba8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Sun, 17 Apr 2022 17:34:51 +0200 Subject: [PATCH] Refactor insert offset and key inside DVEntry add extractor methods to DVEntry. --- src/dvparser.cc | 69 ++++++++++++++++++++++--------------- src/dvparser.h | 19 ++++++----- src/meters.cc | 91 ++++++++++++++++++++++++++++--------------------- 3 files changed, 105 insertions(+), 74 deletions(-) diff --git a/src/dvparser.cc b/src/dvparser.cc index 55ff36b..a20a5ab 100644 --- a/src/dvparser.cc +++ b/src/dvparser.cc @@ -344,6 +344,11 @@ bool parseDV(Telegram *t, (*dv_entries_ordered).push_back( &(*dv_entries)[key].second ); + DVEntry *dve = (*dv_entries_ordered).back(); + DVEntry *dvee = &(*dv_entries)[key].second; + + assert(key == dve->dif_vif_key.str() && key == dvee->dif_vif_key.str()); + if (value.length() > 0) { // This call increments data with datalen. t->addExplanationAndIncrementPos(data, datalen, KindOfData::CONTENT, Understanding::NONE, "%s", value.c_str()); @@ -413,7 +418,6 @@ bool findKeyWithNr(MeasurementType mit, VIFRange vif_range, StorageNr storagenr, return false; } - void extractDV(DifVifKey &dvk, uchar *dif, uchar *vif) { string tmp = dvk.str(); @@ -832,21 +836,26 @@ bool extractDVHexString(map> *dv_entries, bool extractDVReadableString(map> *dv_entries, string key, int *offset, - string *value) + string *out) { if ((*dv_entries).count(key) == 0) { verbose("(dvparser) warning: cannot extract string from non-existant key \"%s\"\n", key.c_str()); *offset = -1; return false; } - uchar dif, vif; - extractDV(key, &dif, &vif); - int t = dif&0xf; - pair& p = (*dv_entries)[key]; *offset = p.first; - string v = p.second.value; + return p.second.extractReadableString(out); +} + +bool DVEntry::extractReadableString(string *out) +{ + uchar dif, vif; + extractDV(dif_vif_key, &dif, &vif); + int t = dif&0xf; + + string v = value; if (t == 0x1 || // 8 Bit Integer/Binary t == 0x2 || // 16 Bit Integer/Binary @@ -872,7 +881,7 @@ bool extractDVReadableString(map> *dv_entries, v = reverseBCD(v); } - *value = v; + *out = v; return true; } @@ -913,48 +922,54 @@ bool extractTime(uchar hi, uchar lo, struct tm *date) bool extractDVdate(map> *dv_entries, string key, int *offset, - struct tm *value) + struct tm *out) { if ((*dv_entries).count(key) == 0) { verbose("(dvparser) warning: cannot extract date from non-existant key \"%s\"\n", key.c_str()); *offset = -1; - memset(value, 0, sizeof(struct tm)); + memset(out, 0, sizeof(struct tm)); return false; } + pair& p = (*dv_entries)[key]; + *offset = p.first; + + return p.second.extractDate(out); +} + +bool DVEntry::extractDate(struct tm *out) +{ // This will install the correct timezone // offset tm_gmtoff into the timestamp. time_t t = time(NULL); - localtime_r(&t, value); - value->tm_hour = 0; - value->tm_min = 0; - value->tm_sec = 0; - value->tm_mday = 0; - value->tm_mon = 0; - value->tm_year = 0; + localtime_r(&t, out); + out->tm_hour = 0; + out->tm_min = 0; + out->tm_sec = 0; + out->tm_mday = 0; + out->tm_mon = 0; + out->tm_year = 0; uchar dif, vif; - extractDV(key, &dif, &vif); + extractDV(dif_vif_key, &dif, &vif); - pair& p = (*dv_entries)[key]; - *offset = p.first; vector v; - hex2bin(p.second.value, &v); + hex2bin(value, &v); bool ok = true; if (v.size() == 2) { - ok &= extractDate(v[1], v[0], value); + ok &= ::extractDate(v[1], v[0], out); } else if (v.size() == 4) { - ok &= extractDate(v[3], v[2], value); - ok &= extractTime(v[1], v[0], value); + ok &= ::extractDate(v[3], v[2], out); + ok &= ::extractTime(v[1], v[0], out); } else if (v.size() == 6) { - ok &= extractDate(v[4], v[3], value); - ok &= extractTime(v[2], v[1], value); + ok &= ::extractDate(v[4], v[3], out); + ok &= ::extractTime(v[2], v[1], out); // ..ss ssss int sec = (0x3f) & v[0]; - value->tm_sec = sec; + out->tm_sec = sec; // some daylight saving time decoding needed here.... } diff --git a/src/dvparser.h b/src/dvparser.h index dccfbc2..964f091 100644 --- a/src/dvparser.h +++ b/src/dvparser.h @@ -147,20 +147,23 @@ static IndexNr AnyIndexNr = IndexNr(-1); struct DVEntry { - int offset { 0 }; // Where in the telegram this dventry was found. - DifVifKey dif_vif_key { "" }; - MeasurementType measurement_type {}; - Vif vif { 0 }; - StorageNr storage_nr { 0 }; - TariffNr tariff_nr { 0 }; - SubUnitNr subunit_nr { 0 }; + int offset; // Where in the telegram this dventry was found. + DifVifKey dif_vif_key; + MeasurementType measurement_type; + Vif vif; + StorageNr storage_nr; + TariffNr tariff_nr; + SubUnitNr subunit_nr; std::string value; - DVEntry() {} DVEntry(int off, DifVifKey dvk, MeasurementType mt, Vif vi, StorageNr st, TariffNr ta, SubUnitNr su, std::string &val) : offset(off), dif_vif_key(dvk), measurement_type(mt), vif(vi), storage_nr(st), tariff_nr(ta), subunit_nr(su), value(val) {} + DVEntry() : + offset(999999), dif_vif_key("????"), measurement_type(MeasurementType::Instantaneous), vif(0), storage_nr(0), tariff_nr(0), subunit_nr(0), value("x") {} bool extractDouble(double *out, bool auto_scale, bool assume_signed); bool extractLong(uint64_t *out); + bool extractDate(struct tm *out); + bool extractReadableString(std::string *out); }; struct FieldMatcher diff --git a/src/meters.cc b/src/meters.cc index 72c7087..a7441ac 100644 --- a/src/meters.cc +++ b/src/meters.cc @@ -2076,28 +2076,31 @@ bool FieldInfo::extractNumeric(Meter *m, Telegram *t, DVEntry *dve) bool found = false; string key = difVifKey().str(); - int offset {}; - if (key == "") + if (dve == NULL) { - // Search for key. - bool ok = findKeyWithNr(measurementType(), - vifRange(), - storageNr().intValue(), - tariffNr().intValue(), - indexNr().intValue(), - &key, - &t->dv_entries); - if (!ok) return false; + if (key == "") + { + // Search for key. + bool ok = findKeyWithNr(measurementType(), + vifRange(), + storageNr().intValue(), + tariffNr().intValue(), + indexNr().intValue(), + &key, + &t->dv_entries); + // No entry was found. + if (!ok) return false; + } + // No entry with this key was found. + if (t->dv_entries.count(key) == 0) return false; + dve = &t->dv_entries[key].second; } double extracted_double_value = NAN; - if (extractDVdouble(&t->dv_entries, - key, - &offset, - &extracted_double_value, - vifScaling() == VifScaling::Auto || - vifScaling() == VifScaling::AutoSigned, - vifScaling() == VifScaling::NoneSigned || - vifScaling() == VifScaling::AutoSigned)) + if (dve->extractDouble(&extracted_double_value, + vifScaling() == VifScaling::Auto || + vifScaling() == VifScaling::AutoSigned, + vifScaling() == VifScaling::NoneSigned || + vifScaling() == VifScaling::AutoSigned)) { Unit decoded_unit = defaultUnit(); if (vifRange() != VIFRange::Any && @@ -2109,7 +2112,7 @@ bool FieldInfo::extractNumeric(Meter *m, Telegram *t, DVEntry *dve) decoded_unit = toDefaultUnit(vifRange()); } setValueDouble(decoded_unit, extracted_double_value); - t->addMoreExplanation(offset, renderJson(&m->conversions())); + t->addMoreExplanation(dve->offset, renderJson(&m->conversions())); found = true; } return found; @@ -2119,55 +2122,65 @@ bool FieldInfo::extractString(Meter *m, Telegram *t, DVEntry *dve) { bool found = false; string key = difVifKey().str(); - int offset {}; - if (key == "") + + if (dve == NULL) { - // Search for key. - bool ok = findKeyWithNr(measurementType(), - vifRange(), - storageNr().intValue(), - tariffNr().intValue(), - indexNr().intValue(), - &key, - &t->dv_entries); - if (!ok) return false; + if (key == "") + { + // Search for key. + bool ok = findKeyWithNr(measurementType(), + vifRange(), + storageNr().intValue(), + tariffNr().intValue(), + indexNr().intValue(), + &key, + &t->dv_entries); + // No entry was found. + if (!ok) return false; + } + // No entry with this key was found. + if (t->dv_entries.count(key) == 0) return false; + dve = &t->dv_entries[key].second; } + assert(dve != NULL); + assert(dve->dif_vif_key.str() == key); + uint64_t extracted_bits {}; if (lookup_.hasLookups()) { - if (extractDVlong(&t->dv_entries, key, &offset, &extracted_bits)) + if (dve->extractLong(&extracted_bits)) { string translated_bits = lookup().translate(extracted_bits); setValueString(translated_bits); - t->addMoreExplanation(offset, renderJsonText()); + t->addMoreExplanation(dve->offset, renderJsonText()); found = true; } } else if (vifRange() == VIFRange::DateTime) { struct tm datetime; - extractDVdate(&t->dv_entries, key, &offset, &datetime); + dve->extractDate(&datetime); string extracted_device_date_time = strdatetime(&datetime); setValueString(extracted_device_date_time); - t->addMoreExplanation(offset, renderJsonText()); + t->addMoreExplanation(dve->offset, renderJsonText()); found = true; } else if (vifRange() == VIFRange::Date) { struct tm date; - extractDVdate(&t->dv_entries, key, &offset, &date); + dve->extractDate(&date); string extracted_device_date = strdate(&date); setValueString(extracted_device_date); - t->addMoreExplanation(offset, renderJsonText()); + t->addMoreExplanation(dve->offset, renderJsonText()); found = true; } else if (vifRange() == VIFRange::EnhancedIdentification || vifRange() == VIFRange::FabricationNo) { string extracted_id; - extractDVReadableString(&t->dv_entries, key, &offset, &extracted_id); + dve->extractReadableString(&extracted_id); setValueString(extracted_id); - t->addMoreExplanation(offset, renderJsonText()); + t->addMoreExplanation(dve->offset, renderJsonText()); found = true; } else