Refactor insert offset and key inside DVEntry add extractor methods to DVEntry.

pull/520/head
Fredrik Öhrström 2022-04-17 17:34:51 +02:00
rodzic 70a7078a57
commit 11763b2f22
3 zmienionych plików z 105 dodań i 74 usunięć

Wyświetl plik

@ -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<string,pair<int,DVEntry>> *dv_entries,
bool extractDVReadableString(map<string,pair<int,DVEntry>> *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<int,DVEntry>& 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<string,pair<int,DVEntry>> *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<string,pair<int,DVEntry>> *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<int,DVEntry>& 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<int,DVEntry>& p = (*dv_entries)[key];
*offset = p.first;
vector<uchar> 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....
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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