kopia lustrzana https://github.com/weetmuts/wmbusmeters
Pattern generated fields based on storage nr calculation now work.
rodzic
bccee1a170
commit
addff11eb7
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
43
src/main.cc
43
src/main.cc
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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: $?"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue