From 87c4cb9256a681175c3e8b4bcd37700222fb88a7 Mon Sep 17 00:00:00 2001 From: weetmuts Date: Tue, 5 Mar 2019 18:38:54 +0100 Subject: [PATCH] Added support for id * wildcard. --- Makefile | 4 ++++ src/main.cc | 7 ++++--- src/meter_iperl.cc | 20 +++++++++++--------- src/meter_multical21.cc | 14 ++++++++------ src/meter_multical302.cc | 14 ++++++++------ src/meter_omnipower.cc | 14 ++++++++------ src/meter_qcaloric.cc | 16 +++++++++------- src/meter_supercom587.cc | 14 ++++++++------ src/meters.cc | 23 ++++++++++++++--------- src/meters.h | 5 +++-- src/meters_common_implementation.h | 6 +++--- src/printer.cc | 4 ++-- src/printer.h | 2 +- src/util.cc | 1 + src/wmbus.cc | 1 + src/wmbus.h | 4 ++-- 16 files changed, 87 insertions(+), 62 deletions(-) diff --git a/Makefile b/Makefile index 6a367b3..060a5ef 100644 --- a/Makefile +++ b/Makefile @@ -116,6 +116,10 @@ test: ./build/testinternals ./test.sh build/wmbusmeters +testd: + ./build_debug/testinternals + ./test.sh build_debug/wmbusmeters + update_manufacturers: wget http://www.m-bus.de/man.html echo '// Data downloaded from http://www.m-bus.de/man.html' > m.h diff --git a/src/main.cc b/src/main.cc index dffb7f9..67851ac 100644 --- a/src/main.cc +++ b/src/main.cc @@ -277,7 +277,8 @@ void startUsingCommandline(Configuration *config) if (config->list_shell_envs) { string ignore1, ignore2, ignore3; vector envs; - meters.back()->printMeter(&ignore1, + meters.back()->printMeter("", + &ignore1, &ignore2, config->separator, &ignore3, &envs); @@ -289,8 +290,8 @@ void startUsingCommandline(Configuration *config) } exit(0); } - meters.back()->onUpdate(calll(output.get(),print,Meter*)); - meters.back()->onUpdate([&](Meter*meter) { oneshotCheck(config, manager.get(), meter, meters); }); + meters.back()->onUpdate([&](string id, Meter* meter) { output->print(id,meter); }); +// meters.back()->onUpdate([&](string id, Meter* meter) { oneshotCheck(config, manager.get(), meter, meters); }); } } else { notice("No meters configured. Printing id:s of all telegrams heard!\n\n"); diff --git a/src/meter_iperl.cc b/src/meter_iperl.cc index 3ea8bd1..c73b96b 100644 --- a/src/meter_iperl.cc +++ b/src/meter_iperl.cc @@ -55,7 +55,8 @@ struct MeterIperl : public virtual WaterMeter, public virtual MeterCommonImpleme string timeLeaking(); string timeBursting(); - void printMeter(string *human_readable, + void printMeter(string id, + string *human_readable, string *fields, char separator, string *json, vector *envs); @@ -148,10 +149,11 @@ void MeterIperl::processContent(Telegram *t) t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_); } -void MeterIperl::printMeter(string *human_readable, - string *fields, char separator, - string *json, - vector *envs) +void MeterIperl::printMeter(string id, + string *human_readable, + string *fields, char separator, + string *json, + vector *envs) { char buf[65536]; buf[65535] = 0; @@ -162,7 +164,7 @@ void MeterIperl::printMeter(string *human_readable, "% 3.3f m3\t" "%s", name().c_str(), - id().c_str(), + id.c_str(), totalWaterConsumption(), datetimeOfUpdateHumanReadable().c_str()); @@ -174,7 +176,7 @@ void MeterIperl::printMeter(string *human_readable, "%f%c" "%s", name().c_str(), separator, - id().c_str(), separator, + id.c_str(), separator, totalWaterConsumption(), separator, datetimeOfUpdateRobot().c_str()); @@ -194,7 +196,7 @@ void MeterIperl::printMeter(string *human_readable, "}", mediaType(manufacturer(), media()).c_str(), name().c_str(), - id().c_str(), + id.c_str(), totalWaterConsumption(), datetimeOfUpdateRobot().c_str()); @@ -202,7 +204,7 @@ void MeterIperl::printMeter(string *human_readable, envs->push_back(string("METER_JSON=")+*json); envs->push_back(string("METER_TYPE=iperl")); - envs->push_back(string("METER_ID=")+id()); + envs->push_back(string("METER_ID=")+id); envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption())); envs->push_back(string("METER_TIMESTAMP=")+datetimeOfUpdateRobot()); } diff --git a/src/meter_multical21.cc b/src/meter_multical21.cc index 07796ce..81a8f39 100644 --- a/src/meter_multical21.cc +++ b/src/meter_multical21.cc @@ -77,7 +77,8 @@ struct MeterMultical21 : public virtual WaterMeter, public virtual MeterCommonIm string timeLeaking(); string timeBursting(); - void printMeter(string *human_readable, + void printMeter(string id, + string *human_readable, string *fields, char separator, string *json, vector *envs); @@ -495,7 +496,8 @@ string MeterMultical21::decodeTime(int time) } } -void MeterMultical21::printMeter(string *human_readable, +void MeterMultical21::printMeter(string id, + string *human_readable, string *fields, char separator, string *json, vector *envs) @@ -523,7 +525,7 @@ void MeterMultical21::printMeter(string *human_readable, snprintf(buf, sizeof(buf)-1, "%s\t%s\t% 3.3f m3\t% 3.3f m3\t% 3.3f m3/h\t%s°C\t%s°C\t%s\t%s", name().c_str(), - id().c_str(), + id.c_str(), totalWaterConsumption(), targetWaterConsumption(), maxFlow(), @@ -536,7 +538,7 @@ void MeterMultical21::printMeter(string *human_readable, snprintf(buf, sizeof(buf)-1, "%s%c" "%s%c" "%f%c" "%f%c" "%f%c" "%.0f%c" "%.0f%c" "%s%c" "%s", name().c_str(), separator, - id().c_str(), separator, + id.c_str(), separator, totalWaterConsumption(), separator, targetWaterConsumption(), separator, maxFlow(), separator, @@ -571,7 +573,7 @@ void MeterMultical21::printMeter(string *human_readable, mediaType(manufacturer(), media()).c_str(), meter_name_, name().c_str(), - id().c_str(), + id.c_str(), totalWaterConsumption(), targetWaterConsumption(), maxFlow(), @@ -588,7 +590,7 @@ void MeterMultical21::printMeter(string *human_readable, envs->push_back(string("METER_JSON=")+*json); envs->push_back(string("METER_TYPE=")+meter_name_); - envs->push_back(string("METER_ID=")+id()); + envs->push_back(string("METER_ID=")+id); envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption())); envs->push_back(string("METER_TARGET_M3=")+to_string(targetWaterConsumption())); envs->push_back(string("METER_MAX_FLOW_M3H=")+to_string(maxFlow())); diff --git a/src/meter_multical302.cc b/src/meter_multical302.cc index 280b980..3a6e13e 100644 --- a/src/meter_multical302.cc +++ b/src/meter_multical302.cc @@ -35,7 +35,8 @@ struct MeterMultical302 : public virtual HeatMeter, public virtual MeterCommonIm double totalVolume(); - void printMeter(string *human_readable, + void printMeter(string id, + string *human_readable, string *fields, char separator, string *json, vector *envs); @@ -182,7 +183,8 @@ unique_ptr createMultical302(WMBus *bus, string& name, string& id, st return unique_ptr(new MeterMultical302(bus,name,id,key)); } -void MeterMultical302::printMeter(string *human_readable, +void MeterMultical302::printMeter(string id, + string *human_readable, string *fields, char separator, string *json, vector *envs) @@ -192,7 +194,7 @@ void MeterMultical302::printMeter(string *human_readable, snprintf(buf, sizeof(buf)-1, "%s\t%s\t% 3.3f kwh\t% 3.3f m3\t% 3.3f kwh\t%s", name().c_str(), - id().c_str(), + id.c_str(), totalEnergyConsumption(), totalVolume(), currentPowerConsumption(), @@ -202,7 +204,7 @@ void MeterMultical302::printMeter(string *human_readable, snprintf(buf, sizeof(buf)-1, "%s%c%s%c%f%c%f%c%f%c%s", name().c_str(), separator, - id().c_str(), separator, + id.c_str(), separator, totalEnergyConsumption(), separator, totalVolume(), separator, currentPowerConsumption(), separator, @@ -225,7 +227,7 @@ void MeterMultical302::printMeter(string *human_readable, QSE(timestamp,%s) "}", name().c_str(), - id().c_str(), + id.c_str(), totalEnergyConsumption(), totalVolume(), currentPowerConsumption(), @@ -235,7 +237,7 @@ void MeterMultical302::printMeter(string *human_readable, envs->push_back(string("METER_JSON=")+*json); envs->push_back(string("METER_TYPE=multical302")); - envs->push_back(string("METER_ID=")+id()); + envs->push_back(string("METER_ID=")+id); envs->push_back(string("METER_TOTAL_KWH=")+to_string(totalEnergyConsumption())); envs->push_back(string("METER_TOTAL_VOLUME_M3=")+to_string(totalVolume())); envs->push_back(string("METER_CURRENT_KW=")+to_string(currentPowerConsumption())); diff --git a/src/meter_omnipower.cc b/src/meter_omnipower.cc index 672e9d6..89b4dfd 100644 --- a/src/meter_omnipower.cc +++ b/src/meter_omnipower.cc @@ -35,7 +35,8 @@ struct MeterOmnipower : public virtual ElectricityMeter, public virtual MeterCom double totalEnergyConsumption(); double currentPowerConsumption(); - void printMeter(string *human_readable, + void printMeter(string id, + string *human_readable, string *fields, char separator, string *json, vector *envs); @@ -123,7 +124,8 @@ unique_ptr createOmnipower(WMBus *bus, string& name, string& i return unique_ptr(new MeterOmnipower(bus,name,id,key)); } -void MeterOmnipower::printMeter(string *human_readable, +void MeterOmnipower::printMeter(string id, + string *human_readable, string *fields, char separator, string *json, vector *envs) @@ -134,7 +136,7 @@ void MeterOmnipower::printMeter(string *human_readable, snprintf(buf, sizeof(buf)-1, "%s\t%s\t% 3.3f kwh\t% 3.3f kwh\t%s", name().c_str(), - id().c_str(), + id.c_str(), totalEnergyConsumption(), currentPowerConsumption(), datetimeOfUpdateHumanReadable().c_str()); @@ -143,7 +145,7 @@ void MeterOmnipower::printMeter(string *human_readable, snprintf(buf, sizeof(buf)-1, "%s%c%s%c%f%c%f%c%s", name().c_str(), separator, - id().c_str(), separator, + id.c_str(), separator, totalEnergyConsumption(), separator, currentPowerConsumption(), separator, datetimeOfUpdateRobot().c_str()); @@ -164,7 +166,7 @@ void MeterOmnipower::printMeter(string *human_readable, QSE(timestamp,%s) "}", name().c_str(), - id().c_str(), + id.c_str(), totalEnergyConsumption(), currentPowerConsumption(), datetimeOfUpdateRobot().c_str()); @@ -173,7 +175,7 @@ void MeterOmnipower::printMeter(string *human_readable, envs->push_back(string("METER_JSON=")+*json); envs->push_back(string("METER_TYPE=omnipower")); - envs->push_back(string("METER_ID=")+id()); + envs->push_back(string("METER_ID=")+id); envs->push_back(string("METER_TOTAL_KWH=")+to_string(totalEnergyConsumption())); envs->push_back(string("METER_CURRENT_KW=")+to_string(currentPowerConsumption())); envs->push_back(string("METER_TIMESTAMP=")+datetimeOfUpdateRobot()); diff --git a/src/meter_qcaloric.cc b/src/meter_qcaloric.cc index f094035..a2e7527 100644 --- a/src/meter_qcaloric.cc +++ b/src/meter_qcaloric.cc @@ -36,7 +36,8 @@ struct MeterQCaloric : public virtual HeatCostMeter, public virtual MeterCommonI string setDate(); double consumptionAtSetDate(); - void printMeter(string *human_readable, + void printMeter(string id, + string *human_readable, string *fields, char separator, string *json, vector *envs); @@ -226,7 +227,8 @@ unique_ptr createQCaloric(WMBus *bus, string& name, string& id, s return unique_ptr(new MeterQCaloric(bus,name,id,key)); } -void MeterQCaloric::printMeter(string *human_readable, +void MeterQCaloric::printMeter(string id, + string *human_readable, string *fields, char separator, string *json, vector *envs) @@ -235,9 +237,9 @@ void MeterQCaloric::printMeter(string *human_readable, char buf[65536]; buf[65535] = 0; - snprintf(buf, sizeof(buf)-1, "%s\t%s\t% 3.3f hca\t%s\t% 3.3f hca\t%s", + snprintf(buf, sizeof(buf)-1, "%s\t%s\t% 3.0f hca\t%s\t% 3.0f hca\t%s", name().c_str(), - id().c_str(), + id.c_str(), currentConsumption(), setDate().c_str(), consumptionAtSetDate(), @@ -247,7 +249,7 @@ void MeterQCaloric::printMeter(string *human_readable, snprintf(buf, sizeof(buf)-1, "%s%c%s%c%f%c%s%c%f%c%s", name().c_str(), separator, - id().c_str(), separator, + id.c_str(), separator, currentConsumption(), separator, setDate().c_str(), separator, consumptionAtSetDate(), separator, @@ -274,7 +276,7 @@ void MeterQCaloric::printMeter(string *human_readable, QSE(timestamp,%s) "}", name().c_str(), - id().c_str(), + id.c_str(), currentConsumption(), setDate().c_str(), consumptionAtSetDate(), @@ -288,7 +290,7 @@ void MeterQCaloric::printMeter(string *human_readable, envs->push_back(string("METER_JSON=")+*json); envs->push_back(string("METER_TYPE=qcaloric")); - envs->push_back(string("METER_ID=")+id()); + envs->push_back(string("METER_ID=")+id); envs->push_back(string("METER_CURRENT_CONSUMPTION_HCA=")+to_string(currentConsumption())); envs->push_back(string("METER_SET_DATE=")+setDate()); envs->push_back(string("METER_CONSUMPTION_AT_SET_DATE_HCA=")+to_string(consumptionAtSetDate())); diff --git a/src/meter_supercom587.cc b/src/meter_supercom587.cc index 62a1d95..b227794 100644 --- a/src/meter_supercom587.cc +++ b/src/meter_supercom587.cc @@ -54,7 +54,8 @@ struct MeterSupercom587 : public virtual WaterMeter, public virtual MeterCommonI string timeLeaking(); string timeBursting(); - void printMeter(string *human_readable, + void printMeter(string id, + string *human_readable, string *fields, char separator, string *json, vector *envs); @@ -143,7 +144,8 @@ void MeterSupercom587::processContent(Telegram *t) t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_); } -void MeterSupercom587::printMeter(string *human_readable, +void MeterSupercom587::printMeter(string id, + string *human_readable, string *fields, char separator, string *json, vector *envs) @@ -157,7 +159,7 @@ void MeterSupercom587::printMeter(string *human_readable, "% 3.3f m3\t" "%s", name().c_str(), - id().c_str(), + id.c_str(), totalWaterConsumption(), datetimeOfUpdateHumanReadable().c_str()); @@ -169,7 +171,7 @@ void MeterSupercom587::printMeter(string *human_readable, "%f%c" "%s", name().c_str(), separator, - id().c_str(), separator, + id.c_str(), separator, totalWaterConsumption(), separator, datetimeOfUpdateRobot().c_str()); @@ -189,7 +191,7 @@ void MeterSupercom587::printMeter(string *human_readable, "}", mediaType(manufacturer(), media()).c_str(), name().c_str(), - id().c_str(), + id.c_str(), totalWaterConsumption(), datetimeOfUpdateRobot().c_str()); @@ -197,7 +199,7 @@ void MeterSupercom587::printMeter(string *human_readable, envs->push_back(string("METER_JSON=")+*json); envs->push_back(string("METER_TYPE=supercom587")); - envs->push_back(string("METER_ID=")+id()); + envs->push_back(string("METER_ID=")+id); envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption())); envs->push_back(string("METER_TIMESTAMP=")+datetimeOfUpdateRobot()); } diff --git a/src/meters.cc b/src/meters.cc index 18ca98c..d0100bf 100644 --- a/src/meters.cc +++ b/src/meters.cc @@ -27,7 +27,7 @@ MeterCommonImplementation::MeterCommonImplementation(WMBus *bus, string& name, s required_link_mode_(required_link_mode) { use_aes_ = true; - hex2bin(id, &id_); + id_ = id; if (key.length() == 0) { use_aes_ = false; } else { @@ -52,7 +52,7 @@ int MeterCommonImplementation::media() string MeterCommonImplementation::id() { - return bin2hex(id_); + return id_; } string MeterCommonImplementation::name() @@ -70,7 +70,7 @@ LinkMode MeterCommonImplementation::requiredLinkMode() return required_link_mode_; } -void MeterCommonImplementation::onUpdate(function cb) +void MeterCommonImplementation::onUpdate(function cb) { on_update_.push_back(cb); } @@ -125,11 +125,16 @@ LinkMode toMeterLinkMode(string& type) bool MeterCommonImplementation::isTelegramForMe(Telegram *t) { - return (manufacturer_ == 0 || t->m_field == manufacturer_) && - t->a_field_address[3] == id_[3] && - t->a_field_address[2] == id_[2] && - t->a_field_address[1] == id_[1] && - t->a_field_address[0] == id_[0]; + if (manufacturer_ != 0 && t->m_field != manufacturer_) { + return false; + } + if (id_ == t->id) { + return true; + } + if (id_ == "*") { + return true; + } + return false; } bool MeterCommonImplementation::useAes() @@ -166,7 +171,7 @@ void MeterCommonImplementation::triggerUpdate(Telegram *t) { datetime_of_update_ = time(NULL); num_updates_++; - for (auto &cb : on_update_) if (cb) cb(this); + for (auto &cb : on_update_) if (cb) cb(t->id, this); t->handled = true; } diff --git a/src/meters.h b/src/meters.h index fc7de39..a75b78a 100644 --- a/src/meters.h +++ b/src/meters.h @@ -48,10 +48,11 @@ struct Meter { virtual string datetimeOfUpdateHumanReadable() = 0; virtual string datetimeOfUpdateRobot() = 0; - virtual void onUpdate(function cb) = 0; + virtual void onUpdate(function cb) = 0; virtual int numUpdates() = 0; - virtual void printMeter(string *human_readable, + virtual void printMeter(string id, + string *human_readable, string *fields, char separator, string *json, vector *envs) = 0; diff --git a/src/meters_common_implementation.h b/src/meters_common_implementation.h index 8eb1d0c..a8ec919 100644 --- a/src/meters_common_implementation.h +++ b/src/meters_common_implementation.h @@ -35,7 +35,7 @@ struct MeterCommonImplementation : public virtual Meter string datetimeOfUpdateHumanReadable(); string datetimeOfUpdateRobot(); - void onUpdate(function cb); + void onUpdate(function cb); int numUpdates(); bool isTelegramForMe(Telegram *t); @@ -63,10 +63,10 @@ private: int manufacturer_ {}; int media_ {}; string name_; - vector id_; + string id_; vector key_; WMBus *bus_ {}; - vector> on_update_; + vector> on_update_; int num_updates_ {}; bool use_aes_ {}; time_t datetime_of_update_ {}; diff --git a/src/printer.cc b/src/printer.cc index db5529f..579d702 100644 --- a/src/printer.cc +++ b/src/printer.cc @@ -36,13 +36,13 @@ Printer::Printer(bool json, bool fields, char separator, overwrite_ = overwrite; } -void Printer::print(Meter *meter) +void Printer::print(string id, Meter *meter) { string human_readable, fields, json; vector envs; bool printed = false; - meter->printMeter(&human_readable, &fields, separator_, &json, &envs); + meter->printMeter(id, &human_readable, &fields, separator_, &json, &envs); if (shell_cmdlines_.size() > 0) { printShells(meter, envs); diff --git a/src/printer.h b/src/printer.h index 22d945e..d33fe90 100644 --- a/src/printer.h +++ b/src/printer.h @@ -29,7 +29,7 @@ struct Printer { vector shell_cmdlines, bool overwrite); - void print(Meter *meter); + void print(string id, Meter *meter); private: diff --git a/src/util.cc b/src/util.cc index 2bb7979..a8aed25 100644 --- a/src/util.cc +++ b/src/util.cc @@ -305,6 +305,7 @@ void debug(const char* fmt, ...) { bool isValidId(string& id) { + if (id == "*") return true; if (id.length() != 8) return false; for (int i=0; i<8; ++i) { if (id[i]<'0' || id[i]>'9') return false; diff --git a/src/wmbus.cc b/src/wmbus.cc index 00cd782..fd939a5 100644 --- a/src/wmbus.cc +++ b/src/wmbus.cc @@ -366,6 +366,7 @@ void Telegram::parse(vector &frame) addExplanation(bytes, 4, "%02x%02x%02x%02x a-field-addr (%02x%02x%02x%02x)", frame[4], frame[5], frame[6], frame[7], frame[7], frame[6], frame[5], frame[4]); + strprintf(id, "%02x%02x%02x%02x", frame[7], frame[6], frame[5], frame[4]); a_field_version = frame[4+4]; a_field_device_type = frame[4+5]; addExplanation(bytes, 1, "%02x a-field-version", frame[8]); diff --git a/src/wmbus.h b/src/wmbus.h index 976cf7e..66d25d5 100644 --- a/src/wmbus.h +++ b/src/wmbus.h @@ -58,6 +58,7 @@ struct Telegram { vector a_field; // A field 6 bytes // The 6 a field bytes are composed of: vector a_field_address; // Address in BCD = 8 decimal 00000000...99999999 digits. + string id; // the address as a string. int a_field_version {}; // 1 byte int a_field_device_type {}; // 1 byte @@ -81,8 +82,7 @@ struct Telegram { bool handled {}; // Set to true, when a meter has accepted the telegram. - // The id as written on the physical meter device. - string id() { return bin2hex(a_field_address); } + void parse(vector &payload); void print(); void verboseFields();