diff --git a/CHANGES b/CHANGES index 9a7600a..bc226ed 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,13 @@ -Version 0.9.10: 2019-6-13 +Version 0.9.11: 2019-06-20 + +Added --meterfilesnaming=(name|id|name-id) +to choose the file name written meter file. + +Naming using id or name-id is necessary when a meter +specification listens to many different meters using id +wildcards. + +Version 0.9.10: 2019-06-13 Update logrotate to trigger HUP when rotating log files. This will re-initialize the serial connection to the usb dongle diff --git a/README.md b/README.md index b9341f3..b6e69e0 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ logtelegrams=false format=json meterfiles=/var/log/wmbusmeters/meter_readings meterfilesaction=overwrite +meterfilesnaming=name logfile=/var/log/wmbusmeters/wmbusmeters.log shell=/usr/bin/mosquitto_pub -h localhost -t wmbusmeters/$METER_ID -m "$METER_JSON" ``` @@ -103,6 +104,7 @@ As you can use: --logtelegrams log the contents of the telegrams for easy replay --meterfiles= store meter readings in dir --meterfilesaction=(overwrite|append) overwrite or append to the meter readings file + --meterfilesnaming=(name|id|name-id) the meter file is the meter's: name, id or name-id --n1a to --n1f listen to N1 messages (perhaps) --oneshot wait for an update from each meter, then quit --separator= change field separator to c diff --git a/src/cmdline.cc b/src/cmdline.cc index 015c388..dbb49a1 100644 --- a/src/cmdline.cc +++ b/src/cmdline.cc @@ -180,24 +180,6 @@ unique_ptr parseCommandLine(int argc, char **argv) { i++; continue; } - if (!strncmp(argv[i], "--meterfiles", 12)) { - c->meterfiles = true; - if (strlen(argv[i]) > 12 && argv[i][12] == '=') { - size_t len = strlen(argv[i])-13; - if (len > 0) { - c->meterfiles_dir = string(argv[i]+13, len); - } else { - c->meterfiles_dir = "/tmp"; - } - } else { - c->meterfiles_dir = "/tmp"; - } - if (!checkIfDirExists(c->meterfiles_dir.c_str())) { - error("Cannot write meter files into dir \"%s\"\n", c->meterfiles_dir.c_str()); - } - i++; - continue; - } if (!strncmp(argv[i], "--meterfilesaction", 18)) { if (strlen(argv[i]) > 18 && argv[i][18] == '=') { if (!strncmp(argv[i]+19, "overwrite", 9)) { @@ -213,6 +195,47 @@ unique_ptr parseCommandLine(int argc, char **argv) { i++; continue; } + if (!strncmp(argv[i], "--meterfilesnaming", 18)) { + if (strlen(argv[i]) > 18 && argv[i][18] == '=') { + if (!strncmp(argv[i]+19, "name-id", 7)) + { + c->meterfiles_naming = MeterFileNaming::NameId; + } + else if (!strncmp(argv[i]+19, "name", 4)) + { + c->meterfiles_naming = MeterFileNaming::Name; + } + else if (!strncmp(argv[i]+19, "id", 2)) + { + c->meterfiles_naming = MeterFileNaming::Id; + } else + { + error("No such meter file naming %s\n", argv[i]+19); + } + } else { + error("Incorrect option %s\n", argv[i]); + } + i++; + continue; + } + if (!strcmp(argv[i], "--meterfiles") || + (!strncmp(argv[i], "--meterfiles", 12) && + strlen(argv[i]) > 12 && + argv[i][12] == '=')) + { + c->meterfiles = true; + size_t len = strlen(argv[i]); + if (len > 13) { + c->meterfiles_dir = string(argv[i]+13, len-13); + } else { + c->meterfiles_dir = "/tmp"; + } + if (!checkIfDirExists(c->meterfiles_dir.c_str())) { + error("Cannot write meter files into dir \"%s\"\n", c->meterfiles_dir.c_str()); + } + i++; + continue; + } if (!strncmp(argv[i], "--logfile=", 10)) { c->use_logfile = true; if (strlen(argv[i]) > 10) { diff --git a/src/config.cc b/src/config.cc index 940c5ba..226d431 100644 --- a/src/config.cc +++ b/src/config.cc @@ -210,6 +210,26 @@ void handleMeterfilesAction(Configuration *c, string meterfilesaction) } } +void handleMeterfilesNaming(Configuration *c, string type) +{ + if (type == "name") + { + c->meterfiles_naming = MeterFileNaming::Name; + } + else if (type == "id") + { + c->meterfiles_naming = MeterFileNaming::Id; + } + else if (type == "name-id") + { + c->meterfiles_naming = MeterFileNaming::NameId; + } + else + { + warning("No such meter file naming \"%s\"\n", type.c_str()); + } +} + void handleLogfile(Configuration *c, string logfile) { if (logfile.length() > 0) @@ -296,6 +316,7 @@ unique_ptr loadConfiguration(string root) else if (p.first == "logtelegrams") handleLogtelegrams(c, p.second); else if (p.first == "meterfiles") handleMeterfiles(c, p.second); else if (p.first == "meterfilesaction") handleMeterfilesAction(c, p.second); + else if (p.first == "meterfilesnaming") handleMeterfilesNaming(c, p.second); else if (p.first == "logfile") handleLogfile(c, p.second); else if (p.first == "format") handleFormat(c, p.second); else if (p.first == "separator") handleSeparator(c, p.second); diff --git a/src/config.h b/src/config.h index 0c30102..d1627c5 100644 --- a/src/config.h +++ b/src/config.h @@ -31,6 +31,11 @@ enum class MeterFileType Overwrite, Append }; +enum class MeterFileNaming +{ + Name, Id, NameId +}; + struct Configuration { bool daemon {}; std::string pid_file; @@ -47,6 +52,7 @@ struct Configuration { bool meterfiles {}; std::string meterfiles_dir; MeterFileType meterfiles_action {}; + MeterFileNaming meterfiles_naming {}; bool use_logfile {}; std::string logfile; bool json {}; diff --git a/src/main.cc b/src/main.cc index 58aa90c..a695531 100644 --- a/src/main.cc +++ b/src/main.cc @@ -97,6 +97,7 @@ As you can use: --logtelegrams log the contents of the telegrams for easy replay --meterfiles= store meter readings in dir --meterfilesaction=(overwrite|append) overwrite or append to the meter readings file + --meterfilesnaming=(name|id|name-id) the meter file is the meter's: name, id or name-id --oneshot wait for an update from each meter, then quit --separator= change field separator to c --shell= invokes cmdline with env variables containing the latest reading @@ -272,7 +273,8 @@ bool startUsingCommandline(Configuration *config) config->separator, config->meterfiles, config->meterfiles_dir, config->use_logfile, config->logfile, config->shells, - config->meterfiles_action == MeterFileType::Overwrite)); + config->meterfiles_action == MeterFileType::Overwrite, + config->meterfiles_naming)); vector> meters; if (config->meters.size() > 0) { diff --git a/src/printer.cc b/src/printer.cc index 0293eba..312b9c7 100644 --- a/src/printer.cc +++ b/src/printer.cc @@ -23,7 +23,8 @@ using namespace std; Printer::Printer(bool json, bool fields, char separator, bool use_meterfiles, string &meterfiles_dir, bool use_logfile, string &logfile, - vector shell_cmdlines, bool overwrite) + vector shell_cmdlines, bool overwrite, + MeterFileNaming naming) { json_ = json; fields_ = fields; @@ -34,6 +35,7 @@ Printer::Printer(bool json, bool fields, char separator, logfile_ = logfile; shell_cmdlines_ = shell_cmdlines; overwrite_ = overwrite; + naming_ = naming; } void Printer::print(Telegram *t, Meter *meter) @@ -49,12 +51,12 @@ void Printer::print(Telegram *t, Meter *meter) printed = true; } if (use_meterfiles_) { - printFiles(meter, human_readable, fields, json); + printFiles(meter, t, human_readable, fields, json); printed = true; } if (!printed) { // This will print on stdout or in the logfile. - printFiles(meter, human_readable, fields, json); + printFiles(meter, t, human_readable, fields, json); } } @@ -72,14 +74,24 @@ void Printer::printShells(Meter *meter, vector &envs) } } -void Printer::printFiles(Meter *meter, string &human_readable, string &fields, string &json) +void Printer::printFiles(Meter *meter, Telegram *t, string &human_readable, string &fields, string &json) { FILE *output = stdout; if (use_meterfiles_) { char filename[128]; memset(filename, 0, sizeof(filename)); - snprintf(filename, 127, "%s/%s", meterfiles_dir_.c_str(), meter->name().c_str()); + switch (naming_) { + case MeterFileNaming::Name: + snprintf(filename, 127, "%s/%s", meterfiles_dir_.c_str(), meter->name().c_str()); + break; + case MeterFileNaming::Id: + snprintf(filename, 127, "%s/%s", meterfiles_dir_.c_str(), t->id.c_str()); + break; + case MeterFileNaming::NameId: + snprintf(filename, 127, "%s/%s-%s", meterfiles_dir_.c_str(), meter->name().c_str(), t->id.c_str()); + break; + } const char *mode = overwrite_ ? "w" : "a"; output = fopen(filename, mode); if (!output) { diff --git a/src/printer.h b/src/printer.h index ddf1708..47db2f9 100644 --- a/src/printer.h +++ b/src/printer.h @@ -17,6 +17,7 @@ #include"cmdline.h" #include"meters.h" +#include"wmbus.h" using namespace std; @@ -27,7 +28,8 @@ struct Printer { bool meterfiles, string &meterfiles_dir, bool use_logfile, string &logfile, vector shell_cmdlines, - bool overwrite); + bool overwrite, + MeterFileNaming naming); void print(Telegram *t, Meter *meter); @@ -41,8 +43,9 @@ struct Printer { char separator_; vector shell_cmdlines_; bool overwrite_; + MeterFileNaming naming_; void printShells(Meter *meter, vector &envs); - void printFiles(Meter *meter, string &human_readable, string &fields, string &json); + void printFiles(Meter *meter, Telegram *t, string &human_readable, string &fields, string &json); }; diff --git a/tests/config3/etc/wmbusmeters.conf b/tests/config3/etc/wmbusmeters.conf index 0bec2ba..ef33c39 100644 --- a/tests/config3/etc/wmbusmeters.conf +++ b/tests/config3/etc/wmbusmeters.conf @@ -4,4 +4,5 @@ logtelegrams=false format=json meterfiles=testoutput/meter_readings3 meterfilesaction=append +meterfilesnaming=id logfile=testoutput/thelog3.txt diff --git a/tests/test_elements.sh b/tests/test_elements.sh index cea5860..1343192 100755 --- a/tests/test_elements.sh +++ b/tests/test_elements.sh @@ -4,14 +4,20 @@ PROG="$1" TEST=testoutput mkdir -p $TEST/meter_readings3 -rm -f $TEST/meter_readings3/Element +rm -f $TEST/meter_readings3/* cat simulations/simulation_multiple_qcalorics.txt | grep '^{' > $TEST/test_expected.txt $PROG --useconfig=tests/config3 > $TEST/test_output.txt if [ "$?" == "0" ] then - cat $TEST/meter_readings3/Element | sed 's/"timestamp":"....-..-..T..:..:..Z"/"timestamp":"1111-11-11T11:11:11Z"/' > $TEST/test_responses.txt + FILES=$(ls $TEST/meter_readings3/ | tr '\n' ' ') + if [ ! "$FILES" = "78563412 78563413 88563414 " ] + then + echo Failure, not the expected files in meter readings directory. + exit 1 + fi + cat $TEST/meter_readings3/* | sed 's/"timestamp":"....-..-..T..:..:..Z"/"timestamp":"1111-11-11T11:11:11Z"/' > $TEST/test_responses.txt diff $TEST/test_expected.txt $TEST/test_responses.txt if [ "$?" == "0" ] then diff --git a/tests/test_meterfiles.sh b/tests/test_meterfiles.sh index cbf0c02..90e79fc 100755 --- a/tests/test_meterfiles.sh +++ b/tests/test_meterfiles.sh @@ -20,11 +20,23 @@ fi rm -rf /tmp/testmeters mkdir /tmp/testmeters cat simulations/simulation_c1.txt | grep '^{' | grep 76348799 | tail -n 1 > $TEST/test_expected.txt -$PROG --meterfiles=/tmp/testmeters --format=json simulations/simulation_c1.txt MyTapWater multical21 76348799 "" > /dev/null -cat /tmp/testmeters/MyTapWater | sed 's/"timestamp":"....-..-..T..:..:..Z"/"timestamp":"1111-11-11T11:11:11Z"/' > $TEST/test_response.txt +$PROG --meterfiles=/tmp/testmeters --meterfilesnaming=name-id --format=json simulations/simulation_c1.txt MyTapWater multical21 76348799 "" > /dev/null +cat /tmp/testmeters/MyTapWater-76348799 | sed 's/"timestamp":"....-..-..T..:..:..Z"/"timestamp":"1111-11-11T11:11:11Z"/' > $TEST/test_response.txt diff $TEST/test_expected.txt $TEST/test_response.txt if [ "$?" == "0" ] then echo Meterfiles dir OK rm -rf /tmp/testmeters fi + +rm -rf /tmp/testmeters +mkdir /tmp/testmeters +cat simulations/simulation_c1.txt | grep '^{' | grep 76348799 | tail -n 1 > $TEST/test_expected.txt +$PROG --meterfiles=/tmp/testmeters --meterfilesnaming=id --format=json simulations/simulation_c1.txt MyTapWater multical21 76348799 "" +cat /tmp/testmeters/76348799 | sed 's/"timestamp":"....-..-..T..:..:..Z"/"timestamp":"1111-11-11T11:11:11Z"/' > $TEST/test_response.txt +diff $TEST/test_expected.txt $TEST/test_response.txt +if [ "$?" == "0" ] +then + echo Meterfiles naming OK + rm -rf /tmp/testmeters +fi diff --git a/wmbusmeters.1 b/wmbusmeters.1 index 1f89e77..3a8eb4c 100644 --- a/wmbusmeters.1 +++ b/wmbusmeters.1 @@ -43,6 +43,8 @@ mqtt_publish) sent to a REST API (eg curl) or store it in a database \fB\--meterfilesaction=\fR(overwrite|append) overwrite or append to the meter readings file +\fB\--meterfilesnaming=\fR(name|id|name-id) the meter file is the meter's: name, id or name-id + \fB\--oneshot\fR wait for an update from each meter, then quit \fB\--separator=\fR change field separator to c