kopia lustrzana https://github.com/weetmuts/wmbusmeters
rodzic
bd63a73d0a
commit
6d6e1b5d93
11
CHANGES
11
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.
|
Update logrotate to trigger HUP when rotating log files.
|
||||||
This will re-initialize the serial connection to the usb dongle
|
This will re-initialize the serial connection to the usb dongle
|
||||||
|
|
|
@ -34,6 +34,7 @@ logtelegrams=false
|
||||||
format=json
|
format=json
|
||||||
meterfiles=/var/log/wmbusmeters/meter_readings
|
meterfiles=/var/log/wmbusmeters/meter_readings
|
||||||
meterfilesaction=overwrite
|
meterfilesaction=overwrite
|
||||||
|
meterfilesnaming=name
|
||||||
logfile=/var/log/wmbusmeters/wmbusmeters.log
|
logfile=/var/log/wmbusmeters/wmbusmeters.log
|
||||||
shell=/usr/bin/mosquitto_pub -h localhost -t wmbusmeters/$METER_ID -m "$METER_JSON"
|
shell=/usr/bin/mosquitto_pub -h localhost -t wmbusmeters/$METER_ID -m "$METER_JSON"
|
||||||
```
|
```
|
||||||
|
@ -103,6 +104,7 @@ As <options> you can use:
|
||||||
--logtelegrams log the contents of the telegrams for easy replay
|
--logtelegrams log the contents of the telegrams for easy replay
|
||||||
--meterfiles=<dir> store meter readings in dir
|
--meterfiles=<dir> store meter readings in dir
|
||||||
--meterfilesaction=(overwrite|append) overwrite or append to the meter readings file
|
--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)
|
--n1a to --n1f listen to N1 messages (perhaps)
|
||||||
--oneshot wait for an update from each meter, then quit
|
--oneshot wait for an update from each meter, then quit
|
||||||
--separator=<c> change field separator to c
|
--separator=<c> change field separator to c
|
||||||
|
|
|
@ -180,24 +180,6 @@ unique_ptr<Configuration> parseCommandLine(int argc, char **argv) {
|
||||||
i++;
|
i++;
|
||||||
continue;
|
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 (!strncmp(argv[i], "--meterfilesaction", 18)) {
|
||||||
if (strlen(argv[i]) > 18 && argv[i][18] == '=') {
|
if (strlen(argv[i]) > 18 && argv[i][18] == '=') {
|
||||||
if (!strncmp(argv[i]+19, "overwrite", 9)) {
|
if (!strncmp(argv[i]+19, "overwrite", 9)) {
|
||||||
|
@ -213,6 +195,47 @@ unique_ptr<Configuration> parseCommandLine(int argc, char **argv) {
|
||||||
i++;
|
i++;
|
||||||
continue;
|
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)) {
|
if (!strncmp(argv[i], "--logfile=", 10)) {
|
||||||
c->use_logfile = true;
|
c->use_logfile = true;
|
||||||
if (strlen(argv[i]) > 10) {
|
if (strlen(argv[i]) > 10) {
|
||||||
|
|
|
@ -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)
|
void handleLogfile(Configuration *c, string logfile)
|
||||||
{
|
{
|
||||||
if (logfile.length() > 0)
|
if (logfile.length() > 0)
|
||||||
|
@ -296,6 +316,7 @@ unique_ptr<Configuration> loadConfiguration(string root)
|
||||||
else if (p.first == "logtelegrams") handleLogtelegrams(c, p.second);
|
else if (p.first == "logtelegrams") handleLogtelegrams(c, p.second);
|
||||||
else if (p.first == "meterfiles") handleMeterfiles(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 == "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 == "logfile") handleLogfile(c, p.second);
|
||||||
else if (p.first == "format") handleFormat(c, p.second);
|
else if (p.first == "format") handleFormat(c, p.second);
|
||||||
else if (p.first == "separator") handleSeparator(c, p.second);
|
else if (p.first == "separator") handleSeparator(c, p.second);
|
||||||
|
|
|
@ -31,6 +31,11 @@ enum class MeterFileType
|
||||||
Overwrite, Append
|
Overwrite, Append
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class MeterFileNaming
|
||||||
|
{
|
||||||
|
Name, Id, NameId
|
||||||
|
};
|
||||||
|
|
||||||
struct Configuration {
|
struct Configuration {
|
||||||
bool daemon {};
|
bool daemon {};
|
||||||
std::string pid_file;
|
std::string pid_file;
|
||||||
|
@ -47,6 +52,7 @@ struct Configuration {
|
||||||
bool meterfiles {};
|
bool meterfiles {};
|
||||||
std::string meterfiles_dir;
|
std::string meterfiles_dir;
|
||||||
MeterFileType meterfiles_action {};
|
MeterFileType meterfiles_action {};
|
||||||
|
MeterFileNaming meterfiles_naming {};
|
||||||
bool use_logfile {};
|
bool use_logfile {};
|
||||||
std::string logfile;
|
std::string logfile;
|
||||||
bool json {};
|
bool json {};
|
||||||
|
|
|
@ -97,6 +97,7 @@ As <options> you can use:
|
||||||
--logtelegrams log the contents of the telegrams for easy replay
|
--logtelegrams log the contents of the telegrams for easy replay
|
||||||
--meterfiles=<dir> store meter readings in dir
|
--meterfiles=<dir> store meter readings in dir
|
||||||
--meterfilesaction=(overwrite|append) overwrite or append to the meter readings file
|
--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
|
--oneshot wait for an update from each meter, then quit
|
||||||
--separator=<c> change field separator to c
|
--separator=<c> change field separator to c
|
||||||
--shell=<cmdline> invokes cmdline with env variables containing the latest reading
|
--shell=<cmdline> 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->separator, config->meterfiles, config->meterfiles_dir,
|
||||||
config->use_logfile, config->logfile,
|
config->use_logfile, config->logfile,
|
||||||
config->shells,
|
config->shells,
|
||||||
config->meterfiles_action == MeterFileType::Overwrite));
|
config->meterfiles_action == MeterFileType::Overwrite,
|
||||||
|
config->meterfiles_naming));
|
||||||
vector<unique_ptr<Meter>> meters;
|
vector<unique_ptr<Meter>> meters;
|
||||||
|
|
||||||
if (config->meters.size() > 0) {
|
if (config->meters.size() > 0) {
|
||||||
|
|
|
@ -23,7 +23,8 @@ using namespace std;
|
||||||
Printer::Printer(bool json, bool fields, char separator,
|
Printer::Printer(bool json, bool fields, char separator,
|
||||||
bool use_meterfiles, string &meterfiles_dir,
|
bool use_meterfiles, string &meterfiles_dir,
|
||||||
bool use_logfile, string &logfile,
|
bool use_logfile, string &logfile,
|
||||||
vector<string> shell_cmdlines, bool overwrite)
|
vector<string> shell_cmdlines, bool overwrite,
|
||||||
|
MeterFileNaming naming)
|
||||||
{
|
{
|
||||||
json_ = json;
|
json_ = json;
|
||||||
fields_ = fields;
|
fields_ = fields;
|
||||||
|
@ -34,6 +35,7 @@ Printer::Printer(bool json, bool fields, char separator,
|
||||||
logfile_ = logfile;
|
logfile_ = logfile;
|
||||||
shell_cmdlines_ = shell_cmdlines;
|
shell_cmdlines_ = shell_cmdlines;
|
||||||
overwrite_ = overwrite;
|
overwrite_ = overwrite;
|
||||||
|
naming_ = naming;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Printer::print(Telegram *t, Meter *meter)
|
void Printer::print(Telegram *t, Meter *meter)
|
||||||
|
@ -49,12 +51,12 @@ void Printer::print(Telegram *t, Meter *meter)
|
||||||
printed = true;
|
printed = true;
|
||||||
}
|
}
|
||||||
if (use_meterfiles_) {
|
if (use_meterfiles_) {
|
||||||
printFiles(meter, human_readable, fields, json);
|
printFiles(meter, t, human_readable, fields, json);
|
||||||
printed = true;
|
printed = true;
|
||||||
}
|
}
|
||||||
if (!printed) {
|
if (!printed) {
|
||||||
// This will print on stdout or in the logfile.
|
// 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<string> &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;
|
FILE *output = stdout;
|
||||||
|
|
||||||
if (use_meterfiles_) {
|
if (use_meterfiles_) {
|
||||||
char filename[128];
|
char filename[128];
|
||||||
memset(filename, 0, sizeof(filename));
|
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";
|
const char *mode = overwrite_ ? "w" : "a";
|
||||||
output = fopen(filename, mode);
|
output = fopen(filename, mode);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include"cmdline.h"
|
#include"cmdline.h"
|
||||||
#include"meters.h"
|
#include"meters.h"
|
||||||
|
#include"wmbus.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -27,7 +28,8 @@ struct Printer {
|
||||||
bool meterfiles, string &meterfiles_dir,
|
bool meterfiles, string &meterfiles_dir,
|
||||||
bool use_logfile, string &logfile,
|
bool use_logfile, string &logfile,
|
||||||
vector<string> shell_cmdlines,
|
vector<string> shell_cmdlines,
|
||||||
bool overwrite);
|
bool overwrite,
|
||||||
|
MeterFileNaming naming);
|
||||||
|
|
||||||
void print(Telegram *t, Meter *meter);
|
void print(Telegram *t, Meter *meter);
|
||||||
|
|
||||||
|
@ -41,8 +43,9 @@ struct Printer {
|
||||||
char separator_;
|
char separator_;
|
||||||
vector<string> shell_cmdlines_;
|
vector<string> shell_cmdlines_;
|
||||||
bool overwrite_;
|
bool overwrite_;
|
||||||
|
MeterFileNaming naming_;
|
||||||
|
|
||||||
void printShells(Meter *meter, vector<string> &envs);
|
void printShells(Meter *meter, vector<string> &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);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,4 +4,5 @@ logtelegrams=false
|
||||||
format=json
|
format=json
|
||||||
meterfiles=testoutput/meter_readings3
|
meterfiles=testoutput/meter_readings3
|
||||||
meterfilesaction=append
|
meterfilesaction=append
|
||||||
|
meterfilesnaming=id
|
||||||
logfile=testoutput/thelog3.txt
|
logfile=testoutput/thelog3.txt
|
||||||
|
|
|
@ -4,14 +4,20 @@ PROG="$1"
|
||||||
TEST=testoutput
|
TEST=testoutput
|
||||||
mkdir -p $TEST/meter_readings3
|
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
|
cat simulations/simulation_multiple_qcalorics.txt | grep '^{' > $TEST/test_expected.txt
|
||||||
|
|
||||||
$PROG --useconfig=tests/config3 > $TEST/test_output.txt
|
$PROG --useconfig=tests/config3 > $TEST/test_output.txt
|
||||||
|
|
||||||
if [ "$?" == "0" ]
|
if [ "$?" == "0" ]
|
||||||
then
|
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
|
diff $TEST/test_expected.txt $TEST/test_responses.txt
|
||||||
if [ "$?" == "0" ]
|
if [ "$?" == "0" ]
|
||||||
then
|
then
|
||||||
|
|
|
@ -20,11 +20,23 @@ fi
|
||||||
rm -rf /tmp/testmeters
|
rm -rf /tmp/testmeters
|
||||||
mkdir /tmp/testmeters
|
mkdir /tmp/testmeters
|
||||||
cat simulations/simulation_c1.txt | grep '^{' | grep 76348799 | tail -n 1 > $TEST/test_expected.txt
|
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
|
$PROG --meterfiles=/tmp/testmeters --meterfilesnaming=name-id --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
|
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
|
diff $TEST/test_expected.txt $TEST/test_response.txt
|
||||||
if [ "$?" == "0" ]
|
if [ "$?" == "0" ]
|
||||||
then
|
then
|
||||||
echo Meterfiles dir OK
|
echo Meterfiles dir OK
|
||||||
rm -rf /tmp/testmeters
|
rm -rf /tmp/testmeters
|
||||||
fi
|
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
|
||||||
|
|
|
@ -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\--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\--oneshot\fR wait for an update from each meter, then quit
|
||||||
|
|
||||||
\fB\--separator=\fR<c> change field separator to c
|
\fB\--separator=\fR<c> change field separator to c
|
||||||
|
|
Ładowanie…
Reference in New Issue