Skip to content

Commit

Permalink
Add dynaic driver add_combinable and storage_nr.
Browse files Browse the repository at this point in the history
  • Loading branch information
weetmuts committed Feb 15, 2024
1 parent dbd9969 commit 097f91f
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 45 deletions.
2 changes: 2 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
FROM alpine AS build
RUN apk add --no-cache alpine-sdk gcc linux-headers libxml2-dev cmake libusb-dev bash samurai

ADD https://api.github.com/repos/wmbusmeters/wmbusmeters/git/refs/heads/master version.json
RUN git clone https://github.com/steve-m/librtlsdr.git && \
git clone https://github.com/wmbusmeters/wmbusmeters.git && \
git clone https://github.com/weetmuts/rtl-wmbus.git && \
Expand Down
122 changes: 87 additions & 35 deletions src/driver_dynamic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,12 @@ string get_translation(XMQDoc *doc, XMQNode *node, string name, string lang);
string check_calculate(const char *formula, DriverDynamic *dd);
Unit check_display_unit(const char *display_unit, DriverDynamic *dd);

void check_set_measurement_type(const char *measurement_type_s, FieldMatcher *fm, DriverDynamic *dd);
void check_set_vif_range(const char *vif_range_s, FieldMatcher *fm, DriverDynamic *dd);
void checked_set_measurement_type(const char *measurement_type_s, FieldMatcher *fm, DriverDynamic *dd);
void checked_set_vif_range(const char *vif_range_s, FieldMatcher *fm, DriverDynamic *dd);
void checked_set_storagenr_range(const char *storagenr_range_s, FieldMatcher *fm, DriverDynamic *dd);
void checked_set_tariffnr_range(const char *tariffnr_range_s, FieldMatcher *fm, DriverDynamic *dd);
void checked_set_subunitnr_range(const char *subunitnr_range_s, FieldMatcher *fm, DriverDynamic *dd);
void checked_add_vif_combinable(const char *vif_range_s, FieldMatcher *fm, DriverDynamic *dd);

const char *line = "-------------------------------------------------------------------------------";

Expand Down Expand Up @@ -107,26 +111,19 @@ bool DriverDynamic::load(DriverInfo *di, const string &file_name, const char *co
DriverDynamic::DriverDynamic(MeterInfo &mi, DriverInfo &di) :
MeterCommonImplementation(mi, di), file_name_(di.getDynamicFileName())
{
XMQDoc *doc = di.getDynamicDriver();
assert(doc);

verbose("(driver) constructing driver %s from already loaded file %s\n",
di.name().str().c_str(),
fileName().c_str());

try
{
xmqForeach(doc, NULL, "/driver/use", (XMQNodeCallback)add_use, this);
}
catch (...)
{
}
XMQDoc *doc = di.getDynamicDriver();
assert(doc);

try
{
verbose("(driver) constructing driver %s from already loaded file %s\n",
di.name().str().c_str(),
fileName().c_str());

xmqForeach(doc, NULL, "/driver/use", (XMQNodeCallback)add_use, this);
xmqForeach(doc, NULL, "/driver/field", (XMQNodeCallback)add_field, this);
}
catch (...)
catch(...)
{
}
}
Expand Down Expand Up @@ -163,9 +160,9 @@ XMQProceed DriverDynamic::add_detect(XMQDoc *doc, XMQNode *detect, DriverInfo *d
char a = mfct[0];
char b = mfct[1];
char c = mfct[2];
if (!(a >= 'A' && a < 'Z' &&
b >= 'A' && b < 'Z' &&
c >= 'A' && c < 'Z'))
if (!(a >= 'A' && a <= 'Z' &&
b >= 'A' && b <= 'Z' &&
c >= 'A' && c <= 'Z'))
{
warning("(driver) error in %s, bad manufacturer in mvt triplet: %s\n"
"%s\n"
Expand Down Expand Up @@ -339,22 +336,22 @@ XMQProceed DriverDynamic::add_match(XMQDoc *doc, XMQNode *match, DriverDynamic *
{
FieldMatcher *fm = dd->tmp_matcher_;

check_set_measurement_type(xmqGetString(doc, match, "measurement_type"), fm, dd);
checked_set_measurement_type(xmqGetString(doc, match, "measurement_type"), fm, dd);

check_set_vif_range(xmqGetString(doc, match, "vif_range"), fm, dd);
checked_set_vif_range(xmqGetString(doc, match, "vif_range"), fm, dd);

const char *vif_range_s = xmqGetString(doc, match, "vif_range");
checked_set_storagenr_range(xmqGetString(doc, match, "storage_nr"), fm, dd);

if (vif_range_s)
{
VIFRange vif_range = toVIFRange(vif_range_s);
if (vif_range == VIFRange::None)
{
warning("(driver) error unknown measurement type %s\n", vif_range_s);
throw 1;
}
fm->set(vif_range);
}
xmqForeach(doc, match, "add_combinable", (XMQNodeCallback)add_combinable, dd);

return XMQ_CONTINUE;
}

XMQProceed DriverDynamic::add_combinable(XMQDoc *doc, XMQNode *match, DriverDynamic *dd)
{
FieldMatcher *fm = dd->tmp_matcher_;

checked_add_vif_combinable(xmqGetString(doc, match, "."), fm, dd);

return XMQ_CONTINUE;
}
Expand Down Expand Up @@ -622,7 +619,7 @@ Unit check_display_unit(const char *display_unit_s, DriverDynamic *dd)
return u;
}

void check_set_measurement_type(const char *measurement_type_s, FieldMatcher *fm, DriverDynamic *dd)
void checked_set_measurement_type(const char *measurement_type_s, FieldMatcher *fm, DriverDynamic *dd)
{
if (!measurement_type_s)
{
Expand Down Expand Up @@ -665,7 +662,7 @@ void check_set_measurement_type(const char *measurement_type_s, FieldMatcher *fm
fm->set(measurement_type);
}

void check_set_vif_range(const char *vif_range_s, FieldMatcher *fm, DriverDynamic *dd)
void checked_set_vif_range(const char *vif_range_s, FieldMatcher *fm, DriverDynamic *dd)
{
if (!vif_range_s)
{
Expand Down Expand Up @@ -701,3 +698,58 @@ void check_set_vif_range(const char *vif_range_s, FieldMatcher *fm, DriverDynami

fm->set(vif_range);
}

void checked_set_storagenr_range(const char *storagenr_range_s, FieldMatcher *fm, DriverDynamic *dd)
{
if (!storagenr_range_s) return;

auto fields = splitString(storagenr_range_s, ',');
bool ok = isNumber(fields[0]);
if (fields.size() > 1)
{
ok &= isNumber(fields[1]);
}
if (!ok || fields.size() > 2)
{
warning("(driver) error in %s, bad storagenr_range: %s\n"
"%s\n",
dd->fileName().c_str(),
storagenr_range_s,
line);
throw 1;
}

if (fields.size() == 1)
{
fm->set(StorageNr(atoi(fields[0].c_str())));
}
else
{
fm->set(StorageNr(atoi(fields[0].c_str())),
StorageNr(atoi(fields[1].c_str())));
}
}

void checked_add_vif_combinable(const char *vif_combinable_s, FieldMatcher *fm, DriverDynamic *dd)
{
if (!vif_combinable_s) return;

VIFCombinable vif_combinable = toVIFCombinable(vif_combinable_s);

if (vif_combinable == VIFCombinable::None)
{
warning("(driver) error in %s, bad vif_combinable: %s\n"
"%s\n"
"Available vif combinables:\n"
"%s\n"
"%s\n",
dd->fileName().c_str(),
vif_combinable_s,
line,
availableVIFCombinables().c_str(),
line);
throw 1;
}

fm->add(vif_combinable);
}
1 change: 1 addition & 0 deletions src/driver_dynamic.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct DriverDynamic : public virtual MeterCommonImplementation
static XMQProceed add_use(XMQDoc *doc, XMQNode *field, DriverDynamic *dd);
static XMQProceed add_field(XMQDoc *doc, XMQNode *field, DriverDynamic *dd);
static XMQProceed add_match(XMQDoc *doc, XMQNode *match, DriverDynamic *dd);
static XMQProceed add_combinable(XMQDoc *doc, XMQNode *match, DriverDynamic *dd);

const string &fileName() { return file_name_; }

Expand Down
43 changes: 36 additions & 7 deletions src/dvparser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,17 @@ LIST_OF_VIF_RANGES
return VIFRange::None;
}

VIFCombinable toVIFCombinable(const char *s)
{
if (!strcmp(s, "None")) return VIFCombinable::None;
if (!strcmp(s, "Any")) return VIFCombinable::Any;
#define X(name,from,to) if (!strcmp(s, #name)) return VIFCombinable::name;
LIST_OF_VIF_COMBINABLES
#undef X

return VIFCombinable::None;
}

const char *toString(VIFCombinable v)
{
switch (v) {
Expand Down Expand Up @@ -1299,13 +1310,16 @@ bool FieldMatcher::matches(DVEntry &dv_entry)
}

// Test ranges and types.
bool b =
(!match_vif_range || isInsideVIFRange(dv_entry.vif, vif_range)) &&
(!match_vif_raw || dv_entry.vif == vif_raw) &&
(!match_measurement_type || dv_entry.measurement_type == measurement_type) &&
(!match_storage_nr || (dv_entry.storage_nr >= storage_nr_from && dv_entry.storage_nr <= storage_nr_to)) &&
(!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));
bool range = (!match_vif_range || isInsideVIFRange(dv_entry.vif, vif_range));
bool raw = (!match_vif_raw || dv_entry.vif == vif_raw);
bool type = (!match_measurement_type || dv_entry.measurement_type == measurement_type);
bool storage = (!match_storage_nr || (dv_entry.storage_nr >= storage_nr_from && dv_entry.storage_nr <= storage_nr_to));
bool tariff = (!match_tariff_nr || (dv_entry.tariff_nr >= tariff_nr_from && dv_entry.tariff_nr <= tariff_nr_to));
bool subunit = (!match_subunit_nr || (dv_entry.subunit_nr >= subunit_nr_from && dv_entry.subunit_nr <= subunit_nr_to));

//printf("Match? range=%d raw=%d type=%d storage=%d tariff=%d subunit=%d \n", range, raw, type, storage, tariff, subunit);

bool b = range & raw & type & storage & tariff & subunit;

if (!b) return false;

Expand Down Expand Up @@ -1501,3 +1515,18 @@ LIST_OF_VIF_RANGES
available_vif_ranges_.pop_back();
return available_vif_ranges_;
}

string available_vif_combinables_;

const string &availableVIFCombinables()
{
if (available_vif_combinables_ != "") return available_vif_combinables_;

#define X(n,from,to) available_vif_combinables_ += string(#n) + "\n";
LIST_OF_VIF_COMBINABLES
#undef X

// Remove last newline
available_vif_combinables_.pop_back();
return available_vif_combinables_;
}
4 changes: 3 additions & 1 deletion src/dvparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
X(ExternalTemperature,0x64,0x67, Quantity::Temperature, Unit::C) \
X(Pressure,0x68,0x6B, Quantity::Pressure, Unit::BAR) \
X(HeatCostAllocation,0x6E,0x6E, Quantity::HCA, Unit::HCA) \
X(Date,0x6C,0x6C, Quantity::PointInTime, Unit::DateTimeLT) \
X(Date,0x6C,0x6C, Quantity::PointInTime, Unit::DateLT) \
X(DateTime,0x6D,0x6D, Quantity::PointInTime, Unit::DateTimeLT) \
X(EnergyMJ,0x08,0x0F, Quantity::Energy, Unit::MJ) \
X(EnergyWh,0x00,0x07, Quantity::Energy, Unit::KWH) \
Expand Down Expand Up @@ -208,6 +208,7 @@ struct VIFCombinableRaw {
uint16_t value;
};

VIFCombinable toVIFCombinable(const char *s);
VIFCombinable toVIFCombinable(int i);
const char *toString(VIFCombinable v);

Expand Down Expand Up @@ -588,5 +589,6 @@ bool extractDVdate(std::map<std::string,std::pair<int,DVEntry>> *values,


const std::string &availableVIFRanges();
const std::string &availableVIFCombinables();

#endif
1 change: 0 additions & 1 deletion src/meters.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1313,7 +1313,6 @@ void MeterCommonImplementation::processFieldExtractors(Telegram *t)
if (fi.hasMatcher() && fi.matches(dve))
{
current_match_nr++;

if (fi.matcher().index_nr != IndexNr(current_match_nr) &&
!fi.matcher().expectedToMatchAgainstMultipleEntries())
{
Expand Down
22 changes: 22 additions & 0 deletions src/testinternals.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ using namespace std;
bool verbose_ = false;

#define LIST_OF_TESTS \
X(dynamic_loading)\
X(crc) \
X(dvparser) \
X(devices) \
Expand Down Expand Up @@ -2028,6 +2029,8 @@ LIST_OF_QUANTITIES
test_si_convert(2211717, 2211717, Unit::FACTOR, "counter", Unit::COUNTER, "counter", Quantity::Dimensionless, &from_set, &to_set);
test_si_convert(2211717, 2211717, Unit::NUMBER, "counter", Unit::COUNTER, "counter", Quantity::Dimensionless, &from_set, &to_set);
test_si_convert(2211717, 2211717, Unit::FACTOR, "counter", Unit::NUMBER, "counter", Quantity::Dimensionless, &from_set, &to_set);
test_si_convert(2211717, 2211717, Unit::PERCENTAGE, "counter", Unit::NUMBER, "counter", Quantity::Dimensionless, &from_set, &to_set);
test_si_convert(2211717, 2211717, Unit::NUMBER, "counter", Unit::PERCENTAGE, "counter", Quantity::Dimensionless, &from_set, &to_set);

check_units_tested(from_set, to_set, Quantity::Dimensionless);

Expand Down Expand Up @@ -2588,3 +2591,22 @@ void test_formulas_stringinterpolation()
}

}

void test_dynamic_loading()
{
VIFRange vr = toVIFRange("Date");

if (vr != VIFRange::Date)
{
printf("ERROR in dynamic loading got %s but expected %s!\n",
toString(vr), toString(VIFRange::Date));
}

vr = toVIFRange("DateTime");

if (vr != VIFRange::DateTime)
{
printf("ERROR in dynamic loading got %s but expected %s!\n",
toString(vr), toString(VIFRange::DateTime));
}
}
5 changes: 4 additions & 1 deletion src/units.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ using namespace std;
X(NUMBER, COUNTER, {vto=vfrom;}) \
X(FACTOR, NUMBER, {vto=vfrom;}) \
X(NUMBER, FACTOR, {vto=vfrom;}) \
X(PERCENTAGE, NUMBER, {vto=vfrom;}) \
X(NUMBER, PERCENTAGE, {vto=vfrom;}) \
X(UnixTimestamp,DateTimeLT, {vto=vfrom; }) \
X(DateTimeLT,UnixTimestamp, {vto=vfrom; }) \
X(DateLT,UnixTimestamp, {vto=vfrom; }) \
Expand Down Expand Up @@ -122,6 +124,7 @@ using namespace std;
X(COUNTER, 1.0, SIExp()) \
X(FACTOR, 1.0, SIExp()) \
X(NUMBER, 1.0, SIExp()) \
X(PERCENTAGE, 1.0, SIExp()) \
X(TXT, 1.0, SIExp()) \


Expand Down Expand Up @@ -830,7 +833,7 @@ const char *availableUnits()
if (available_units_[0]) return available_units_;

#define X(n,suffix,sn,q,ln) if (Unit::n != Unit::Unknown) { \
strcat(available_units_, #suffix); strcat(available_units_, "\n"); \
strcat(available_units_, #suffix); strcat(available_units_, " "); \
assert(strlen(available_units_) < 1024); }
LIST_OF_UNITS
#undef X
Expand Down

0 comments on commit 097f91f

Please sign in to comment.