Adding more fields to abbb23 driver.

pull/1021/head
Fredrik Öhrström 2023-08-22 22:28:04 +02:00
rodzic a41bce1145
commit 1faabb7526
13 zmienionych plików z 414 dodań i 26 usunięć

Wyświetl plik

@ -1,5 +1,5 @@
/*
Copyright (C) 2019-2022 Fredrik Öhrström (gpl-3.0-or-later)
Copyright (C) 2019-2023 Fredrik Öhrström (gpl-3.0-or-later)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -36,16 +36,170 @@ namespace
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addStringField(
"status",
"Status, error, warning and alarm flags.",
DEFAULT_PRINT_PROPERTIES | PrintProperty::INCLUDE_TPL_STATUS | PrintProperty::STATUS);
addNumericFieldWithExtractor(
"total_energy_consumption",
"The total energy consumption recorded by this meter.",
"Total cumulative active imported energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
FieldMatcher::build()
.set(DifVifKey("0E8400"))
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
.add(VIFCombinableRaw(0)) // Stupid 00 combinable....
);
addNumericFieldWithExtractor(
"total_energy_consumption_tariff_{tariff_counter}",
"Total cumulative active imported energy per tariff.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
.set(TariffNr(1),TariffNr(4))
.add(VIFCombinableRaw(0)) // Stupid 00 combinable....
);
addNumericFieldWithExtractor(
"total_energy_production",
"Total cumulative active exported energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
.set(TariffNr(0))
.set(SubUnitNr(1))
.add(VIFCombinableRaw(0)) // Stupid 00 combinable....
);
addNumericFieldWithExtractor(
"total_energy_production_tariff_{tariff_counter}",
"Total cumulative active exported energy per tariff.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
.set(TariffNr(1),TariffNr(4))
.set(SubUnitNr(1))
.add(VIFCombinableRaw(0)) // Stupid 00 combinable....
);
addNumericFieldWithExtractor(
"active_tariff",
"Active tariff.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
FieldMatcher::build()
.set(DifVifKey("01FF9300"))
);
addNumericFieldWithExtractor(
"ct_numerator",
"Current transformer ratio (numerator).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
FieldMatcher::build()
.set(DifVifKey("04FFA015")),
Unit::FACTOR
);
addNumericFieldWithExtractor(
"vt_numerator",
"Voltage transformer ratio (numerator).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
FieldMatcher::build()
.set(DifVifKey("04FFA115")),
Unit::FACTOR
);
addNumericFieldWithExtractor(
"ct_denominator",
"Current transformer ratio (denominator).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
FieldMatcher::build()
.set(DifVifKey("04FFA215")),
Unit::FACTOR
);
addNumericFieldWithExtractor(
"vt_denominator",
"Voltage transformer ratio (denominator).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
FieldMatcher::build()
.set(DifVifKey("04FFA315")),
Unit::FACTOR
);
addStringFieldWithExtractorAndLookup(
"error_flags",
"Error flags.",
DEFAULT_PRINT_PROPERTIES | PrintProperty::INJECT_INTO_STATUS,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(DifVifKey("07FFA600")),
Translate::Lookup()
.add(Translate::Rule("ERROR_FLAGS", Translate::Type::BitToString)
.set(MaskBits(0xffffffffffffffff))
.set(DefaultMessage("OK"))
));
addStringFieldWithExtractorAndLookup(
"warning_flags",
"Warning flags.",
DEFAULT_PRINT_PROPERTIES | PrintProperty::INJECT_INTO_STATUS,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(DifVifKey("07FFA700")),
Translate::Lookup()
.add(Translate::Rule("WARNING_FLAGS", Translate::Type::BitToString)
.set(MaskBits(0xffffffffffffffff))
.set(DefaultMessage("OK"))
));
addStringFieldWithExtractorAndLookup(
"information_flags",
"Information flags.",
DEFAULT_PRINT_PROPERTIES,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(DifVifKey("07FFA800")),
Translate::Lookup()
.add(Translate::Rule("INFORMATION_FLAGS", Translate::Type::BitToString)
.set(MaskBits(0xffffffffffffffff))
.set(DefaultMessage(""))
));
addStringFieldWithExtractorAndLookup(
"alarm_flags",
"alarm flags.",
DEFAULT_PRINT_PROPERTIES | PrintProperty::INJECT_INTO_STATUS,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(DifVifKey("07FFA900")),
Translate::Lookup()
.add(Translate::Rule("ALARM_FLAGS", Translate::Type::BitToString)
.set(MaskBits(0xffffffffffffffff))
.set(DefaultMessage("OK"))
));
addStringFieldWithExtractor(
"firmware_version",
"Firmware version.",
@ -53,7 +207,7 @@ namespace
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FirmwareVersion)
.add(VIFCombinable::Any) // Stupid 00 combinable....
.add(VIFCombinableRaw(0)) // Stupid 00 combinable....
);
addStringFieldWithExtractor(
@ -62,10 +216,175 @@ namespace
DEFAULT_PRINT_PROPERTIES,
FieldMatcher::build().
set(DifVifKey("0DFFAA00")));
addNumericFieldWithExtractor(
"power_fail",
"Power fail counter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
FieldMatcher::build()
.set(DifVifKey("04FF9800"))
);
addNumericFieldWithExtractor(
"active_consumption",
"Instantaneous total active imported power.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
.add(VIFCombinableRaw(0)) // Stupid 00 combinable....
);
addNumericFieldWithExtractor(
"reactive_consumption",
"Instantaneous total reactive imported power.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
.set(SubUnitNr(2))
.add(VIFCombinableRaw(0)) // Stupid 00 combinable....
);
addNumericFieldWithExtractor(
"apparent_consumption",
"Instantaneous total apparent imported power.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
.set(SubUnitNr(4))
.add(VIFCombinableRaw(0)) // Stupid 00 combinable....
);
addNumericFieldWithExtractor(
"voltage_l1_n",
"Instantaneous voltage between L1 and neutral.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::AutoSigned,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
.add(VIFCombinableRaw(0x7f01))
.add(VIFCombinableRaw(0)) // Stupid 00 combinable....
);
addNumericFieldWithExtractor(
"voltage_l2_n",
"Instantaneous voltage between L2 and neutral.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::AutoSigned,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
.add(VIFCombinableRaw(0x7f02))
.add(VIFCombinableRaw(0)) // Stupid 00 combinable....
);
addNumericFieldWithExtractor(
"voltage_l3_n",
"Instantaneous voltage between L3 and neutral.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::AutoSigned,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
.add(VIFCombinableRaw(0x7f03))
.add(VIFCombinableRaw(0)) // Stupid 00 combinable....
);
addNumericFieldWithExtractor(
"current_l1",
"Instantaneous current in the L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::AutoSigned,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Amperage)
.add(VIFCombinableRaw(0x7f01))
.add(VIFCombinableRaw(0)) // Stupid 00 combinable....
);
addNumericFieldWithExtractor(
"current_l2",
"Instantaneous current in the L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::AutoSigned,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Amperage)
.add(VIFCombinableRaw(0x7f02))
.add(VIFCombinableRaw(0)) // Stupid 00 combinable....
);
addNumericFieldWithExtractor(
"current_l3",
"Instantaneous current in the L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::AutoSigned,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Amperage)
.add(VIFCombinableRaw(0x7f03))
.add(VIFCombinableRaw(0)) // Stupid 00 combinable....
);
addNumericFieldWithExtractor(
"frequency",
"Frequency of AC",
DEFAULT_PRINT_PROPERTIES,
Quantity::Frequency,
VifScaling::None,
FieldMatcher::build()
.set(DifVifKey("0AFFD900")),
Unit::HZ,
0.01
);
addNumericFieldWithExtractor(
"power",
"Power factor.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
FieldMatcher::build()
.set(DifVifKey("02FFE000")),
Unit::FACTOR,
0.001
);
addNumericFieldWithExtractor(
"energy_co2",
"Energy in co2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Mass,
VifScaling::None,
FieldMatcher::build()
.set(DifVifKey("0EFFF9C400")),
Unit::KG,
0.001
);
}
}
// Test: ABBmeter abbb23 33221100 NOKEY
// telegram=|844442040011223320027A3E000020_0E840017495200000004FFA0150000000004FFA1150000000004FFA2150000000004FFA3150000000007FFA600000000000000000007FFA700000000000000000007FFA800000000000000000007FFA90000000000000000000DFD8E0007302E38322E31420DFFAA000B3030312D313131203332421F|
// {"media":"electricity","meter":"abbb23","name":"ABBmeter","id":"33221100","total_energy_consumption_kwh":5249.17,"firmware_version": "B1.28.0","product_no": "B23 111-100","timestamp":"1111-11-11T11:11:11Z"}
// |ABBmeter;33221100;5249.17;1111-11-11 11:11.11
/* / Test: ABBmeter abbb23 33221100 NOKEY
/ telegram=|844442040011223320027A3E000020_0E840017495200000004FFA0150000000004FFA1150000000004FFA2150000000004FFA3150000000007FFA600000000000000000007FFA700000000000000000007FFA800000000000000000007FFA90000000000000000000DFD8E0007302E38322E31420DFFAA000B3030312D313131203332421F|
/ {"media":"electricity","meter":"abbb23","name":"ABBmeter","id":"33221100","total_energy_consumption_kwh":5249.17,"firmware_version": "B1.28.0","product_no": "B23 111-100","timestamp":"1111-11-11T11:11:11Z"}
/ |ABBmeter;33221100;5249.17;1111-11-11 11:11.11
*/

Wyświetl plik

@ -61,7 +61,7 @@ namespace
string total;
strprintf(&total, "%02x%02x%02x%02x", content[0], content[1], content[2], content[3]);
vendor_values["0413"] = { 25, DVEntry(25, DifVifKey("0413"), MeasurementType::Instantaneous, 0x13, {}, 0, 0, 0, total) };
vendor_values["0413"] = { 25, DVEntry(25, DifVifKey("0413"), MeasurementType::Instantaneous, 0x13, {}, {}, 0, 0, 0, total) };
int offset;
string key;
if(findKey(MeasurementType::Instantaneous, VIFRange::Volume, 0, 0, &key, &vendor_values))

Wyświetl plik

@ -119,7 +119,7 @@ namespace
string total;
strprintf(&total, "%02x%02x%02x%02x", content[i+0], content[i+1], content[i+2], content[i+3]);
int offset = i-1+t->header_size;
vendor_values["0413"] = {offset, DVEntry(offset, DifVifKey("0413"), MeasurementType::Instantaneous, 0x13, {}, 0, 0, 0, total) };
vendor_values["0413"] = {offset, DVEntry(offset, DifVifKey("0413"), MeasurementType::Instantaneous, 0x13, {}, {}, 0, 0, 0, total) };
double total_water_consumption_m3 {};
extractDVdouble(&vendor_values, "0413", &offset, &total_water_consumption_m3);
total = "*** 10-"+total+" total consumption (%f m3)";

Wyświetl plik

@ -64,7 +64,7 @@ namespace
string total;
strprintf(&total, "%02x%02x%02x%02x", content[i+0], content[i+1], content[i+2], content[i+3]);
int offset = i-1+t->header_size;
vendor_values["0413"] = {offset, DVEntry(offset, DifVifKey("0413"), MeasurementType::Instantaneous, 0x13, {}, 0, 0, 0, total) };
vendor_values["0413"] = {offset, DVEntry(offset, DifVifKey("0413"), MeasurementType::Instantaneous, 0x13, {}, {}, 0, 0, 0, total) };
double tmp = 0;
extractDVdouble(&vendor_values, "0413", &offset, &tmp);
// Single tick seems to be 1/3 of a m3. Divide by 3 and keep a single decimal.

Wyświetl plik

@ -80,7 +80,7 @@ namespace
string prevs;
strprintf(&prevs, "%02x%02x", prev_lo, prev_hi);
int offset = t->parsed.size()+3;
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, 0, 0, 0, prevs) };
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, {}, 0, 0, 0, prevs) };
Explanation pe(offset, 2, prevs, KindOfData::CONTENT, Understanding::FULL);
t->explanations.push_back(pe);
t->addMoreExplanation(offset, " energy used in previous billing period (%f KWH)", prev);
@ -92,7 +92,7 @@ namespace
string currs;
strprintf(&currs, "%02x%02x", curr_lo, curr_hi);
offset = t->parsed.size()+7;
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, 0, 0, 0, currs) };
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, {}, 0, 0, 0, currs) };
Explanation ce(offset, 2, currs, KindOfData::CONTENT, Understanding::FULL);
t->explanations.push_back(ce);
t->addMoreExplanation(offset, " energy used in current billing period (%f KWH)", curr);

Wyświetl plik

@ -76,7 +76,7 @@ namespace
string prevs;
strprintf(&prevs, "%02x%02x", prev_lo, prev_hi);
int offset = t->parsed.size()+3;
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, 0, 0, 0, prevs) };
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, {}, 0, 0, 0, prevs) };
t->explanations.push_back(Explanation(offset, 2, prevs, KindOfData::CONTENT, Understanding::FULL));
t->addMoreExplanation(offset, " energy used in previous billing period (%f GJ)", prev_gj);
@ -87,7 +87,7 @@ namespace
string currs;
strprintf(&currs, "%02x%02x", curr_lo, curr_hi);
offset = t->parsed.size()+7;
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, 0, 0, 0, currs) };
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, {}, 0, 0, 0, currs) };
t->explanations.push_back(Explanation(offset, 2, currs, KindOfData::CONTENT, Understanding::FULL));
t->addMoreExplanation(offset, " energy used in current billing period (%f GJ)", curr_gj);

Wyświetl plik

@ -319,6 +319,7 @@ bool parseDV(Telegram *t,
int combinable_full_vif = 0;
bool combinable_extension_vif = false;
set<VIFCombinable> found_combinable_vifs;
set<uint16_t> found_combinable_vifs_raw;
DEBUG_PARSER("(dvparser debug) vif=%04x \"%s\"\n", vif, vifType(vif).c_str());
@ -407,6 +408,8 @@ bool parseDV(Telegram *t,
combinable_extension_vif = false;
VIFCombinable vc = toVIFCombinable(combinable_full_vif);
found_combinable_vifs.insert(vc);
found_combinable_vifs_raw.insert(combinable_full_vif);
if (data_has_difvifs)
{
t->addExplanationAndIncrementPos(*format, 1, KindOfData::PROTOCOL, Understanding::FULL,
@ -432,6 +435,8 @@ bool parseDV(Telegram *t,
{
VIFCombinable vc = toVIFCombinable(combinable_full_vif);
found_combinable_vifs.insert(vc);
found_combinable_vifs_raw.insert(combinable_full_vif);
if (data_has_difvifs)
{
t->addExplanationAndIncrementPos(*format, 1, KindOfData::PROTOCOL, Understanding::FULL,
@ -487,6 +492,7 @@ bool parseDV(Telegram *t,
mt,
Vif(full_vif),
found_combinable_vifs,
found_combinable_vifs_raw,
StorageNr(storage_nr),
TariffNr(tariff),
SubUnitNr(subunit),
@ -1127,12 +1133,13 @@ double DVEntry::getCounter(DVEntryCounterType ct)
string DVEntry::str()
{
string s =
tostrprintf("%d: %s %s vif=%x %s st=%d ta=%d su=%d",
tostrprintf("%d: %s %s vif=%x %s%s st=%d ta=%d su=%d",
offset,
dif_vif_key.str().c_str(),
toString(measurement_type),
vif.intValue(),
combinable_vifs.size() > 0 ? "HASCOMB ":"",
combinable_vifs_raw.size() > 0 ? "HASCOMBRAW ":"",
storage_nr.intValue(),
tariff_nr.intValue(),
subunit_nr.intValue()
@ -1248,15 +1255,28 @@ bool FieldMatcher::matches(DVEntry &dv_entry)
// So far so good, now test the combinables.
// If field matcher has no combinables, then do NOT match any dventry with a combinable!
if (vif_combinables.size()== 0)
if (vif_combinables.size()== 0 && vif_combinables_raw.size() == 0)
{
if (dv_entry.combinable_vifs.size() == 0) return true;
// If there is a combinable vif, then there is a raw combinable vif. So comparing both not strictly necessary.
if (dv_entry.combinable_vifs.size() == 0 && dv_entry.combinable_vifs_raw.size() == 0) return true;
// Oups, field matcher does not expect any combinables, but the dv_entry has combinables.
// This means no match for us since combinables must be handled explicitly.
return false;
}
// Lets check that the dv_entry vif combinables raw contains the field matcher requested combinable raws.
// The raws are used for meters using reserved and manufacturer specific vif combinables.
for (uint16_t vcr : vif_combinables_raw)
{
if (dv_entry.combinable_vifs_raw.count(vcr) == 0)
{
// Ouch, one of the requested vif combinables raw did not exist in the dv_entry. No match!
return false;
}
}
// Lets check that the dv_entry combinables contains the field matcher requested combinables.
// The named vif combinables are used by well behaved meters.
for (VIFCombinable vc : vif_combinables)
{
if (vc != VIFCombinable::Any && dv_entry.combinable_vifs.count(vc) == 0)
@ -1270,12 +1290,26 @@ bool FieldMatcher::matches(DVEntry &dv_entry)
// then we need to check if there are unmatched combinables in the telegram, if so fail the match.
if (vif_combinables.count(VIFCombinable::Any) == 0)
{
for (VIFCombinable vc : dv_entry.combinable_vifs)
if (vif_combinables.size() > 0)
{
if (vif_combinables.count(vc) == 0)
for (VIFCombinable vc : dv_entry.combinable_vifs)
{
// Oups, the telegram entry had a combinable that we had no matcher for.
return false;
if (vif_combinables.count(vc) == 0)
{
// Oups, the telegram entry had a vif combinable that we had no matcher for.
return false;
}
}
}
else
{
for (uint16_t vcr : dv_entry.combinable_vifs_raw)
{
if (vif_combinables_raw.count(vcr) == 0)
{
// Oups, the telegram entry had a vif combinable raw that we had no matcher for.
return false;
}
}
}
}

Wyświetl plik

@ -193,6 +193,11 @@ LIST_OF_VIF_COMBINABLES
#undef X
};
struct VIFCombinableRaw {
VIFCombinableRaw(uint16_t v) : value(v) {}
uint16_t value;
};
VIFCombinable toVIFCombinable(int i);
const char *toString(VIFCombinable v);
@ -322,6 +327,7 @@ struct DVEntry
MeasurementType measurement_type;
Vif vif;
std::set<VIFCombinable> combinable_vifs;
std::set<uint16_t> combinable_vifs_raw;
StorageNr storage_nr;
TariffNr tariff_nr;
SubUnitNr subunit_nr;
@ -332,6 +338,7 @@ struct DVEntry
MeasurementType mt,
Vif vi,
std::set<VIFCombinable> vc,
std::set<uint16_t> vc_raw,
StorageNr st,
TariffNr ta,
SubUnitNr su,
@ -341,6 +348,7 @@ struct DVEntry
measurement_type(mt),
vif(vi),
combinable_vifs(vc),
combinable_vifs_raw(vc_raw),
storage_nr(st),
tariff_nr(ta),
subunit_nr(su),
@ -393,6 +401,7 @@ struct FieldMatcher
// Match any vif combinables.
std::set<VIFCombinable> vif_combinables;
std::set<uint16_t> vif_combinables_raw;
// Match the storage nr. If no storage is specified, default to match only 0.
bool match_storage_nr = true;
@ -432,6 +441,9 @@ struct FieldMatcher
FieldMatcher &add(VIFCombinable v) {
vif_combinables.insert(v);
return *this; }
FieldMatcher &add(VIFCombinableRaw v) {
vif_combinables_raw.insert(v.value);
return *this; }
FieldMatcher &set(StorageNr s) {
storage_nr_from = storage_nr_to = s;
match_storage_nr = (s != AnyStorageNr);

Wyświetl plik

@ -358,6 +358,7 @@ void qdsExtractWalkByField(Telegram *t, Meter *driver, DVEntry &mfctEntry, int p
MeasurementType::Instantaneous,
key.vif(),
set<VIFCombinable>(),
set<uint16_t>(),
AnyStorageNr,
AnyTariffNr,
SubUnitNr(0),

Wyświetl plik

@ -311,7 +311,8 @@ void MeterCommonImplementation::addNumericFieldWithExtractor(string vname,
Quantity vquantity,
VifScaling vif_scaling,
FieldMatcher matcher,
Unit display_unit)
Unit display_unit,
double scale)
{
field_infos_.emplace_back(
FieldInfo(field_infos_.size(),
@ -319,6 +320,7 @@ void MeterCommonImplementation::addNumericFieldWithExtractor(string vname,
vquantity,
display_unit == Unit::Unknown ? defaultUnitForQuantity(vquantity) : display_unit,
vif_scaling,
scale,
matcher,
help,
print_properties,
@ -357,6 +359,7 @@ void MeterCommonImplementation::addNumericFieldWithCalculator(string vname,
vquantity,
display_unit == Unit::Unknown ? defaultUnitForQuantity(vquantity) : display_unit,
VifScaling::Auto,
1.0,
FieldMatcher::noMatcher(),
help,
print_properties,
@ -396,6 +399,7 @@ void MeterCommonImplementation::addNumericFieldWithCalculatorAndMatcher(string v
vquantity,
display_unit == Unit::Unknown ? defaultUnitForQuantity(vquantity) : display_unit,
VifScaling::Auto,
1.0,
matcher,
help,
print_properties,
@ -422,6 +426,7 @@ void MeterCommonImplementation::addNumericField(
vquantity,
display_unit == Unit::Unknown ? defaultUnitForQuantity(vquantity) : display_unit,
VifScaling::None,
1.0,
FieldMatcher::noMatcher(),
help,
print_properties,
@ -445,6 +450,7 @@ void MeterCommonImplementation::addStringFieldWithExtractor(string vname,
Quantity::Text,
defaultUnitForQuantity(Quantity::Text),
VifScaling::None,
1.0,
matcher,
help,
print_properties,
@ -469,6 +475,7 @@ void MeterCommonImplementation::addStringFieldWithExtractorAndLookup(string vnam
Quantity::Text,
defaultUnitForQuantity(Quantity::Text),
VifScaling::None,
1.0,
matcher,
help,
print_properties,
@ -491,6 +498,7 @@ void MeterCommonImplementation::addStringField(string vname,
Quantity::Text,
defaultUnitForQuantity(Quantity::Text),
VifScaling::None,
1.0,
FieldMatcher(),
help,
print_properties,
@ -1459,6 +1467,7 @@ FieldInfo::FieldInfo(int index,
Quantity xuantity,
Unit display_unit,
VifScaling vif_scaling,
double scale,
FieldMatcher matcher,
string help,
PrintProperties print_properties,
@ -1474,6 +1483,7 @@ FieldInfo::FieldInfo(int index,
xuantity_(xuantity),
display_unit_(display_unit),
vif_scaling_(vif_scaling),
scale_(scale),
matcher_(matcher),
help_(help),
print_properties_(print_properties),
@ -2173,13 +2183,19 @@ bool FieldInfo::extractNumeric(Meter *m, Telegram *t, DVEntry *dve)
decoded_unit = toDefaultUnit(matcher_.vif_range);
}
debug("(meter) %s %s decoded %s default %s value %g\n",
debug("(meter) %s %s decoded %s default %s value %g (scale %g)\n",
toString(matcher_.vif_range),
field_name.c_str(),
unitToStringLowerCase(decoded_unit).c_str(),
unitToStringLowerCase(display_unit_).c_str(),
extracted_double_value);
extracted_double_value,
scale());
if (scale() != 1.0)
{
// Hardcoded scale factor for this field used for manufacturer specific values without vif units.
extracted_double_value *= scale();
}
m->setNumericValue(this, dve, display_unit_, convert(extracted_double_value, decoded_unit, display_unit_));
t->addMoreExplanation(dve->offset, renderJson(m, dve));
found = true;

Wyświetl plik

@ -274,6 +274,7 @@ struct FieldInfo
Quantity quantity,
Unit display_unit,
VifScaling vif_scaling,
double scale,
FieldMatcher matcher,
string help,
PrintProperties print_properties,
@ -290,6 +291,7 @@ struct FieldInfo
Quantity xuantity() { return xuantity_; }
Unit displayUnit() { return display_unit_; }
VifScaling vifScaling() { return vif_scaling_; }
double scale() { return scale_; }
FieldMatcher& matcher() { return matcher_; }
string help() { return help_; }
PrintProperties printProperties() { return print_properties_; }
@ -336,6 +338,7 @@ private:
Quantity xuantity_; // Quantity: Energy, Volume
Unit display_unit_; // Selected display unit for above quantity: KWH, M3
VifScaling vif_scaling_;
double scale_; // A hardcoded scale factor. Used only for manufacturer specific values with unknown units for the vifs.
FieldMatcher matcher_;
string help_; // Helpful information on this meters use of this value.
PrintProperties print_properties_;

Wyświetl plik

@ -109,7 +109,8 @@ protected:
Quantity vquantity, // Value belongs to this quantity, this quantity determines the default unit.
VifScaling vif_scaling, // How should any Vif value be scaled.
FieldMatcher matcher,
Unit display_unit = Unit::Unknown); // If specified use this unit for the json field instead instead of the default unit.
Unit display_unit = Unit::Unknown, // If specified use this unit for the json field instead instead of the default unit.
double scale = 1.0); // A hard coded extra scale factor. Useful for manufacturer specific values.
void addNumericFieldWithCalculator(
string vname, // Name of value without unit, eg "total" "total_month{storagenr}"

Wyświetl plik

@ -1493,6 +1493,7 @@ void test_field_matcher()
MeasurementType::Instantaneous,
Vif(0x13),
{ },
{ },
StorageNr(0),
TariffNr(0),
SubUnitNr(0),
@ -1522,6 +1523,7 @@ void test_field_matcher()
MeasurementType::Instantaneous,
Vif(0x10),
{ VIFCombinable::DeltaBetweenImportAndExport },
{ },
StorageNr(2),
TariffNr(0),
SubUnitNr(0),