Add handling of combinables.

pull/540/head
Fredrik Öhrström 2022-05-07 19:16:34 +02:00
rodzic 3282c19344
commit 19ec79fc41
11 zmienionych plików z 313 dodań i 51 usunięć

Wyświetl plik

@ -66,7 +66,7 @@ void MeterApator08::processContent(Telegram *t)
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

@ -42,6 +42,26 @@ LIST_OF_VIF_RANGES
assert(0);
}
const char *toString(VIFCombinable v)
{
switch (v) {
case VIFCombinable::None: return "None";
case VIFCombinable::Any: return "Any";
#define X(name,from,to) case VIFCombinable::name: return #name;
LIST_OF_VIF_COMBINABLES
#undef X
}
assert(0);
}
VIFCombinable toVIFCombinable(int i)
{
#define X(name,from,to) if (from <= i && i <= to) return VIFCombinable::name;
LIST_OF_VIF_COMBINABLES
#undef X
return VIFCombinable::None;
}
Unit toDefaultUnit(VIFRange v)
{
switch (v) {
@ -221,8 +241,10 @@ bool parseDV(Telegram *t,
bool has_another_dife = (dif & 0x80) == 0x80;
while (has_another_dife) {
while (has_another_dife)
{
if (*format == format_end) { debug("(dvparser) warning: unexpected end of data (dife expected)\n"); break; }
uchar dife = **format;
int subunit_bit = (dife & 0x40) >> 6;
subunit |= subunit_bit << difenr;
@ -231,15 +253,18 @@ bool parseDV(Telegram *t,
int storage_nr_bits = (dife & 0x0f);
storage_nr |= storage_nr_bits << (1+difenr*4);
DEBUG_PARSER("(dvparser debug) dife=%02x (subunit=%d tariff=%d storagenr=%d)\n",
dife, subunit, tariff, storage_nr);
if (data_has_difvifs) {
DEBUG_PARSER("(dvparser debug) dife=%02x (subunit=%d tariff=%d storagenr=%d)\n", dife, subunit, tariff, storage_nr);
if (data_has_difvifs)
{
format_bytes.push_back(dife);
id_bytes.push_back(dife);
t->addExplanationAndIncrementPos(*format, 1, KindOfData::PROTOCOL, Understanding::FULL,
"%02X dife (subunit=%d tariff=%d storagenr=%d)",
dife, subunit, tariff, storage_nr);
} else {
}
else
{
id_bytes.push_back(**format);
(*format)++;
}
@ -251,17 +276,32 @@ bool parseDV(Telegram *t,
if (*format == format_end) { debug("(dvparser) warning: unexpected end of data (vif expected)\n"); break; }
uchar vif = **format;
DEBUG_PARSER("(dvparser debug) vif=%02x \"%s\"\n", vif, vifType(vif).c_str());
if (data_has_difvifs) {
int full_vif = vif & 0x7f;
bool extension_vif = false;
set<VIFCombinable> found_combinable_vifs;
DEBUG_PARSER("(dvparser debug) vif=%04x \"%s\"\n", vif, vifType(vif).c_str());
if (data_has_difvifs)
{
format_bytes.push_back(vif);
id_bytes.push_back(vif);
t->addExplanationAndIncrementPos(*format, 1, KindOfData::PROTOCOL, Understanding::FULL,
"%02X vif (%s)", vif, vifType(vif).c_str());
} else {
} else
{
id_bytes.push_back(**format);
(*format)++;
}
// Check if this is marker for one of the extended sets of vifs: first, second and thir.
if (vif == 0xfb || vif == 0xfd || vif == 0xef)
{
// Extension vifs.
full_vif <<= 8;
extension_vif = true;
}
// Grabbing a variable length vif. This does not currently work
// with the compact format.
if (vif == 0x7c)
@ -282,21 +322,52 @@ bool parseDV(Telegram *t,
}
}
// Do we have another vife byte? We better have one, if extension_vif is true.
bool has_another_vife = (vif & 0x80) == 0x80;
while (has_another_vife) {
while (has_another_vife)
{
if (*format == format_end) { debug("(dvparser) warning: unexpected end of data (vife expected)\n"); break; }
uchar vife = **format;
DEBUG_PARSER("(dvparser debug) vife=%02x (%s)\n", vife, vifeType(dif, vif, vife).c_str());
if (data_has_difvifs) {
if (data_has_difvifs)
{
// Collect the difvifs to create signature for future use.
format_bytes.push_back(vife);
id_bytes.push_back(vife);
t->addExplanationAndIncrementPos(*format, 1, KindOfData::PROTOCOL, Understanding::FULL,
"%02X vife (%s)", vife, vifeType(dif, vif, vife).c_str());
} else {
}
else
{
// Reuse the existing
id_bytes.push_back(**format);
(*format)++;
}
has_another_vife = (vife & 0x80) == 0x80;
if (extension_vif)
{
// First vife after the extension marker is the real vif.
full_vif |= (vife & 0x7f);
extension_vif = false;
if (data_has_difvifs)
{
t->addExplanationAndIncrementPos(*format, 1, KindOfData::PROTOCOL, Understanding::FULL,
"%02X vife (%s)", vife, vifeType(dif, vif, vife).c_str());
}
}
else
{
// If the full vif is now handled, then the rest are combinable vifs.
VIFCombinable vc = toVIFCombinable(vife & 0x7f);
found_combinable_vifs.insert(vc);
if (data_has_difvifs)
{
t->addExplanationAndIncrementPos(*format, 1, KindOfData::PROTOCOL, Understanding::FULL,
"%02X combinable vif (%s)", vife, toString(vc));
}
}
}
dv = "";
@ -337,7 +408,8 @@ bool parseDV(Telegram *t,
(*dv_entries)[key] = { offset, DVEntry(offset,
key,
mt,
Vif(vif&0x7f),
Vif(full_vif),
found_combinable_vifs,
StorageNr(storage_nr),
TariffNr(tariff),
SubUnitNr(subunit),
@ -345,6 +417,11 @@ bool parseDV(Telegram *t,
DVEntry *dve = &(*dv_entries)[key].second;
if (isDebugEnabled())
{
debug("(dvparser) entry %s\n", dve->str().c_str());
}
assert(key == dve->dif_vif_key.str());
if (value.length() > 0) {
@ -376,18 +453,17 @@ bool hasKey(std::map<std::string,std::pair<int,DVEntry>> *dv_entries, std::strin
return dv_entries->count(key) > 0;
}
bool findKey(MeasurementType mit, VIFRange vif, StorageNr storagenr, TariffNr tariffnr,
bool findKey(MeasurementType mit, VIFRange vif_range, StorageNr storagenr, TariffNr tariffnr,
std::string *key, std::map<std::string,std::pair<int,DVEntry>> *dv_entries)
{
return findKeyWithNr(mit, vif, storagenr, tariffnr, 1, key, dv_entries);
return findKeyWithNr(mit, vif_range, storagenr, tariffnr, 1, key, dv_entries);
}
bool findKeyWithNr(MeasurementType mit, VIFRange vif_range, StorageNr storagenr, TariffNr tariffnr, int nr,
std::string *key, std::map<std::string,std::pair<int,DVEntry>> *dv_entries)
{
/*debug("(dvparser) looking for type=%s vif=%s storagenr=%d value_ran_low=%02x value_ran_hi=%02x\n",
measurementTypeName(mit).c_str(), toString(vif), storagenr,
low, hi);*/
/*debug("(dvparser) looking for type=%s vifrange=%s storagenr=%d tariffnr=%d\n",
measurementTypeName(mit).c_str(), toString(vif_range), storagenr.intValue(), tariffnr.intValue());*/
for (auto& v : *dv_entries)
{
@ -396,9 +472,9 @@ bool findKeyWithNr(MeasurementType mit, VIFRange vif_range, StorageNr storagenr,
StorageNr sn = v.second.second.storage_nr;
TariffNr tn = v.second.second.tariff_nr;
/*debug("(dvparser) match? %s type=%s vif=%02x (%s) and storagenr=%d\n",
/* debug("(dvparser) match? %s type=%s vife=%x (%s) and storagenr=%d\n",
v.first.c_str(),
measurementTypeName(ty).c_str(), vi, toString(toVIFRange(vi)), storagenr, sn);*/
measurementTypeName(ty).c_str(), vi.intValue(), storagenr, sn);*/
if (isInsideVIFRange(vi, vif_range) &&
(mit == MeasurementType::Instantaneous || mit == ty) &&
@ -408,9 +484,9 @@ bool findKeyWithNr(MeasurementType mit, VIFRange vif_range, StorageNr storagenr,
*key = v.first;
nr--;
if (nr <= 0) return true;
/*debug("(dvparser) found key %s for type=%s vif=%02x (%s) storagenr=%d\n",
debug("(dvparser) found key %s for type=%s vif=%x storagenr=%d\n",
v.first.c_str(), measurementTypeName(ty).c_str(),
vi, toString(toVIFRange(vi)), storagenr);*/
vi.intValue(), storagenr.intValue());
}
}
return false;
@ -893,6 +969,23 @@ bool DVEntry::extractReadableString(string *out)
return true;
}
string DVEntry::str()
{
string s =
tostrprintf("%d: %s %s vif=%x %s st=%d ta=%d su=%d",
offset,
dif_vif_key.str().c_str(),
toString(measurement_type),
vif.intValue(),
combinable_vifs.size() > 0 ? "HASCOMB ":"",
storage_nr.intValue(),
tariff_nr.intValue(),
subunit_nr.intValue()
);
return s;
}
bool extractDate(uchar hi, uchar lo, struct tm *date)
{
// | hi | lo |
@ -991,12 +1084,6 @@ bool FieldMatcher::matches(DVEntry &dv_entry)
return b;
}
if (dv_entry.dif_vif_key.hasVifes())
{
// Currently we cannot match vifes. They must be selected using expicit dif_vif_keys above.
return false;
}
bool b =
(!match_vif_range || isInsideVIFRange(dv_entry.vif, vif_range)) &&
(!match_measurement_type || dv_entry.measurement_type == measurement_type) &&
@ -1004,5 +1091,40 @@ bool FieldMatcher::matches(DVEntry &dv_entry)
(!match_tariff_nr || (dv_entry.tariff_nr >= tariff_nr_from && dv_entry.tariff_nr <= tariff_nr_to)) &&
(!match_subunit_nr || (dv_entry.subunit_nr >= subunit_nr_from && dv_entry.subunit_nr <= subunit_nr_to));
return b;
if (!b) return false;
// If field matcher has no combinables, then do NOT match any dventry with a combinable!
if (vif_combinables.size()== 0)
{
if (dv_entry.combinable_vifs.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 combinables contains the field matcher requested combinables.
for (VIFCombinable vc : vif_combinables)
{
if (dv_entry.combinable_vifs.count(vc) == 0)
{
// Ouch, one of the requested combinables did not exist in the dv_entry. No match!
return false;
}
}
// Yay, they were all found.
return true;
}
const char *toString(MeasurementType mt)
{
switch (mt)
{
case MeasurementType::Any: return "Any";
case MeasurementType::Instantaneous: return "Instantaneous";
case MeasurementType::Minimum: return "Minimum";
case MeasurementType::Maximum: return "Maximum";
case MeasurementType::AtError: return "AtError";
}
return "?";
}

Wyświetl plik

@ -22,6 +22,7 @@
#include"units.h"
#include<map>
#include<set>
#include<stdint.h>
#include<time.h>
#include<functional>
@ -44,6 +45,8 @@
X(ActualityDuration,0x74,0x77, Quantity::Time, Unit::Second) \
X(FabricationNo,0x78,0x78, Quantity::Text, Unit::TXT) \
X(EnhancedIdentification,0x79,0x79, Quantity::Text, Unit::TXT) \
X(ParameterSet,0x7D0B,0x7D0B, Quantity::Text, Unit::TXT) \
X(ModelVersion,0x7D0C,0x7D0C, Quantity::Text, Unit::TXT) \
X(AnyVolumeVIF,0x00,0x00, Quantity::Volume, Unit::Unknown) \
X(AnyEnergyVIF,0x00,0x00, Quantity::Energy, Unit::Unknown) \
X(AnyPowerVIF,0x00,0x00, Quantity::Power, Unit::Unknown) \
@ -62,6 +65,108 @@ Unit toDefaultUnit(VIFRange v);
VIFRange toVIFRange(int i);
bool isInsideVIFRange(int i, VIFRange range);
#define LIST_OF_VIF_COMBINABLES \
X(Reserved,0x00,0x11) \
X(Average,0x12,0x12) \
X(InverseCompactProfile,0x13,0x13) \
X(RelativeDeviation,0x14,0x14) \
X(RecordErrorCodeMeterToController,0x15,0x1c) \
X(StandardConformDataContent,0x1d,0x1d) \
X(CompactProfileWithRegister,0x1e,0x1e) \
X(CompactProfile,0x1f,0x1f) \
X(PerSecond,0x20,0x20) \
X(PerMinute,0x21,0x21) \
X(PerHour,0x22,0x22) \
X(PerDay,0x23,0x23) \
X(PerWeek,0x24,0x24) \
X(PerMonth,0x25,0x25) \
X(PerYear,0x26,0x26) \
X(PerRevolutionMeasurement,0x27,0x27) \
X(IncrPerInputPulseChannel0,0x28,0x28) \
X(IncrPerInputPulseChannel1,0x29,0x29) \
X(IncrPerOutputPulseChannel0,0x2a,0x2a) \
X(IncrPerOutputPulseChannel1,0x2b,0x2b) \
X(PerLitre,0x2c,0x2c) \
X(PerM3,0x2d,0x2d) \
X(PerKg,0x2e,0x2e) \
X(PerKelvin,0x2f,0x2f) \
X(PerKWh,0x30,0x30) \
X(PerGJ,0x31,0x31) \
X(PerKW,0x32,0x32) \
X(PerKelvinLitreW,0x33,0x33) \
X(PerVolt,0x34,0x34) \
X(PerAmpere,0x35,0x35) \
X(MultipliedByS,0x36,0x36) \
X(MultipliedBySDivV,0x37,0x37) \
X(MultipliedBySDivA,0x38,0x38) \
X(StartDateTimeOfAB,0x39,0x39) \
X(UncorrectedMeterUnit,0x3a,0x3a) \
X(ForwardFlow,0x3b,0x3b) \
X(BackwardFlow,0x3c,0x3c) \
X(ReservedNonMetric,0x3d,0x3d) \
X(ValueAtBaseCondC,0x3e,0x3e) \
X(ObisDeclaration,0x3f,0x3f) \
X(LowerLimit,0x40,0x40) \
X(ExceedsLowerLimit,0x41,0x41) \
X(DateTimeExceedsLowerFirstBegin, 0x42,0x42) \
X(DateTimeExceedsLowerFirstEnd, 0x43,0x43) \
X(DateTimeExceedsLowerLastBegin, 0x46,0x46) \
X(DateTimeExceedsLowerLastEnd, 0x47,0x47) \
X(UpperLimit,0x48,0x48) \
X(ExceedsUpperLimit,0x49,0x49) \
X(DateTimeExceedsUpperFirstBegin, 0x4a,0x4a) \
X(DateTimeExceedsUpperFirstEnd, 0x4b,0x4b) \
X(DateTimeExceedsUpperLastBegin, 0x4d,0x4d) \
X(DateTimeExceedsUpperLastEnd, 0x4e,0x4e) \
X(DurationExceedsLowerFirst,0x50,0x53) \
X(DurationExceedsLowerLast,0x54,0x57) \
X(DurationExceedsUpperFirst,0x58,0x5b) \
X(DurationExceedsUpperLast,0x5c,0x5f) \
X(DurationOfDFirst,0x60,0x63) \
X(DurationOfDLast,0x64,0x67) \
X(ValueDuringLowerLimitExceeded,0x68,0x68) \
X(LeakageValues,0x69,0x69) \
X(OverflowValues,0x6a,0x6a) \
X(ValueDuringUpperLimitExceeded,0x6c,0x6c) \
X(DateTimeOfDEFirstBegin,0x6a,0x6a) \
X(DateTimeOfDEFirstEnd,0x6b,0x6b) \
X(DateTimeOfDELastBegin,0x6e,0x6e) \
X(DateTimeOfDELastEnd,0x6f,0x6f) \
X(MultiplicativeCorrectionFactorForValue,0x70,0x77) \
X(AdditiveCorrectionConstant,0x78,0x7b) \
X(CombinableVIFExtension,0x7c,0x7c) \
X(MultiplicativeCorrectionFactorForValue103,0x7d,0x7d) \
X(FutureValue,0x7e,0x7e) \
X(MfctSpecific,0x7f,0x7f) \
X(AtPhase1,0x7c01,0x7c01) \
X(AtPhase2,0x7c02,0x7c02) \
X(AtPhase3,0x7c03,0x7c03) \
X(AtNeutral,0x7c04,0x7c04) \
X(BetweenPhaseL1AndL2,0x7c05,0x7c05) \
X(BetweenPhaseL2AndL3,0x7c06,0x7c06) \
X(BetweenPhaseL3AndL1,0x7c07,0x7c07) \
X(AtQuadrantQ1,0x7c08,0x7c08) \
X(AtQuadrantQ2,0x7c09,0x7c09) \
X(AtQuadrantQ3,0x7c0a,0x7c0a) \
X(AtQuadrantQ4,0x7c0b,0x7c0b) \
X(DeltaBetweenImportAndExport,0x7c0c,0x7c0c) \
X(AccumulationOfAbsoluteValue,0x7c10,0x7c10) \
X(DataPresentedWithTypeC,0x7c11,0x7c11) \
X(DataPresentedWithTypeD,0x7c12,0x7c12) \
enum class VIFCombinable
{
None,
Any,
#define X(name,from,to) name,
LIST_OF_VIF_COMBINABLES
#undef X
};
VIFCombinable toVIFCombinable(int i);
const char *toString(VIFCombinable v);
enum class MeasurementType
{
Any,
@ -71,6 +176,8 @@ enum class MeasurementType
AtError
};
const char *toString(MeasurementType mt);
void extractDV(std::string &s, uchar *dif, uchar *vif, bool *has_difes, bool *has_vifes);
struct DifVifKey
@ -170,23 +277,52 @@ struct DVEntry
DifVifKey dif_vif_key;
MeasurementType measurement_type;
Vif vif;
std::set<VIFCombinable> combinable_vifs;
StorageNr storage_nr;
TariffNr tariff_nr;
SubUnitNr subunit_nr;
std::string value;
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(int off,
DifVifKey dvk,
MeasurementType mt,
Vif vi,
std::set<VIFCombinable> vc,
StorageNr st,
TariffNr ta,
SubUnitNr su,
std::string &val) :
offset(off),
dif_vif_key(dvk),
measurement_type(mt),
vif(vi),
combinable_vifs(vc),
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") {}
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);
bool hasVifes();
void setFieldInfo(FieldInfo *fi) { field_info_ = fi; }
FieldInfo *getFieldInfo() { return field_info_; }
std::string str();
private:
FieldInfo *field_info_ {}; // The field info selected to decode this entry.
@ -209,6 +345,9 @@ struct FieldMatcher
bool match_vif_range = false;
VIFRange vif_range { VIFRange::Any };
// Match any vif combinables.
std::set<VIFCombinable> vif_combinables;
// Match the storage nr. If no storage is specified, default to match only 0.
bool match_storage_nr = true;
StorageNr storage_nr_from { 0 };
@ -242,6 +381,9 @@ struct FieldMatcher
vif_range = v;
match_vif_range = (v != VIFRange::Any);
return *this; }
FieldMatcher &add(VIFCombinable v) {
vif_combinables.insert(v);
return *this; }
FieldMatcher &set(StorageNr s) {
storage_nr_from = storage_nr_to = s;
match_storage_nr = (s != AnyStorageNr);

Wyświetl plik

@ -126,7 +126,7 @@ void MeterApator162::processContent(Telegram *t)
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) };
extractDVdouble(&vendor_values, "0413", &offset, &total_water_consumption_m3_);
total = "*** 10-"+total+" total consumption (%f m3)";
t->addSpecialExplanation(offset, 4, KindOfData::CONTENT, Understanding::FULL, total.c_str(), total_water_consumption_m3_);

Wyświetl plik

@ -110,7 +110,7 @@ void MeterCompact5::processContent(Telegram *t)
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);
@ -122,7 +122,7 @@ void MeterCompact5::processContent(Telegram *t)
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

@ -111,9 +111,6 @@
X(UNISMART, MANUFACTURER_AMX, 0x03, 0x01) \
X(VARIO451, MANUFACTURER_TCH, 0x04, 0x27) \
X(VARIO451, MANUFACTURER_TCH, 0xc3, 0x27) \
X(WATERSTARM, MANUFACTURER_DWZ, 0x06, 0x02) \
X(WATERSTARM, MANUFACTURER_DWZ, 0x07, 0x02) \
X(WATERSTARM, MANUFACTURER_EFE, 0x07, 0x03) \
X(WHE46X, MANUFACTURER_LSE, 0x08, 0x18) \
X(WHE5X, MANUFACTURER_LSE, 0x08, 0x34) \
X(WEH_07, MANUFACTURER_WEH, 0x07, 0xfe) \

Wyświetl plik

@ -100,7 +100,7 @@ void MKRadio3::processContent(Telegram *t)
string prev_date_str;
strprintf(prev_date_str, "%04x", prev_date);
uint offset = t->parsed.size() + 1;
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x6c, 0, 0, 0, prev_date_str) };
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x6c, {}, 0, 0, 0, prev_date_str) };
t->explanations.push_back(Explanation(offset, 1, prev_date_str, KindOfData::CONTENT, Understanding::FULL));
t->addMoreExplanation(offset, " previous date (%s)", previous_date_.c_str());
@ -112,7 +112,7 @@ void MKRadio3::processContent(Telegram *t)
string prevs;
strprintf(prevs, "%02x%02x", prev_lo, prev_hi);
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, " prev consumption (%f m3)", prev);
@ -125,7 +125,7 @@ void MKRadio3::processContent(Telegram *t)
string current_date_str;
strprintf(current_date_str, "%04x", current_date);
offset = t->parsed.size() + 5;
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x6c, 0, 0, 0, current_date_str) };
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x6c, {}, 0, 0, 0, current_date_str) };
t->explanations.push_back(Explanation(offset, 1, current_date_str, KindOfData::CONTENT, Understanding::FULL));
t->addMoreExplanation(offset, " current date (%s)", current_date_.c_str());
@ -137,7 +137,7 @@ void MKRadio3::processContent(Telegram *t)
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, " curr consumption (%f m3)", curr);

Wyświetl plik

@ -83,7 +83,7 @@ void MKRadio4::processContent(Telegram *t)
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, " prev consumption (%f m3)", prev);
@ -94,7 +94,7 @@ void MKRadio4::processContent(Telegram *t)
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, " curr consumption (%f m3)", curr);

Wyświetl plik

@ -109,7 +109,7 @@ void MeterVario451::processContent(Telegram *t)
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);
@ -120,7 +120,7 @@ void MeterVario451::processContent(Telegram *t)
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);

Wyświetl plik

@ -2468,7 +2468,9 @@ bool FieldInfo::extractString(Meter *m, Telegram *t, DVEntry *dve)
found = true;
}
else if (matcher_.vif_range == VIFRange::EnhancedIdentification ||
matcher_.vif_range == VIFRange::FabricationNo)
matcher_.vif_range == VIFRange::FabricationNo ||
matcher_.vif_range == VIFRange::ModelVersion ||
matcher_.vif_range == VIFRange::ParameterSet)
{
string extracted_id;
dve->extractReadableString(&extracted_id);

Wyświetl plik

@ -105,7 +105,6 @@ LIST_OF_METER_TYPES
X(sontex868, T1_bit, HeatCostAllocationMeter, SONTEX868, Sontex868) \
X(topaseskr, T1_bit, WaterMeter, TOPASESKR, TopasEsKr) \
X(vario451, T1_bit, HeatMeter, VARIO451, Vario451) \
X(waterstarm, C1_bit|T1_bit, WaterMeter,WATERSTARM, WaterstarM) \
X(whe46x, S1_bit, HeatCostAllocationMeter, WHE46X, Whe46x) \
X(whe5x, S1_bit, HeatCostAllocationMeter, WHE5X, Whe5x) \
X(lse_08, S1_bit|C1_bit, HeatCostAllocationMeter, LSE_08, LSE_08) \