Added support for id * wildcard.

pull/22/head
weetmuts 2019-03-05 18:38:54 +01:00
rodzic 83c6a3fefc
commit 87c4cb9256
16 zmienionych plików z 87 dodań i 62 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -277,7 +277,8 @@ void startUsingCommandline(Configuration *config)
if (config->list_shell_envs) {
string ignore1, ignore2, ignore3;
vector<string> 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");

Wyświetl plik

@ -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<string> *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<string> *envs)
void MeterIperl::printMeter(string id,
string *human_readable,
string *fields, char separator,
string *json,
vector<string> *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());
}

Wyświetl plik

@ -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<string> *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<string> *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()));

Wyświetl plik

@ -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<string> *envs);
@ -182,7 +183,8 @@ unique_ptr<HeatMeter> createMultical302(WMBus *bus, string& name, string& id, st
return unique_ptr<HeatMeter>(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<string> *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()));

Wyświetl plik

@ -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<string> *envs);
@ -123,7 +124,8 @@ unique_ptr<ElectricityMeter> createOmnipower(WMBus *bus, string& name, string& i
return unique_ptr<ElectricityMeter>(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<string> *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());

Wyświetl plik

@ -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<string> *envs);
@ -226,7 +227,8 @@ unique_ptr<HeatCostMeter> createQCaloric(WMBus *bus, string& name, string& id, s
return unique_ptr<HeatCostMeter>(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<string> *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()));

Wyświetl plik

@ -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<string> *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<string> *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());
}

Wyświetl plik

@ -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<void(Meter*)> cb)
void MeterCommonImplementation::onUpdate(function<void(string,Meter*)> 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;
}

Wyświetl plik

@ -48,10 +48,11 @@ struct Meter {
virtual string datetimeOfUpdateHumanReadable() = 0;
virtual string datetimeOfUpdateRobot() = 0;
virtual void onUpdate(function<void(Meter*)> cb) = 0;
virtual void onUpdate(function<void(string id, Meter*)> 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<string> *envs) = 0;

Wyświetl plik

@ -35,7 +35,7 @@ struct MeterCommonImplementation : public virtual Meter
string datetimeOfUpdateHumanReadable();
string datetimeOfUpdateRobot();
void onUpdate(function<void(Meter*)> cb);
void onUpdate(function<void(string id, Meter*)> cb);
int numUpdates();
bool isTelegramForMe(Telegram *t);
@ -63,10 +63,10 @@ private:
int manufacturer_ {};
int media_ {};
string name_;
vector<uchar> id_;
string id_;
vector<uchar> key_;
WMBus *bus_ {};
vector<function<void(Meter*)>> on_update_;
vector<function<void(string,Meter*)>> on_update_;
int num_updates_ {};
bool use_aes_ {};
time_t datetime_of_update_ {};

Wyświetl plik

@ -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<string> 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);

Wyświetl plik

@ -29,7 +29,7 @@ struct Printer {
vector<string> shell_cmdlines,
bool overwrite);
void print(Meter *meter);
void print(string id, Meter *meter);
private:

Wyświetl plik

@ -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;

Wyświetl plik

@ -366,6 +366,7 @@ void Telegram::parse(vector<uchar> &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]);

Wyświetl plik

@ -58,6 +58,7 @@ struct Telegram {
vector<uchar> a_field; // A field 6 bytes
// The 6 a field bytes are composed of:
vector<uchar> 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<uchar> &payload);
void print();
void verboseFields();