kopia lustrzana https://github.com/weetmuts/wmbusmeters
New field printing works for partially converted sharky driver.
rodzic
3e56671bfc
commit
ebae419f82
|
@ -261,6 +261,7 @@ As {options} you can use:
|
|||
--nodeviceexit if no wmbus devices are found, then exit immediately
|
||||
--normal for normal logging
|
||||
--oneshot wait for an update from each meter, then quit
|
||||
--ppjson pretty print the json
|
||||
--resetafter=<time> reset the wmbus dongle regularly, default is 23h
|
||||
--selectfields=id,timestamp,total_m3 select only these fields to be printed (--listfields=<meter> to list available fields)
|
||||
--separator=<c> change field separator to c
|
||||
|
|
|
@ -242,6 +242,12 @@ static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int ar
|
|||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "--ppjson"))
|
||||
{
|
||||
c->pretty_print_json = true;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(argv[i], "--format=", 9))
|
||||
{
|
||||
if (!strcmp(argv[i]+9, "json"))
|
||||
|
|
|
@ -95,6 +95,7 @@ struct Configuration
|
|||
bool ignore_duplicate_telegrams = true; // Default is to ignore duplicates.
|
||||
std::string logfile;
|
||||
bool json {};
|
||||
bool pretty_print_json {};
|
||||
bool fields {};
|
||||
char separator { ';' };
|
||||
std::vector<std::string> telegram_shells;
|
||||
|
|
|
@ -23,7 +23,6 @@ struct MeterSharky : public virtual MeterCommonImplementation
|
|||
MeterSharky(MeterInfo &mi, DriverInfo &di);
|
||||
|
||||
private:
|
||||
double total_energy_kwh_ {};
|
||||
double total_energy_tariff1_kwh_ {};
|
||||
double total_volume_m3_ {};
|
||||
double total_volume_tariff2_m3_ {};
|
||||
|
@ -58,8 +57,8 @@ MeterSharky::MeterSharky(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementat
|
|||
IndexNr(1),
|
||||
PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT,
|
||||
"The total heat energy consumption recorded by this meter.",
|
||||
SET_FUNC(total_energy_kwh_, Unit::KWH),
|
||||
GET_FUNC(total_energy_kwh_, Unit::KWH));
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
addNumericFieldWithExtractor(
|
||||
"total_energy_consumption_tariff1",
|
||||
|
@ -73,21 +72,19 @@ MeterSharky::MeterSharky(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementat
|
|||
IndexNr(1),
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
"The total heat energy consumption recorded by this meter on tariff 1.",
|
||||
SET_FUNC(total_energy_tariff1_kwh_, Unit::KWH),
|
||||
GET_FUNC(total_energy_tariff1_kwh_, Unit::KWH));
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
addNumericFieldWithExtractor(
|
||||
"total_volume",
|
||||
"The total heating media volume recorded by this meter.",
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
Quantity::Volume,
|
||||
VifScaling::Auto,
|
||||
FieldMatcher::build()
|
||||
.set(MeasurementType::Instantaneous)
|
||||
.set(VIFRange::Volume)
|
||||
,
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
"The total heating media volume recorded by this meter.",
|
||||
SET_FUNC(total_volume_m3_, Unit::M3),
|
||||
GET_FUNC(total_volume_m3_, Unit::M3));
|
||||
);
|
||||
|
||||
addNumericFieldWithExtractor(
|
||||
"total_volume_tariff2",
|
||||
|
@ -101,8 +98,8 @@ MeterSharky::MeterSharky(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementat
|
|||
IndexNr(1),
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
"The total heating media volume recorded by this meter on tariff 2.",
|
||||
SET_FUNC(total_volume_tariff2_m3_, Unit::M3),
|
||||
GET_FUNC(total_volume_tariff2_m3_, Unit::M3));
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
addNumericFieldWithExtractor(
|
||||
"volume_flow",
|
||||
|
@ -116,8 +113,8 @@ MeterSharky::MeterSharky(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementat
|
|||
IndexNr(1),
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
"The current heat media volume flow.",
|
||||
SET_FUNC(volume_flow_m3h_, Unit::M3H),
|
||||
GET_FUNC(volume_flow_m3h_, Unit::M3H));
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
addNumericFieldWithExtractor(
|
||||
"power",
|
||||
|
@ -131,8 +128,8 @@ MeterSharky::MeterSharky(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementat
|
|||
IndexNr(1),
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
"The current power consumption.",
|
||||
SET_FUNC(power_kw_, Unit::KW),
|
||||
GET_FUNC(power_kw_, Unit::KW));
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
addNumericFieldWithExtractor(
|
||||
"flow_temperature",
|
||||
|
@ -146,8 +143,8 @@ MeterSharky::MeterSharky(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementat
|
|||
IndexNr(1),
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
"The current forward heat media temperature.",
|
||||
SET_FUNC(flow_temperature_c_, Unit::C),
|
||||
GET_FUNC(flow_temperature_c_, Unit::C));
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
addNumericFieldWithExtractor(
|
||||
"return_temperature",
|
||||
|
@ -161,8 +158,8 @@ MeterSharky::MeterSharky(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementat
|
|||
IndexNr(1),
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
"The current return heat media temperature.",
|
||||
SET_FUNC(return_temperature_c_, Unit::C),
|
||||
GET_FUNC(return_temperature_c_, Unit::C));
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
addNumericFieldWithExtractor(
|
||||
"temperature_difference",
|
||||
|
@ -176,8 +173,8 @@ MeterSharky::MeterSharky(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementat
|
|||
IndexNr(1),
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
"The current return heat media temperature.",
|
||||
SET_FUNC(temperature_difference_c_, Unit::C),
|
||||
GET_FUNC(temperature_difference_c_, Unit::C));
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
// Test: Heat sharky ANYID NOKEY
|
||||
|
|
|
@ -108,7 +108,6 @@ bool parseDV(Telegram *t,
|
|||
vector<uchar>::iterator data,
|
||||
size_t data_len,
|
||||
map<string,pair<int,DVEntry>> *dv_entries,
|
||||
vector<DVEntry*> *dv_entries_ordered,
|
||||
vector<uchar>::iterator *format,
|
||||
size_t format_len,
|
||||
uint16_t *format_hash)
|
||||
|
@ -142,7 +141,6 @@ bool parseDV(Telegram *t,
|
|||
}
|
||||
|
||||
dv_entries->clear();
|
||||
dv_entries_ordered->clear();
|
||||
|
||||
// Data format is:
|
||||
|
||||
|
@ -345,12 +343,9 @@ bool parseDV(Telegram *t,
|
|||
SubUnitNr(subunit),
|
||||
value) };
|
||||
|
||||
(*dv_entries_ordered).push_back( &(*dv_entries)[key].second );
|
||||
DVEntry *dve = &(*dv_entries)[key].second;
|
||||
|
||||
DVEntry *dve = (*dv_entries_ordered).back();
|
||||
DVEntry *dvee = &(*dv_entries)[key].second;
|
||||
|
||||
assert(key == dve->dif_vif_key.str() && key == dvee->dif_vif_key.str());
|
||||
assert(key == dve->dif_vif_key.str());
|
||||
|
||||
if (value.length() > 0) {
|
||||
// This call increments data with datalen.
|
||||
|
|
|
@ -174,7 +174,6 @@ struct DVEntry
|
|||
TariffNr tariff_nr;
|
||||
SubUnitNr subunit_nr;
|
||||
std::string value;
|
||||
FieldInfo *field_info {}; // The field info selected to decode this entry.
|
||||
|
||||
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) {}
|
||||
|
@ -186,6 +185,11 @@ struct DVEntry
|
|||
bool extractDate(struct tm *out);
|
||||
bool extractReadableString(std::string *out);
|
||||
bool hasVifes();
|
||||
void setFieldInfo(FieldInfo *fi) { field_info_ = fi; }
|
||||
FieldInfo *getFieldInfo() { return field_info_; }
|
||||
|
||||
private:
|
||||
FieldInfo *field_info_ {}; // The field info selected to decode this entry.
|
||||
};
|
||||
|
||||
struct FieldMatcher
|
||||
|
@ -279,7 +283,6 @@ bool parseDV(Telegram *t,
|
|||
std::vector<uchar>::iterator data,
|
||||
size_t data_len,
|
||||
std::map<std::string,std::pair<int,DVEntry>> *dv_entries,
|
||||
std::vector<DVEntry*> *dv_entries_ordered,
|
||||
std::vector<uchar>::iterator *format = NULL,
|
||||
size_t format_len = 0,
|
||||
uint16_t *format_hash = NULL);
|
||||
|
|
|
@ -50,11 +50,10 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
vector<DVEntry> dv_entries_ordered;
|
||||
map<string,pair<int,DVEntry*>> dv_entries;
|
||||
map<string,pair<int,DVEntry>> dv_entries;
|
||||
|
||||
Telegram t;
|
||||
vector<uchar>::iterator i = databytes.begin();
|
||||
|
||||
parseDV(&t, databytes, i, databytes.size(), &dv_entries, &dv_entries_ordered);
|
||||
parseDV(&t, databytes, i, databytes.size(), &dv_entries);
|
||||
}
|
||||
|
|
20
src/main.cc
20
src/main.cc
|
@ -174,7 +174,9 @@ provided you with this binary. Read the full license for all details.
|
|||
|
||||
shared_ptr<Printer> create_printer(Configuration *config)
|
||||
{
|
||||
return shared_ptr<Printer>(new Printer(config->json, config->fields,
|
||||
return shared_ptr<Printer>(new Printer(config->json,
|
||||
config->pretty_print_json,
|
||||
config->fields,
|
||||
config->separator, config->meterfiles, config->meterfiles_dir,
|
||||
config->use_logfile, config->logfile,
|
||||
config->telegram_shells,
|
||||
|
@ -249,7 +251,13 @@ void list_fields(Configuration *config, string meter_driver)
|
|||
int width = 13; // Width of timestamp_utc
|
||||
for (FieldInfo &fi : meter->fieldInfos())
|
||||
{
|
||||
if ((int)fi.vname().size() > width) width = fi.vname().size();
|
||||
string name = fi.vname();
|
||||
if (fi.xuantity() != Quantity::Text)
|
||||
{
|
||||
name += "_"+unitToStringLowerCase(defaultUnitForQuantity(fi.xuantity()));
|
||||
}
|
||||
|
||||
if ((int)name.size() > width) width = name.size();
|
||||
}
|
||||
|
||||
string id = padLeft("id", width);
|
||||
|
@ -275,7 +283,13 @@ void list_fields(Configuration *config, string meter_driver)
|
|||
for (auto &fi : meter->fieldInfos())
|
||||
{
|
||||
if (fi.vname() == "") continue;
|
||||
string fn = padLeft(fi.vname(), width);
|
||||
string name = fi.vname();
|
||||
if (fi.xuantity() != Quantity::Text)
|
||||
{
|
||||
name += "_"+unitToStringLowerCase(defaultUnitForQuantity(fi.xuantity()));
|
||||
}
|
||||
|
||||
string fn = padLeft(name, width);
|
||||
printf("%s %s\n", fn.c_str(), fi.help().c_str());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -773,7 +773,8 @@ void MeterCommonImplementation::addPrint(string vname, Quantity vquantity,
|
|||
function<double(Unit)> getValueFunc, string help, PrintProperties pprops)
|
||||
{
|
||||
field_infos_.push_back(
|
||||
FieldInfo(vname,
|
||||
FieldInfo(field_infos_.size(),
|
||||
vname,
|
||||
vquantity,
|
||||
defaultUnitForQuantity(vquantity),
|
||||
VifScaling::Auto,
|
||||
|
@ -792,7 +793,8 @@ void MeterCommonImplementation::addPrint(string vname, Quantity vquantity, Unit
|
|||
function<double(Unit)> getValueFunc, string help, PrintProperties pprops)
|
||||
{
|
||||
field_infos_.push_back(
|
||||
FieldInfo(vname,
|
||||
FieldInfo(field_infos_.size(),
|
||||
vname,
|
||||
vquantity,
|
||||
unit,
|
||||
VifScaling::Auto,
|
||||
|
@ -812,7 +814,8 @@ void MeterCommonImplementation::addPrint(string vname, Quantity vquantity,
|
|||
string help, PrintProperties pprops)
|
||||
{
|
||||
field_infos_.push_back(
|
||||
FieldInfo(vname,
|
||||
FieldInfo(field_infos_.size(),
|
||||
vname,
|
||||
vquantity,
|
||||
defaultUnitForQuantity(vquantity),
|
||||
VifScaling::Auto,
|
||||
|
@ -843,7 +846,8 @@ void MeterCommonImplementation::addNumericFieldWithExtractor(
|
|||
function<double(Unit)> getValueFunc)
|
||||
{
|
||||
field_infos_.push_back(
|
||||
FieldInfo(vname,
|
||||
FieldInfo(field_infos_.size(),
|
||||
vname,
|
||||
vquantity,
|
||||
defaultUnitForQuantity(vquantity),
|
||||
vif_scaling,
|
||||
|
@ -858,27 +862,25 @@ void MeterCommonImplementation::addNumericFieldWithExtractor(
|
|||
));
|
||||
}
|
||||
|
||||
void MeterCommonImplementation::addNumericFieldWithExtractor(
|
||||
string vname,
|
||||
Quantity vquantity,
|
||||
VifScaling vif_scaling,
|
||||
FieldMatcher matcher,
|
||||
PrintProperties print_properties,
|
||||
string help,
|
||||
function<void(Unit,double)> setValueFunc,
|
||||
function<double(Unit)> getValueFunc)
|
||||
void MeterCommonImplementation::addNumericFieldWithExtractor(string vname,
|
||||
string help,
|
||||
PrintProperties print_properties,
|
||||
Quantity vquantity,
|
||||
VifScaling vif_scaling,
|
||||
FieldMatcher matcher)
|
||||
{
|
||||
field_infos_.push_back(
|
||||
FieldInfo(vname,
|
||||
FieldInfo(field_infos_.size(),
|
||||
vname,
|
||||
vquantity,
|
||||
defaultUnitForQuantity(vquantity),
|
||||
vif_scaling,
|
||||
matcher,
|
||||
help,
|
||||
print_properties,
|
||||
getValueFunc,
|
||||
NULL,
|
||||
setValueFunc,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NoLookup
|
||||
));
|
||||
|
@ -893,7 +895,8 @@ void MeterCommonImplementation::addNumericField(
|
|||
function<double(Unit)> getValueFunc)
|
||||
{
|
||||
field_infos_.push_back(
|
||||
FieldInfo(vname,
|
||||
FieldInfo(field_infos_.size(),
|
||||
vname,
|
||||
vquantity,
|
||||
defaultUnitForQuantity(vquantity),
|
||||
VifScaling::None,
|
||||
|
@ -923,7 +926,8 @@ void MeterCommonImplementation::addStringFieldWithExtractor(
|
|||
function<string()> getValueFunc)
|
||||
{
|
||||
field_infos_.push_back(
|
||||
FieldInfo(vname,
|
||||
FieldInfo(field_infos_.size(),
|
||||
vname,
|
||||
vquantity,
|
||||
defaultUnitForQuantity(vquantity),
|
||||
VifScaling::None,
|
||||
|
@ -954,7 +958,8 @@ void MeterCommonImplementation::addStringFieldWithExtractorAndLookup(
|
|||
Translate::Lookup lookup)
|
||||
{
|
||||
field_infos_.push_back(
|
||||
FieldInfo(vname,
|
||||
FieldInfo(field_infos_.size(),
|
||||
vname,
|
||||
vquantity,
|
||||
defaultUnitForQuantity(vquantity),
|
||||
VifScaling::None,
|
||||
|
@ -1462,15 +1467,15 @@ bool MeterCommonImplementation::handleTelegram(AboutTelegram &about, vector<ucha
|
|||
void MeterCommonImplementation::processFieldExtractors(Telegram *t)
|
||||
{
|
||||
// Iterate through the dv_entries in the telegram.
|
||||
|
||||
for (auto i = t->dv_entries_ordered.begin(); i != t->dv_entries_ordered.end(); ++i)
|
||||
for (auto &p : t->dv_entries)
|
||||
{
|
||||
DVEntry *dve = *i;
|
||||
DVEntry *dve = &p.second.second;
|
||||
for (FieldInfo &fi : field_infos_)
|
||||
{
|
||||
if (fi.hasMatcher() && fi.matches(dve))
|
||||
{
|
||||
debug("Using field info %s to extract %d\n", fi.vname().c_str(), dve->dif_vif_key.str().c_str());
|
||||
dve->setFieldInfo(&fi);
|
||||
fi.performExtraction(this, t, dve);
|
||||
}
|
||||
}
|
||||
|
@ -1511,7 +1516,7 @@ double MeterCommonImplementation::getNumericValue(FieldInfo *fi, Unit to)
|
|||
}
|
||||
|
||||
string field_name_no_unit = fi->vname();
|
||||
if (numeric_values_.count(field_name_no_unit) == 0) return -471147114711;
|
||||
assert(numeric_values_.count(field_name_no_unit) != 0);
|
||||
NumericField &nf = numeric_values_[field_name_no_unit];
|
||||
return convert(nf.value, nf.unit, to);
|
||||
}
|
||||
|
@ -1525,7 +1530,6 @@ void MeterCommonImplementation::setStringValue(FieldInfo *fi, string v)
|
|||
}
|
||||
|
||||
string field_name_no_unit = fi->vname();
|
||||
//printf("Setting string %s = %s\n", field_name_no_unit.c_str(), v.c_str());
|
||||
string_values_[field_name_no_unit] = StringField(v, fi);
|
||||
}
|
||||
|
||||
|
@ -1537,7 +1541,7 @@ string MeterCommonImplementation::getStringValue(FieldInfo *fi)
|
|||
}
|
||||
|
||||
string field_name_no_unit = fi->vname();
|
||||
if (string_values_.count(field_name_no_unit) == 0) return "???";
|
||||
assert (string_values_.count(field_name_no_unit) != 0);
|
||||
StringField &sf = string_values_[field_name_no_unit];
|
||||
return sf.value;
|
||||
}
|
||||
|
@ -1664,13 +1668,35 @@ void MeterCommonImplementation::printMeter(Telegram *t,
|
|||
{
|
||||
s += indent+"\"id\":\"\","+newline;
|
||||
}
|
||||
|
||||
// Iterate over the meter field infos...
|
||||
for (FieldInfo& fi : field_infos_)
|
||||
{
|
||||
if (fi.printProperties().hasJSON())
|
||||
{
|
||||
s += indent+fi.renderJson(this, &conversions())+","+newline;
|
||||
// The field should be printed in the json. (Most usually should.)
|
||||
bool found = false;
|
||||
for (auto& i : t->dv_entries)
|
||||
{
|
||||
// Check each telegram dv entry.
|
||||
DVEntry *dve = &i.second.second;
|
||||
// Has the entry been matches to this field, then print it as json.
|
||||
if (dve->getFieldInfo() == &fi)
|
||||
{
|
||||
s += indent+fi.renderJson(this, &conversions())+","+newline;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found && !fi.printProperties().hasOPTIONAL())
|
||||
{
|
||||
// No telegram entries found, but this field should be printed anyway.
|
||||
// It will be printed with any value received from a previous telegram.
|
||||
// Or if no value has been received, a default bad value, like -12345678
|
||||
s += indent+fi.renderJson(this, &conversions())+","+newline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s += indent+"\"timestamp\":\""+datetimeOfUpdateRobot()+"\"";
|
||||
|
||||
if (t->about.device != "")
|
||||
|
|
|
@ -287,7 +287,7 @@ enum PrintProperty
|
|||
JSON = 1, // This field should be printed when using --format=json
|
||||
FIELD = 2, // This field should be printed when using --format=field
|
||||
IMPORTANT = 4, // The most important field.
|
||||
OPTIONAL = 8, // If no data has arrived, do include this field in the json output.
|
||||
OPTIONAL = 8, // If no data has arrived, then do not include this field in the json output.
|
||||
};
|
||||
|
||||
struct PrintProperties
|
||||
|
@ -309,7 +309,8 @@ struct PrintProperties
|
|||
|
||||
struct FieldInfo
|
||||
{
|
||||
FieldInfo(string vname,
|
||||
FieldInfo(int index,
|
||||
string vname,
|
||||
Quantity xuantity,
|
||||
Unit default_unit,
|
||||
VifScaling vif_scaling,
|
||||
|
@ -322,6 +323,7 @@ struct FieldInfo
|
|||
function<void(string)> set_string_value_override,
|
||||
Translate::Lookup lookup
|
||||
) :
|
||||
index_(index),
|
||||
vname_(vname),
|
||||
xuantity_(xuantity),
|
||||
default_unit_(default_unit),
|
||||
|
@ -336,6 +338,7 @@ struct FieldInfo
|
|||
lookup_(lookup)
|
||||
{}
|
||||
|
||||
int index() { return index_; }
|
||||
string vname() { return vname_; }
|
||||
Quantity xuantity() { return xuantity_; }
|
||||
Unit defaultUnit() { return default_unit_; }
|
||||
|
@ -374,6 +377,7 @@ struct FieldInfo
|
|||
|
||||
private:
|
||||
|
||||
int index_; // The field infos for a meter are ordered.
|
||||
string vname_; // Value name, like: total current previous target, ie no unit suffix.
|
||||
Quantity xuantity_; // Quantity: Energy, Volume
|
||||
Unit default_unit_; // Default unit for above quantity: KWH, M3
|
||||
|
|
|
@ -128,14 +128,12 @@ protected:
|
|||
function<double(Unit)> getValueFunc); // Use the GET macro above.
|
||||
|
||||
void addNumericFieldWithExtractor(
|
||||
string vname, // Name of value without unit, eg total
|
||||
Quantity vquantity, // Value belongs to this quantity.
|
||||
VifScaling vif_scaling,
|
||||
FieldMatcher matcher,
|
||||
string vname, // Name of value without unit, eg "total" "total_month{storagenr}"
|
||||
string help, // Information about this field.
|
||||
PrintProperties print_properties, // Should this be printed by default in fields,json and hr.
|
||||
string help,
|
||||
function<void(Unit,double)> setValueFunc, // Use the SET macro above.
|
||||
function<double(Unit)> getValueFunc); // Use the GET macro above.
|
||||
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);
|
||||
|
||||
void addNumericField(
|
||||
string vname, // Name of value without unit, eg total
|
||||
|
@ -162,6 +160,12 @@ protected:
|
|||
function<void(string)> setValueFunc, // Use the SET_STRING macro above.
|
||||
function<string()> getValueFunc); // Use the GET_STRING macro above.
|
||||
|
||||
void addStringFieldWithExtractor(
|
||||
string vname,
|
||||
string help,
|
||||
PrintProperties print_properties,
|
||||
FieldMatcher matcher);
|
||||
|
||||
void addStringFieldWithExtractorAndLookup(
|
||||
string vname, // Name of value without unit, eg total
|
||||
Quantity vquantity, // Value belongs to this quantity.
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
Printer::Printer(bool json, bool fields, char separator,
|
||||
Printer::Printer(bool json, bool pretty_print_json, bool fields, char separator,
|
||||
bool use_meterfiles, string &meterfiles_dir,
|
||||
bool use_logfile, string &logfile,
|
||||
vector<string> shell_cmdlines, bool overwrite,
|
||||
|
@ -28,6 +28,7 @@ Printer::Printer(bool json, bool fields, char separator,
|
|||
MeterFileTimestamp timestamp)
|
||||
{
|
||||
json_ = json;
|
||||
pretty_print_json_ = pretty_print_json;
|
||||
fields_ = fields;
|
||||
separator_ = separator;
|
||||
use_meterfiles_ = use_meterfiles;
|
||||
|
@ -48,7 +49,7 @@ void Printer::print(Telegram *t, Meter *meter,
|
|||
vector<string> envs;
|
||||
bool printed = false;
|
||||
|
||||
meter->printMeter(t, &human_readable, &fields, separator_, &json, &envs, more_json, selected_fields, false);
|
||||
meter->printMeter(t, &human_readable, &fields, separator_, &json, &envs, more_json, selected_fields, pretty_print_json_);
|
||||
|
||||
if (shell_cmdlines_.size() > 0 || meter->shellCmdlines().size() > 0) {
|
||||
printShells(meter, envs);
|
||||
|
|
|
@ -23,6 +23,7 @@ using namespace std;
|
|||
|
||||
struct Printer {
|
||||
Printer(bool json,
|
||||
bool pretty_print_json,
|
||||
bool fields,
|
||||
char separator,
|
||||
bool meterfiles, string &meterfiles_dir,
|
||||
|
@ -36,7 +37,7 @@ struct Printer {
|
|||
|
||||
private:
|
||||
|
||||
bool json_, fields_;
|
||||
bool json_, pretty_print_json_, fields_;
|
||||
bool use_meterfiles_;
|
||||
string meterfiles_dir_;
|
||||
bool use_logfile_;
|
||||
|
|
|
@ -145,8 +145,7 @@ int test_crc()
|
|||
return rc;
|
||||
}
|
||||
|
||||
int test_parse(const char *data, std::map<std::string,std::pair<int,DVEntry>> *dv_entries,
|
||||
std::vector<DVEntry*> *dv_entries_ordered, int testnr)
|
||||
int test_parse(const char *data, std::map<std::string,std::pair<int,DVEntry>> *dv_entries, int testnr)
|
||||
{
|
||||
debug("\n\nTest nr %d......\n\n", testnr);
|
||||
bool b;
|
||||
|
@ -155,7 +154,7 @@ int test_parse(const char *data, std::map<std::string,std::pair<int,DVEntry>> *d
|
|||
hex2bin(data, &databytes);
|
||||
vector<uchar>::iterator i = databytes.begin();
|
||||
|
||||
b = parseDV(&t, databytes, i, databytes.size(), dv_entries, dv_entries_ordered);
|
||||
b = parseDV(&t, databytes, i, databytes.size(), dv_entries);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
@ -207,29 +206,28 @@ void test_date(map<string,pair<int,DVEntry>> &values, const char *key, string da
|
|||
int test_dvparser()
|
||||
{
|
||||
map<string,pair<int,DVEntry>> dv_entries;
|
||||
vector<DVEntry*> dv_entries_ordered;
|
||||
|
||||
int testnr = 1;
|
||||
test_parse("2F 2F 0B 13 56 34 12 8B 82 00 93 3E 67 45 23 0D FD 10 0A 30 31 32 33 34 35 36 37 38 39 0F 88 2F", &dv_entries, &dv_entries_ordered, testnr);
|
||||
test_parse("2F 2F 0B 13 56 34 12 8B 82 00 93 3E 67 45 23 0D FD 10 0A 30 31 32 33 34 35 36 37 38 39 0F 88 2F", &dv_entries, testnr);
|
||||
test_double(dv_entries, "0B13", 123.456, testnr);
|
||||
test_double(dv_entries, "8B8200933E", 234.567, testnr);
|
||||
test_string(dv_entries, "0DFD10", "30313233343536373839", testnr);
|
||||
|
||||
testnr++;
|
||||
dv_entries.clear();
|
||||
test_parse("82046C 5f1C", &dv_entries, &dv_entries_ordered, testnr);
|
||||
test_parse("82046C 5f1C", &dv_entries, testnr);
|
||||
test_date(dv_entries, "82046C", "2010-12-31 00:00:00", testnr); // 2010-dec-31
|
||||
|
||||
testnr++;
|
||||
dv_entries.clear();
|
||||
test_parse("0C1348550000426CE1F14C130000000082046C21298C0413330000008D04931E3A3CFE3300000033000000330000003300000033000000330000003300000033000000330000003300000033000000330000004300000034180000046D0D0B5C2B03FD6C5E150082206C5C290BFD0F0200018C4079678885238310FD3100000082106C01018110FD610002FD66020002FD170000", &dv_entries, &dv_entries_ordered, testnr);
|
||||
test_parse("0C1348550000426CE1F14C130000000082046C21298C0413330000008D04931E3A3CFE3300000033000000330000003300000033000000330000003300000033000000330000003300000033000000330000004300000034180000046D0D0B5C2B03FD6C5E150082206C5C290BFD0F0200018C4079678885238310FD3100000082106C01018110FD610002FD66020002FD170000", &dv_entries, testnr);
|
||||
test_double(dv_entries, "0C13", 5.548, testnr);
|
||||
test_date(dv_entries, "426C", "2127-01-01 00:00:00", testnr); // 2127-jan-1
|
||||
test_date(dv_entries, "82106C", "2000-01-01 00:00:00", testnr); // 2000-jan-1
|
||||
|
||||
testnr++;
|
||||
dv_entries.clear();
|
||||
test_parse("426C FE04", &dv_entries, &dv_entries_ordered, testnr);
|
||||
test_parse("426C FE04", &dv_entries, testnr);
|
||||
test_date(dv_entries, "426C", "2007-04-30 00:00:00", testnr); // 2010-dec-31
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1720,7 +1720,7 @@ bool Telegram::parse_TPL_72(vector<uchar>::iterator &pos)
|
|||
|
||||
if (decrypt_ok)
|
||||
{
|
||||
parseDV(this, frame, pos, remaining, &dv_entries, &dv_entries_ordered);
|
||||
parseDV(this, frame, pos, remaining, &dv_entries);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1735,7 +1735,7 @@ bool Telegram::parse_TPL_78(vector<uchar>::iterator &pos)
|
|||
header_size = distance(frame.begin(), pos);
|
||||
int remaining = distance(pos, frame.end());
|
||||
suffix_size = 0;
|
||||
parseDV(this, frame, pos, remaining, &dv_entries, &dv_entries_ordered);
|
||||
parseDV(this, frame, pos, remaining, &dv_entries);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1786,7 +1786,7 @@ bool Telegram::parse_TPL_79(vector<uchar>::iterator &pos)
|
|||
int remaining = distance(pos, frame.end());
|
||||
suffix_size = 0;
|
||||
|
||||
parseDV(this, frame, pos, remaining, &dv_entries, &dv_entries_ordered, &format, format_bytes.size());
|
||||
parseDV(this, frame, pos, remaining, &dv_entries, &format, format_bytes.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1804,7 +1804,7 @@ bool Telegram::parse_TPL_7A(vector<uchar>::iterator &pos)
|
|||
|
||||
if (decrypt_ok)
|
||||
{
|
||||
parseDV(this, frame, pos, remaining, &dv_entries, &dv_entries_ordered);
|
||||
parseDV(this, frame, pos, remaining, &dv_entries);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -363,6 +363,12 @@ struct Explanation
|
|||
|
||||
struct Telegram
|
||||
{
|
||||
private:
|
||||
Telegram(Telegram&t) { }
|
||||
|
||||
public:
|
||||
Telegram() = default;
|
||||
|
||||
AboutTelegram about;
|
||||
|
||||
// If a warning is printed mark this.
|
||||
|
@ -510,8 +516,6 @@ struct Telegram
|
|||
// The actual content of the (w)mbus telegram. The DifVif entries.
|
||||
// Mapped from their key for quick access to their offset and content.
|
||||
std::map<std::string,std::pair<int,DVEntry>> dv_entries;
|
||||
// And sorted in increasing offset order.
|
||||
std::vector<DVEntry*> dv_entries_ordered;
|
||||
|
||||
string autoDetectPossibleDrivers();
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ cat <<EOF > $TEST/test_expected.txt
|
|||
voltage_at_phase_1_v Voltage at phase L1.
|
||||
voltage_at_phase_2_v Voltage at phase L2.
|
||||
voltage_at_phase_3_v Voltage at phase L3.
|
||||
device_date_time_txt Device date time.
|
||||
device_date_time Device date time.
|
||||
total_energy_consumption_tariff_1_kwh The total energy consumption recorded by this meter on tariff 1.
|
||||
total_energy_consumption_tariff_2_kwh The total energy consumption recorded by this meter on tariff 2.
|
||||
total_energy_consumption_tariff_3_kwh The total energy consumption recorded by this meter on tariff 3.
|
||||
|
|
|
@ -93,6 +93,8 @@ Add :verbose to any analyze to get more verbose analyze output.
|
|||
|
||||
\fB\--oneshot\fR wait for an update from each meter, then quit
|
||||
|
||||
\fB\--ppjson\fR pretty print the json output
|
||||
|
||||
\fB\--resetafter=\fR<time> reset the wmbus dongle regularly, default is 23h
|
||||
|
||||
\fB\--selectfields=\fRid,timestamp,total_m3 select only these fields to be printed (--listfields=<meter> to list available fields)
|
||||
|
|
Ładowanie…
Reference in New Issue