Pattern generated fields based on storage nr calculation now work.

pull/708/head
Fredrik Öhrström 2022-11-24 16:22:37 +01:00
rodzic bccee1a170
commit addff11eb7
9 zmienionych plików z 121 dodań i 38 usunięć

Wyświetl plik

@ -27,7 +27,7 @@ namespace
static bool ok = registerDriver([](DriverInfo&di)
{
di.setName("evo868");
di.setDefaultFields("name,id,total_m3,set_date,consumption_at_set_date_m3,timestamp");
di.setDefaultFields("name,id,total_m3,current_status,consumption_at_set_date_m3,set_date,timestamp");
di.setMeterType(MeterType::WaterMeter);
di.addLinkMode(LinkMode::T1);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
@ -59,7 +59,7 @@ namespace
},
});
addOptionalCommonFields("fabrication_no,meter_datetime");
addOptionalCommonFields("fabrication_no");
addOptionalFlowRelatedFields("total_m3");
addNumericFieldWithExtractor(
@ -140,12 +140,21 @@ namespace
.set(StorageNr(8),StorageNr(19))
);
addStringFieldWithExtractor(
"device_date_time",
"Date and time when the meter sent the telegram.",
PrintProperty::JSON | PrintProperty::OPTIONAL,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::DateTime)
);
}
}
// est: Votchka evo868 79787776 NOKEY
// omment: Test Maddalena EVO 868 wmbus module on water meter
// elegram=|aa4424347677787950077ac10000202f2f041306070000046d1e31b12104fd17000000000e787880048120004413c9040000426c9f2c840113c904000082016c9f2cd3013b9a0200c4016d0534a7218104fd280182046c9f2c840413c9040000c404131b00000084051300000000c405130000000084061300000000c406130000000084071300000000c407130000000084081300000000c408130000000084091300000000c4091300000000ffff|
// "media":"water","meter":"evo868","name":"Votchka","id":"79787776","total_m3":1.798,"device_date_time":"2021-01-17 17:30","current_status":"OK","fabrication_no":"002081048078","consumption_at_set_date_m3":1.225,"set_date":"2020-12-31","consumption_at_set_date_2_m3":1.225,"set_date_2":"2020-12-31","max_flow_since_datetime_m3h":0.666,"max_flow_datetime":"2021-01-07 20:05","consumption_at_history_1_m3":1.225,"history_1_date":"2020-12-31","consumption_at_history_2_m3":0.027,"history_2_date":"2020-11-30","consumption_at_history_3_m3":0,"history_3_date":"2020-10-31","consumption_at_history_4_m3":0,"history_4_date":"2020-09-30","consumption_at_history_5_m3":0,"history_5_date":"2020-08-31","consumption_at_history_6_m3":0,"history_6_date":"2020-07-31","consumption_at_history_7_m3":0,"history_7_date":"2020-06-30","consumption_at_history_8_m3":0,"history_8_date":"2020-05-31","consumption_at_history_9_m3":0,"history_9_date":"2020-04-30","consumption_at_history_10_m3":0,"history_10_date":"2020-03-31","consumption_at_history_11_m3":0,"history_11_date":"2020-02-29","consumption_at_history_12_m3":0,"history_12_date":"2020-01-31","timestamp":"1111-11-11T11:11:11Z"}
// Votchka;79787776;1.798;OK;1.225;2020-12-31;1111-11-11 11:11.11
// Test: Votchka evo868 79787776 NOKEY
// Comment: Test Maddalena EVO 868 wmbus module on water meter
// telegram=|aa4424347677787950077ac10000202f2f041306070000046d1e31b12104fd17000000000e787880048120004413c9040000426c9f2c840113c904000082016c9f2cd3013b9a0200c4016d0534a7218104fd280182046c9f2c840413c9040000c404131b00000084051300000000c405130000000084061300000000c406130000000084071300000000c407130000000084081300000000c408130000000084091300000000c4091300000000ffff|
// {"media":"water","meter":"evo868","name":"Votchka","id":"79787776","total_m3":1.798,"device_date_time":"2021-01-17 17:30","current_status":"OK","fabrication_no":"002081048078","consumption_at_set_date_m3":1.225,"set_date":"2020-12-31","consumption_at_set_date_2_m3":1.225,"set_date_2":"2020-12-31","max_flow_since_datetime_m3h":0.666,"max_flow_datetime":"2021-01-07 20:05","consumption_at_history_1_m3":1.225,"history_1_date":"2020-12-31","consumption_at_history_2_m3":0.027,"history_2_date":"2020-11-30","consumption_at_history_3_m3":0,"history_3_date":"2020-10-31","consumption_at_history_4_m3":0,"history_4_date":"2020-09-30","consumption_at_history_5_m3":0,"history_5_date":"2020-08-31","consumption_at_history_6_m3":0,"history_6_date":"2020-07-31","consumption_at_history_7_m3":0,"history_7_date":"2020-06-30","consumption_at_history_8_m3":0,"history_8_date":"2020-05-31","consumption_at_history_9_m3":0,"history_9_date":"2020-04-30","consumption_at_history_10_m3":0,"history_10_date":"2020-03-31","consumption_at_history_11_m3":0,"history_11_date":"2020-02-29","consumption_at_history_12_m3":0,"history_12_date":"2020-01-31","timestamp":"1111-11-11T11:11:11Z"}
// |Votchka;79787776;1.798;OK;1.225;2020-12-31;1111-11-11 11:11.11

Wyświetl plik

@ -1030,8 +1030,6 @@ StringInterpolatorImplementation::~StringInterpolatorImplementation()
bool StringInterpolatorImplementation::parse(const std::string &f)
{
debug("(stringinterpolator) parsing \"%s\"\n", f.c_str());
strings_.clear();
formulas_.clear();
@ -1042,7 +1040,6 @@ bool StringInterpolatorImplementation::parse(const std::string &f)
{
// Push the string up to the brace.
string part = f.substr(prev_string_start, next_start_brace - prev_string_start);
debug("(stringinterpolator) string \"%s\"\n", part.c_str());
strings_.push_back(part);
// Find the end of the formula.
@ -1050,7 +1047,6 @@ bool StringInterpolatorImplementation::parse(const std::string &f)
if (next_end_brace == string::npos) return false; // Oups, missing closing }
string formula = f.substr(next_start_brace+1, next_end_brace - next_start_brace - 1);
debug("(stringinterpolator) formula \"%s\"\n", formula.c_str());
formulas_.push_back(unique_ptr<Formula>(newFormula()));
bool ok = formulas_.back()->parse(NULL, formula);
@ -1065,7 +1061,6 @@ bool StringInterpolatorImplementation::parse(const std::string &f)
if (prev_string_start < f.length())
{
string part = f.substr(prev_string_start);
debug("(stringinterpolator) last string \"%s\"\n", part.c_str());
strings_.push_back(part);
}

Wyświetl plik

@ -210,21 +210,40 @@ void list_shell_envs(Configuration *config, string meter_driver)
meter = di.construct(mi);
}
meter->printMeter(&t,
&ignore1,
&ignore2, config->separator,
&ignore3,
&envs,
&config->extra_constant_fields,
&config->selected_fields,
false);
printf("METER_DEVICE\n"
"METER_ID\n"
"METER_JSON\n"
"METER_MEDIA\n"
"METER_TYPE\n"
"METER_NAME\n"
"METER_RSSI_DBM\n"
"METER_TIMESTAMP\n"
"METER_TIMESTAMP_LT\n"
"METER_TIMESTAMP_UT\n"
"METER_TIMESTAMP_UTC\n");
for (auto &e : envs)
for (auto &fi : meter->fieldInfos())
{
int p = e.find('=');
string key = e.substr(0,p);
printf("%s\n", key.c_str());
if (fi.vname() == "") continue;
string name = fi.vname();
std::transform(name.begin(), name.end(), name.begin(), ::toupper);
if (fi.xuantity() != Quantity::Text)
{
printf("METER_%s_%s\n",name.c_str(), unitToStringUpperCase(fi.defaultUnit()).c_str());
}
else
{
printf("METER_%s\n",name.c_str());
}
}
for (string &s : meter->extraConstantFields())
{
string name = s;
std::transform(name.begin(), name.end(), name.begin(), ::toupper);
printf("METER_%s\n", name.c_str());
}
}
void list_fields(Configuration *config, string meter_driver)

Wyświetl plik

@ -788,6 +788,11 @@ vector<FieldInfo> &MeterCommonImplementation::fieldInfos()
return field_infos_;
}
vector<string> &MeterCommonImplementation::extraConstantFields()
{
return extra_constant_fields_;
}
string MeterCommonImplementation::name()
{
return name_;
@ -1446,7 +1451,7 @@ void MeterCommonImplementation::processContent(Telegram *t)
{
}
void MeterCommonImplementation::setNumericValue(FieldInfo *fi, Unit u, double v)
void MeterCommonImplementation::setNumericValue(FieldInfo *fi, DVEntry *dve, Unit u, double v)
{
if (fi->hasSetNumericValueOverride())
{
@ -1456,8 +1461,18 @@ void MeterCommonImplementation::setNumericValue(FieldInfo *fi, Unit u, double v)
}
// Store value in default meter location for numeric values.
string field_name_no_unit = fi->vname();
numeric_values_[pair<string,Quantity>(field_name_no_unit,fi->xuantity())] = NumericField(u, v, fi);
string field_name_no_unit;
if (dve == NULL)
{
field_name_no_unit = fi->vname();
}
else
{
field_name_no_unit = fi->generateFieldNameNoUnit(dve);
}
numeric_values_[pair<string,Quantity>(field_name_no_unit, fi->xuantity())] = NumericField(u, v, fi);
}
void MeterCommonImplementation::setNumericValue(string vname, Unit u, double v)
@ -1470,7 +1485,7 @@ void MeterCommonImplementation::setNumericValue(string vname, Unit u, double v)
warning("(meter) cannot set numeric value %g %s for non-existant field \"%s\" %s\n", v, unitToStringLowerCase(u).c_str(), vname.c_str(), toString(q));
return;
}
setNumericValue(fi, u, v);
setNumericValue(fi, NULL, u, v);
}
bool MeterCommonImplementation::hasValue(FieldInfo *fi)
@ -1511,6 +1526,25 @@ double MeterCommonImplementation::getNumericValue(FieldInfo *fi, Unit to)
return convert(nf.value, nf.unit, to);
}
double MeterCommonImplementation::getNumericValue(string vname, Unit to)
{
Quantity q = toQuantity(to);
FieldInfo *fi = findFieldInfo(vname, q);
if (fi != NULL && fi->hasGetNumericValueOverride())
{
return fi->getNumericValueOverride(to);
}
pair<string,Quantity> key(vname,q);
if (numeric_values_.count(key) == 0)
{
return std::numeric_limits<double>::quiet_NaN(); // This is translated into a null in the json.
}
NumericField &nf = numeric_values_[key];
return convert(nf.value, nf.unit, to);
}
void MeterCommonImplementation::setStringValue(FieldInfo *fi, string v)
{
if (fi->hasSetStringValueOverride())
@ -1718,7 +1752,7 @@ string FieldInfo::renderJson(Meter *m, DVEntry *dve)
}
else
{
s += "\""+field_name+"_"+default_unit+"\":"+valueToString(m->getNumericValue(this, defaultUnit()), defaultUnit());
s += "\""+field_name+"_"+default_unit+"\":"+valueToString(m->getNumericValue(field_name, defaultUnit()), defaultUnit());
}
return s;
@ -2255,7 +2289,7 @@ void FieldInfo::performCalculation(Meter *m)
assert(hasFormula());
double value = formula_->calculate(defaultUnit());
m->setNumericValue(this, defaultUnit(), value);
m->setNumericValue(this, NULL, defaultUnit(), value);
}
bool FieldInfo::hasMatcher()
@ -2358,7 +2392,7 @@ bool FieldInfo::extractNumeric(Meter *m, Telegram *t, DVEntry *dve)
unitToStringLowerCase(default_unit_).c_str(),
extracted_double_value);
}
m->setNumericValue(this, default_unit_, convert(extracted_double_value, decoded_unit, default_unit_));
m->setNumericValue(this, dve, default_unit_, convert(extracted_double_value, decoded_unit, default_unit_));
t->addMoreExplanation(dve->offset, renderJson(m, dve));
found = true;
}

Wyświetl plik

@ -411,6 +411,7 @@ struct Meter
virtual string idsc() = 0;
// This meter can report these fields, like total_m3, temp_c.
virtual vector<FieldInfo> &fieldInfos() = 0;
virtual vector<string> &extraConstantFields() = 0;
// Either the default fields specified in the driver, or override fields in the meter configuration file.
virtual vector<string> &selectedFields() = 0;
virtual void setSelectedFields(vector<string> &f) = 0;
@ -428,7 +429,8 @@ struct Meter
virtual bool usesPolling() = 0;
virtual void setNumericValue(string vname, Unit u, double v) = 0;
virtual void setNumericValue(FieldInfo *fi, Unit u, double v) = 0;
virtual void setNumericValue(FieldInfo *fi, DVEntry *dve, Unit u, double v) = 0;
virtual double getNumericValue(string vname, Unit u) = 0;
virtual double getNumericValue(FieldInfo *fi, Unit u) = 0;
virtual void setStringValue(FieldInfo *fi, std::string v) = 0;
virtual std::string getStringValue(FieldInfo *fi) = 0;

Wyświetl plik

@ -60,6 +60,7 @@ struct MeterCommonImplementation : public virtual Meter
vector<string>& ids();
string idsc();
vector<FieldInfo> &fieldInfos();
vector<string> &extraConstantFields();
string name();
MeterDriver driver();
DriverName driverName();
@ -250,7 +251,8 @@ protected:
virtual void processContent(Telegram *t);
void setNumericValue(string vname, Unit u, double v);
void setNumericValue(FieldInfo *fi, Unit u, double v);
void setNumericValue(FieldInfo *fi, DVEntry *dve, Unit u, double v);
double getNumericValue(string vname, Unit u);
double getNumericValue(FieldInfo *fi, Unit u);
void setStringValue(FieldInfo *fi, std::string v);
std::string getStringValue(FieldInfo *fi);

Wyświetl plik

@ -20,6 +20,11 @@ then
then
echo "OK: $TESTNAME"
TESTRESULT="OK"
else
if [ "$USE_MELD" = "true" ]
then
meld $TEST/test_expected.txt $TEST/test_response.txt
fi
fi
fi
@ -30,11 +35,11 @@ if [ "$TESTRESULT" = "ERROR" ]; then echo ERROR: $TESTNAME; exit 1; fi
TESTNAME="Test additional shell envs from cmdline"
TESTRESULT="ERROR"
$PROG --json_floor=5 --json_house="alfa beta" --listenvs=multical21 > $TEST/test_output.txt 2> $TEST/test_stderr.txt
$PROG --json_floor=5 --json_house="alfa beta" --listenvs=multical21 2> $TEST/test_stderr.txt | sort > $TEST/test_output.txt
ENVS=$(cat $TEST/test_output.txt | tr '\n' ' ')
cat > $TEST/test_expected.txt <<EOF
cat <<EOF | sort > $TEST/test_expected.txt
METER_JSON
METER_ID
METER_NAME
@ -58,8 +63,6 @@ METER_TIME_DRY
METER_TIME_REVERSED
METER_TIME_LEAKING
METER_TIME_BURSTING
METER_floor
METER_house
EOF
diff $TEST/test_expected.txt $TEST/test_output.txt
@ -67,6 +70,11 @@ if [ "$?" = "0" ]
then
echo "OK: $TESTNAME"
TESTRESULT="OK"
else
if [ "$USE_MELD" = "true" ]
then
meld $TEST/test_expected.txt $TEST/test_output.txt
fi
fi
if [ "$TESTRESULT" = "ERROR" ]; then echo ERROR: $TESTNAME; exit 1; fi

Wyświetl plik

@ -42,6 +42,10 @@ do
TESTRESULT="OK"
else
TESTRESULT="ERROR"
if [ "$USE_MELD" = "true" ]
then
meld $TEST/test_expected_json.txt $TEST/test_response_json.txt
fi
fi
else
echo "wmbusmeters returned error code: $?"

Wyświetl plik

@ -21,6 +21,7 @@ METER_TIMESTAMP_UTC
METER_TIMESTAMP_UT
METER_TIMESTAMP_LT
METER_DEVICE
METER_DEVICE_DATE_TIME
METER_RSSI_DBM
METER_TOTAL_ENERGY_CONSUMPTION_KWH
METER_CURRENT_POWER_CONSUMPTION_KW
@ -29,7 +30,6 @@ METER_CURRENT_POWER_PRODUCTION_KW
METER_VOLTAGE_AT_PHASE_1_Volt
METER_VOLTAGE_AT_PHASE_2_Volt
METER_VOLTAGE_AT_PHASE_3_Volt
METER_DEVICE_DATE_TIME
METER_TOTAL_ENERGY_CONSUMPTION_TARIFF_1_KWH
METER_TOTAL_ENERGY_CONSUMPTION_TARIFF_2_KWH
METER_TOTAL_ENERGY_CONSUMPTION_TARIFF_3_KWH
@ -45,6 +45,11 @@ then
then
echo OK: $TESTNAME
TESTRESULT="OK"
else
if [ "$USE_MELD" = "true" ]
then
meld $TEST/test_expected.txt $TEST/test_output.txt
fi
fi
fi
@ -90,6 +95,11 @@ then
then
echo OK: $TESTNAME
TESTRESULT="OK"
else
if [ "$USE_MELD" = "true" ]
then
meld $TEST/test_expected.txt $TEST/test_output.txt
fi
fi
fi