kopia lustrzana https://github.com/weetmuts/wmbusmeters
Updated command line options and added man page
rodzic
c3bf72b155
commit
58e89749d3
3
CHANGES
3
CHANGES
|
@ -7,6 +7,7 @@ Running wmbusmeters as daemon is now supported.
|
|||
Using rtl_wmbus to receive wmbus messages from
|
||||
rtl_sdr is work in progress.
|
||||
Updated README
|
||||
Updated some command line options robot is now format.
|
||||
|
||||
Version 0.8.4: 2019-02-23
|
||||
|
||||
|
@ -24,7 +25,7 @@ Now properly extracts temperature from short frames!
|
|||
Added support for Multical21 meters with max flow configuration.
|
||||
|
||||
Note! Since max flow was added to multical21, there is an extra
|
||||
column in the human output and --robot=fields output.
|
||||
column in the human output and --format=fields output.
|
||||
There is also "max_flow_m3h"="123" in the json output, but that does not
|
||||
affect existing code depending on json.
|
||||
|
||||
|
|
99
README.md
99
README.md
|
@ -27,7 +27,7 @@ Check the config file /etc/wmbusmeters.conf:
|
|||
loglevel=normal
|
||||
device=auto
|
||||
logtelegrams=false
|
||||
meterfilesdir=/var/log/wmbusmeters/meter_readings
|
||||
meterfiles=/var/log/wmbusmeters/meter_readings
|
||||
logfile=/var/log/wmbusmeters/wmbusmeters.log
|
||||
shell=/usr/bin/mosquitto_pub -h localhost -t wmbusmeters -m "$METER_JSON"
|
||||
```
|
||||
|
@ -66,31 +66,45 @@ The files/dir should then be located here:
|
|||
|
||||
```
|
||||
wmbusmeters version: 0.9
|
||||
Usage: wmbusmeters {options} (auto | /dev/ttyUSBx)] { [meter_name] [meter_type] [meter_id] [meter_key] }*
|
||||
Usage: wmbusmeters {options} <device> ( [meter_name] [meter_type] [meter_id] [meter_key] )*
|
||||
|
||||
Add more meter quadruplets to listen to more meters.
|
||||
Add --verbose for detailed debug information.
|
||||
--robot or --robot=json for json output.
|
||||
--robot=fields for semicolon separated fields.
|
||||
--separator=X change field separator to X.
|
||||
--logfile=file
|
||||
--meterfiles=dir to create status files below dir,
|
||||
named dir/meter_name, containing the latest reading.
|
||||
--meterfiles defaults dir to /tmp.
|
||||
--c1 or --t1 listen to C1 or T1 messages
|
||||
--shell=cmd invokes cmd with env variables containing the latest reading.
|
||||
--shellenvs list the env variables available for the meter.
|
||||
--oneshot wait for an update from each meter, then quit.
|
||||
--useconfig=dir look for configuration file in dir/etc/wmbusmeters.conf and
|
||||
dir/etc/wmbusmeters.d
|
||||
--useconfig defaults to the root /etc
|
||||
--exitafter=20h program exits after running for twenty hours,
|
||||
or 10m for ten minutes or 5s for five seconds.
|
||||
As <options> you can use:
|
||||
|
||||
Specifying auto as the device will automatically look for usb
|
||||
wmbus dongles on /dev/im871a and /dev/amb8465.
|
||||
--c1 or --t1 listen to C1 or T1 messages when no meters are supplied
|
||||
--debug for a lot of information
|
||||
--exitafter=<time> exit program after time, eg 20h, 10m 5s
|
||||
--format=<hr/json/fields> for human readable, json or semicolon separated fields
|
||||
--logfile=<file> use this file instead of stdout
|
||||
--logtelegrams log the contents of the telegrams for easy replay
|
||||
--meterfiles=<dir> store meter readings in dir
|
||||
--meterfilesaction=(overwrite|append) overwrite or append to the meter readings file
|
||||
--oneshot wait for an update from each meter, then quit
|
||||
--separator=<c> change field separator to c
|
||||
--shell=<cmdline> invokes cmdline with env variables containing the latest reading
|
||||
--shellenvs list the env variables available for the meter
|
||||
--useconfig=<dir> load config files from dir/etc
|
||||
--verbose for more information
|
||||
|
||||
You can specify the device rtlwmbus to have wmbusmeters spawn rtl_sdr|rtlwmbus
|
||||
As a <device> you can use:
|
||||
|
||||
"/dev/ttyUSB" to which a im871a/amb8465 dongle is attached,
|
||||
or you can specify auto and wmbusmeters will look for a suitable dongle
|
||||
on the device links /dev/im871a and /dev/amb8465.
|
||||
|
||||
"rtlwmbus:868.95M" to have wmbusmeters spawn:
|
||||
"rtl_sdr -f 868.95M -s 1600000 - 2>/dev/null | rtl_wmbus"
|
||||
(you might have to tweak 868.95M to nearby frequencies depending
|
||||
on the rtl-sdr dongle you are using)
|
||||
|
||||
"rtlwmbus:<commandline>" to have wmbusmeters spawn
|
||||
that commandline instead, the output is expected to be like rtl_wmbus.
|
||||
|
||||
As meter quadruples you specify:
|
||||
<meter_name> a mnemonic for this particular meter
|
||||
<meter_type> one of the supported meters
|
||||
<meter_id> an 8 digit mbus id, usually printed on the meter
|
||||
<meter_key> an encryption key unique for the meter
|
||||
if the meter uses no encryption, then supply ""
|
||||
|
||||
Supported water meters:
|
||||
Kamstrup Multical 21 (multical21)
|
||||
|
@ -104,13 +118,6 @@ Electricity meter Kamstrup Omnipower (omnipower)
|
|||
Heat cost allocator Qundis Q caloric (qcaloric)
|
||||
```
|
||||
|
||||
No meter quadruplets means listen for telegram traffic and print any id heard,
|
||||
but you have to specify if you want to listen using radio mode C1 or T1. E.g.
|
||||
|
||||
```
|
||||
wmbusmeters --t1 /dev/ttyUSB0
|
||||
```
|
||||
|
||||
You can listen to multiple meters as long as they all require the same radio mode C1 or T1.
|
||||
So (currently) you cannot listen to a multical21 and a supercom587 with a single dongle at the same time.
|
||||
|
||||
|
@ -128,17 +135,17 @@ Example output:
|
|||
|
||||
(Here the multical21 itself, is configured to send target volume, therefore the max flow is 0.000 m3/h.)
|
||||
|
||||
Example robot json output:
|
||||
Example format json output:
|
||||
|
||||
`wmbusmeters --robot=json auto MyTapWater multical21 12345678 00112233445566778899AABBCCDDEEFF MyHeater multical302 22222222 00112233445566778899AABBCCDDEEFF`
|
||||
`wmbusmeters --format=json auto MyTapWater multical21 12345678 00112233445566778899AABBCCDDEEFF MyHeater multical302 22222222 00112233445566778899AABBCCDDEEFF`
|
||||
|
||||
`{"media":"cold water","meter":"multical21","name":"MyTapWater","id":"12345678","total_m3":6.388,"target_m3":6.377,"max_flow_m3h":0.000,"flow_temperature":8,"external_temperature":23,"current_status":"DRY","time_dry":"22-31 days","time_reversed":"","time_leaking":"","time_bursting":"","timestamp":"2018-02-08T09:07:22Z"}`
|
||||
|
||||
`{"media":"heat","meter":"multical302","name":"MyHeater","id":"22222222","total_kwh":0.000,"total_volume_m3":0.000,"current_kw":"0.000","timestamp":"2018-02-08T09:07:22Z"}`
|
||||
|
||||
Example robot fields output:
|
||||
Example format fields output:
|
||||
|
||||
`wmbusmeters --robot=fields auto GreenhouseWater multical21 33333333 ""`
|
||||
`wmbusmeters --format=fields auto GreenhouseWater multical21 33333333 ""`
|
||||
|
||||
`GreenhouseTapWater;33333333;9999.099;77.712;0.000;11;31;;2018-03-05 12:10.24`
|
||||
|
||||
|
@ -158,7 +165,7 @@ You can use `--debug` to get both verbose output and the actual data bytes sent
|
|||
If the meter does not use encryption of its meter data, then enter an empty key on the command line.
|
||||
(you must enter "")
|
||||
|
||||
`wmbusmeters --robot --meterfiles auto MyTapWater multical21 12345678 ""`
|
||||
`wmbusmeters --format=json --meterfiles auto MyTapWater multical21 12345678 ""`
|
||||
|
||||
If you have a Multical21 meter and you have received a KEM file and its password,
|
||||
from your water municipality, then you can use the XMLExtract.java utility to get
|
||||
|
@ -194,19 +201,19 @@ Binary generated: `./wmbusmeters_0.8_armhf.deb`
|
|||
|
||||
# System configuration
|
||||
|
||||
Add yourself to the dialout group to get access to the newly plugged in im871A USB stick.
|
||||
Or even better, add this udev rule:
|
||||
`make install` installs `/usr/bin/wmbusmeters`, `/usr/sbin/wmbusmetersd`, `wmbusmeters.service`
|
||||
and `99-wmbus-usb-serial.rules`.
|
||||
|
||||
Create the file: `/etc/udev/rules.d/99-usb-serial.rules` with the content
|
||||
```
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SYMLINK+="im871a",MODE="0660", GROUP="yourowngroup"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="amb8465",MODE="0660", GROUP="yourowngroup"
|
||||
```
|
||||
This means that when a im871a/amb8465 dongle is inserted, then the appropriate /dev/im871a or
|
||||
/dev/amb8465 link is created. Also the wmbusmeters daemon will be automatically
|
||||
started/stopped whenever the im871a/amb8465 dongle is inserted/removed,
|
||||
and the daemon starts when the computer boots, if the dongle is already inserted.
|
||||
|
||||
When you insert the wmbus USB dongle, a properly named symlink will be
|
||||
created: either `/dev/im871a` or `/dev/amb8465`. These symlinks are
|
||||
necessary if you want to pass "auto" to wmbusmeters instead of the
|
||||
exact serial port /dev/ttyUSBx.
|
||||
If you do not want the daemon to start automatically, simply edit
|
||||
/dev/udev/rules.d/99-wmbus-usb-serial.rules and remove `,TAG+="systemd",ENV{SYSTEMD_WANTS}="wmbusmeters.service"`
|
||||
from each line.
|
||||
|
||||
You can also start/stop the daemon with `sudo systemctl start wmbusmeters`
|
||||
|
||||
# Source code
|
||||
|
||||
|
|
15
install.sh
15
install.sh
|
@ -47,6 +47,17 @@ ln -s $ROOT/usr/bin/wmbusmeters $ROOT/usr/sbin/wmbusmetersd
|
|||
|
||||
echo binaries: installed $ROOT/usr/bin/wmbusmeters and $ROOT/usr/sbin/wmbusmetersd
|
||||
|
||||
####################################################################
|
||||
##
|
||||
## Intall wmbusmeters manual page
|
||||
##
|
||||
|
||||
rm -f $ROOT/usr/share/man/man1/wmbusmeters.1.gz
|
||||
mkdir -p $ROOT/usr/share/man/man1
|
||||
gzip -c wmbusmeters.1 > $ROOT/usr/share/man/man1/wmbusmeters.1.gz
|
||||
|
||||
echo man page: installed $ROOT/usr/share/man/man1/wmbusmeters.1.gz
|
||||
|
||||
####################################################################
|
||||
##
|
||||
## Create wmbusmeters user
|
||||
|
@ -126,8 +137,8 @@ then
|
|||
loglevel=normal
|
||||
device=auto
|
||||
logtelegrams=false
|
||||
robot=json
|
||||
meterfilesdir=/var/log/wmbusmeters/meter_readings
|
||||
format=json
|
||||
meterfiles=/var/log/wmbusmeters/meter_readings
|
||||
meterfilestype=overwrite
|
||||
logfile=/var/log/wmbusmeters/wmbusmeters.log
|
||||
EOF
|
||||
|
|
|
@ -115,29 +115,29 @@ unique_ptr<Configuration> parseCommandLine(int argc, char **argv) {
|
|||
}
|
||||
return unique_ptr<Configuration>(c);
|
||||
}
|
||||
if (!strncmp(argv[i], "--robot", 7)) {
|
||||
if (strlen(argv[i]) == 7 ||
|
||||
(strlen(argv[i]) == 12 &&
|
||||
!strncmp(argv[i]+7, "=json", 5)))
|
||||
if (!strncmp(argv[i], "--format", 8)) {
|
||||
if (strlen(argv[i]) == 8 ||
|
||||
(strlen(argv[i]) == 13 &&
|
||||
!strncmp(argv[i]+8, "=json", 5)))
|
||||
{
|
||||
c->json = true;
|
||||
c->fields = false;
|
||||
}
|
||||
else if (strlen(argv[i]) == 14 &&
|
||||
else if (strlen(argv[i]) == 15 &&
|
||||
!strncmp(argv[i]+7, "=fields", 7))
|
||||
{
|
||||
c->json = false;
|
||||
c->fields = true;
|
||||
c->separator = ';';
|
||||
} else {
|
||||
error("Unknown output format: \"%s\"\n", argv[i]+7);
|
||||
error("Unknown output format: \"%s\"\n", argv[i]+8);
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(argv[i], "--separator=", 12)) {
|
||||
if (!c->fields) {
|
||||
error("You must specify --robot=fields before --separator=X\n");
|
||||
error("You must specify --format=fields before --separator=X\n");
|
||||
}
|
||||
if (strlen(argv[i]) != 13) {
|
||||
error("You must supply a single character as the field separator.\n");
|
||||
|
@ -164,6 +164,21 @@ unique_ptr<Configuration> parseCommandLine(int argc, char **argv) {
|
|||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(argv[i], "--meterfilesaction", 18)) {
|
||||
if (strlen(argv[i]) > 18 && argv[i][18] == '=') {
|
||||
if (!strncmp(argv[i]+19, "overwrite", 9)) {
|
||||
c->meterfiles_action = MeterFileType::Overwrite;
|
||||
} else if (!strncmp(argv[i]+19, "append", 6)) {
|
||||
c->meterfiles_action = MeterFileType::Append;
|
||||
} else {
|
||||
error("No such meter file action %s\n", argv[i]+19);
|
||||
}
|
||||
} else {
|
||||
error("Incorrect option %s\n", argv[i]);
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(argv[i], "--logfile=", 10)) {
|
||||
c->use_logfile = true;
|
||||
if (strlen(argv[i]) > 10) {
|
||||
|
|
|
@ -118,11 +118,11 @@ void handleLogtelegrams(Configuration *c, string logtelegrams)
|
|||
}
|
||||
}
|
||||
|
||||
void handleMeterfilesdir(Configuration *c, string meterfilesdir)
|
||||
void handleMeterfiles(Configuration *c, string meterfiles)
|
||||
{
|
||||
if (meterfilesdir.length() > 0)
|
||||
if (meterfiles.length() > 0)
|
||||
{
|
||||
c->meterfiles_dir = meterfilesdir;
|
||||
c->meterfiles_dir = meterfiles;
|
||||
c->meterfiles = true;
|
||||
if (!checkIfDirExists(c->meterfiles_dir.c_str())) {
|
||||
warning("Cannot write meter files into dir \"%s\"\n", c->meterfiles_dir.c_str());
|
||||
|
@ -130,16 +130,16 @@ void handleMeterfilesdir(Configuration *c, string meterfilesdir)
|
|||
}
|
||||
}
|
||||
|
||||
void handleMeterfilestype(Configuration *c, string meterfilestype)
|
||||
void handleMeterfilesAction(Configuration *c, string meterfilesaction)
|
||||
{
|
||||
if (meterfilestype == "overwrite")
|
||||
if (meterfilesaction == "overwrite")
|
||||
{
|
||||
c->meterfiles_type = MeterFileType::Overwrite;
|
||||
} else if (meterfilestype == "append")
|
||||
c->meterfiles_action = MeterFileType::Overwrite;
|
||||
} else if (meterfilesaction == "append")
|
||||
{
|
||||
c->meterfiles_type = MeterFileType::Append;
|
||||
c->meterfiles_action = MeterFileType::Append;
|
||||
} else {
|
||||
warning("No such meter file type \"%s\"\n", meterfilestype.c_str());
|
||||
warning("No such meter file action \"%s\"\n", meterfilesaction.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,20 +152,24 @@ void handleLogfile(Configuration *c, string logfile)
|
|||
}
|
||||
}
|
||||
|
||||
void handleRobot(Configuration *c, string robot)
|
||||
void handleFormat(Configuration *c, string format)
|
||||
{
|
||||
if (robot == "json")
|
||||
if (format == "hr")
|
||||
{
|
||||
c->json = false;
|
||||
c->fields = false;
|
||||
} else if (format == "json")
|
||||
{
|
||||
c->json = true;
|
||||
c->fields = false;
|
||||
}
|
||||
else if (robot == "fields")
|
||||
else if (format == "fields")
|
||||
{
|
||||
c->json = false;
|
||||
c->fields = true;
|
||||
c->separator = ';';
|
||||
} else {
|
||||
warning("Unknown output format: \"%s\"\n", robot.c_str());
|
||||
warning("Unknown output format: \"%s\"\n", format.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,10 +209,10 @@ unique_ptr<Configuration> loadConfiguration(string root)
|
|||
if (p.first == "loglevel") handleLoglevel(c, p.second);
|
||||
else if (p.first == "device") handleDevice(c, p.second);
|
||||
else if (p.first == "logtelegrams") handleLogtelegrams(c, p.second);
|
||||
else if (p.first == "meterfilesdir") handleMeterfilesdir(c, p.second);
|
||||
else if (p.first == "meterfilestype") handleMeterfilestype(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 == "logfile") handleLogfile(c, p.second);
|
||||
else if (p.first == "robot") handleRobot(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 == "shell") handleShell(c, p.second);
|
||||
else
|
||||
|
|
|
@ -56,7 +56,7 @@ struct Configuration {
|
|||
bool logtelegrams {};
|
||||
bool meterfiles {};
|
||||
std::string meterfiles_dir;
|
||||
MeterFileType meterfiles_type {};
|
||||
MeterFileType meterfiles_action {};
|
||||
bool use_logfile {};
|
||||
std::string logfile;
|
||||
bool json {};
|
||||
|
|
80
src/main.cc
80
src/main.cc
|
@ -48,37 +48,59 @@ int main(int argc, char **argv)
|
|||
|
||||
if (cmdline->need_help) {
|
||||
printf("wmbusmeters version: " WMBUSMETERS_VERSION "\n");
|
||||
printf("Usage: wmbusmeters [options] (auto | /dev/ttyUSBx) { [meter_name] [meter_type] [meter_id] [meter_key] }* \n\n");
|
||||
printf("Add more meter quadruplets to listen to more meters.\n");
|
||||
printf("Add --verbose for more detailed information on communication.\n");
|
||||
printf(" --robot or --robot=json for json output.\n");
|
||||
printf(" --robot=fields for semicolon separated fields.\n");
|
||||
printf(" --separator=X change field separator to X.\n");
|
||||
printf(" --logfile=file\n");
|
||||
printf(" --meterfiles=dir to create status files below dir,\n"
|
||||
" named dir/meter_name, containing the latest reading.\n");
|
||||
printf(" --meterfiles defaults dir to /tmp.\n");
|
||||
printf(" --shell=cmd invokes cmd with env variables containing the latest reading.\n");
|
||||
printf(" --shellenvs list the env variables available for the meter.\n");
|
||||
printf(" --oneshot wait for an update from each meter, then quit.\n");
|
||||
printf(" --useconfig=dir look for configuration file in dir/etc/wmbusmeters.conf and\n");
|
||||
printf(" dir/etc/wmbusmeters.d\n");
|
||||
printf(" --useconfig defaults to the root /etc\n");
|
||||
printf(" --exitafter=20h program exits after running for twenty hoursh\n"
|
||||
" or 10m for ten minutes or 5s for five seconds.\n");
|
||||
printf(" --useconfig read from /etc/wmbusmeters.conf and /etc/wmbusmeters.d\n");
|
||||
printf(" check the man page for how to write the config files.\n");
|
||||
printf(" --reload signals a running wmbusmeters daemon to reload the configuration,\n");
|
||||
printf(" when you have modified config files and/or usb dongles.\n\n");
|
||||
const char *msg = R"MANUAL(
|
||||
Usage: wmbusmeters {options} <device> ( [meter_name] [meter_type] [meter_id] [meter_key] )*
|
||||
|
||||
printf("Specifying auto as the device will automatically look for usb\n");
|
||||
printf("wmbus dongles on /dev/im871a and /dev/amb8465\n\n");
|
||||
As <options> you can use:
|
||||
|
||||
printf("You can specify the device rtlwmbus to have wmbusmeters spawn rtl_sdr|rtlwmbus\n\n");
|
||||
--c1 or --t1 listen to C1 or T1 messages when no meters are supplied
|
||||
--debug for a lot of information
|
||||
--exitafter=<time> exit program after time, eg 20h, 10m 5s
|
||||
--format=<hr/json/fields> for human readable, json or semicolon separated fields
|
||||
--logfile=<file> use this file instead of stdout
|
||||
--logtelegrams log the contents of the telegrams for easy replay
|
||||
--meterfiles=<dir> store meter readings in dir
|
||||
--meterfilesaction=(overwrite|append) overwrite or append to the meter readings file
|
||||
--oneshot wait for an update from each meter, then quit
|
||||
--separator=<c> change field separator to c
|
||||
--shell=<cmdline> invokes cmdline with env variables containing the latest reading
|
||||
--shellenvs list the env variables available for the meter
|
||||
--useconfig=<dir> load config files from dir/etc
|
||||
--verbose for more information
|
||||
|
||||
printf("The meter types: multical21,flowiq3100,supercom587,iperl (water meters) are supported.\n"
|
||||
"The meter types: multical302 (heat) and omnipower (electricity) qcaloric (heat cost)\n"
|
||||
"are work in progress.\n\n");
|
||||
As a <device> you can use:
|
||||
|
||||
"/dev/ttyUSB" to which a im871a/amb8465 dongle is attached,
|
||||
or you can specify auto and wmbusmeters will look for a suitable dongle
|
||||
on the device links /dev/im871a and /dev/amb8465.
|
||||
|
||||
"rtlwmbus:868.95M" to have wmbusmeters spawn:
|
||||
"rtl_sdr -f 868.95M -s 1600000 - 2>/dev/null | rtl_wmbus"
|
||||
(you might have to tweak 868.95M to nearby frequencies depending
|
||||
on the rtl-sdr dongle you are using)
|
||||
|
||||
"rtlwmbus:<commandline>" to have wmbusmeters spawn
|
||||
that commandline instead, the output is expected to be like rtl_wmbus.
|
||||
|
||||
As meter quadruples you specify:
|
||||
<meter_name> a mnemonic for this particular meter
|
||||
<meter_type> one of the supported meters
|
||||
<meter_id> an 8 digit mbus id, usually printed on the meter
|
||||
<meter_key> an encryption key unique for the meter
|
||||
if the meter uses no encryption, then supply ""
|
||||
|
||||
Supported water meters:
|
||||
Kamstrup Multical 21 (multical21)
|
||||
Kamstrup flowIQ 3100 (flowiq3100)
|
||||
Sontex Supercom 587 (supercom587)
|
||||
Sensus iPERL (iperl)
|
||||
|
||||
Work in progress:
|
||||
Heat meter Kamstrup Multical 302 (multical302)
|
||||
Electricity meter Kamstrup Omnipower (omnipower)
|
||||
Heat cost allocator Qundis Q caloric (qcaloric)
|
||||
)MANUAL";
|
||||
puts(msg);
|
||||
}
|
||||
else
|
||||
if (cmdline->daemon) {
|
||||
|
@ -183,7 +205,7 @@ void startUsingCommandline(Configuration *config)
|
|||
auto output = unique_ptr<Printer>(new Printer(config->json, config->fields,
|
||||
config->separator, config->meterfiles, config->meterfiles_dir,
|
||||
config->shells,
|
||||
config->meterfiles_type == MeterFileType::Overwrite));
|
||||
config->meterfiles_action == MeterFileType::Overwrite));
|
||||
vector<unique_ptr<Meter>> meters;
|
||||
|
||||
if (config->meters.size() > 0) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
loglevel=normal
|
||||
device=simulations/simulation_c1.txt
|
||||
logtelegrams=false
|
||||
robot=json
|
||||
format=json
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
loglevel=normal
|
||||
device=simulations/simulation_t1.txt
|
||||
logtelegrams=false
|
||||
robot=json
|
||||
meterfilesdir=testoutput/meter_readings2
|
||||
format=json
|
||||
meterfiles=testoutput/meter_readings2
|
||||
logfile=testoutput/thelog2.txt
|
||||
|
|
|
@ -7,7 +7,7 @@ mkdir -p testoutput
|
|||
TEST=testoutput
|
||||
|
||||
cat simulations/simulation_c1.txt | grep '^{' > $TEST/test_expected.txt
|
||||
$PROG --robot=json simulations/simulation_c1.txt \
|
||||
$PROG --format=json simulations/simulation_c1.txt \
|
||||
MyHeater multical302 12345678 "" \
|
||||
MyTapWater multical21 76348799 "" \
|
||||
Vadden multical21 44556677 "" \
|
||||
|
|
|
@ -46,5 +46,5 @@ if [ "$ERRORS" = "true" ]
|
|||
then
|
||||
echo Failed config2 tests
|
||||
else
|
||||
echo Config2 with logfile and meterfilesdir OK
|
||||
echo Config2 with logfile and meterfiles OK
|
||||
fi
|
||||
|
|
|
@ -8,7 +8,7 @@ TEST=testoutput
|
|||
|
||||
rm -f /tmp/MyTapWater
|
||||
cat simulations/simulation_c1.txt | grep '^{' | grep 76348799 | tail -n 1 > $TEST/test_expected.txt
|
||||
$PROG --meterfiles --robot=json simulations/simulation_c1.txt MyTapWater multical21 76348799 "" > /dev/null
|
||||
$PROG --meterfiles --format=json simulations/simulation_c1.txt MyTapWater multical21 76348799 "" > /dev/null
|
||||
cat /tmp/MyTapWater | 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" ]
|
||||
|
@ -20,7 +20,7 @@ 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 --robot=json simulations/simulation_c1.txt MyTapWater multical21 76348799 "" > /dev/null
|
||||
$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
|
||||
diff $TEST/test_expected.txt $TEST/test_response.txt
|
||||
if [ "$?" == "0" ]
|
||||
|
|
|
@ -7,7 +7,7 @@ mkdir -p testoutput
|
|||
TEST=testoutput
|
||||
|
||||
cat simulations/simulation_t1.txt | grep '^{' > $TEST/test_expected.txt
|
||||
$PROG --robot=json simulations/simulation_t1.txt \
|
||||
$PROG --format=json simulations/simulation_t1.txt \
|
||||
MyWarmWater supercom587 12345678 "" \
|
||||
MyColdWater supercom587 11111111 "" \
|
||||
MoreWater iperl 12345699 "" \
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
.TH BEAK 1
|
||||
.SH NAME
|
||||
wmbusmeters \- read the wireless mbus protocol to acquire and relay utility meter readings.
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B wmbusmeters [options] <device> (<meter_name> <meter_type> <meter_id> meter_key>)*
|
||||
|
||||
.B wmbusmetersd <pid_file>
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
Wmbusmeters acquires wmbus telegrams, parses them and relays them to some other software for further processing.
|
||||
It can for example listen to radio traffic using dedicated wmbus dongles like (im871a/amb8465) or
|
||||
a generic software defined radio dongle (rtl_sdr).
|
||||
|
||||
After the received telegram has been decrypted and parsed, it is relayed using a shell command, or stored in a log file.
|
||||
The shell commands can for example relay the telegram using MQTT (eg mqtt_publish) sent to a REST API (eg curl)
|
||||
or store it in a database (eg psql).
|
||||
|
||||
.SH OPTIONS
|
||||
[\fB\--c1\fR] listen to C1 messages when no meters are supplied
|
||||
|
||||
[\fB\--debug\fR] for a lot of information
|
||||
|
||||
[\fB\--exitafter=\fR<time>] exit program after time, eg 20h, 10m 5s
|
||||
|
||||
[\fB\--format=\fR(hr|json|fields)] for human readable, json or semicolon separated fields
|
||||
|
||||
[\fB\--logfile=\fR<dir>] use this file instead of stdout
|
||||
|
||||
[\fB\--logtelegrams\fR] log the contents of the telegrams for easy replay
|
||||
|
||||
[\fB\--meterfiles=\fR<dir>] store meter readings in dir
|
||||
|
||||
[\fB\--meterfilesaction=\fR(overwrite|append)] overwrite or append to the meter readings file
|
||||
|
||||
[\fB\--oneshot\fR] wait for an update from each meter, then quit
|
||||
|
||||
[\fB\--separator=\fR<c>] change field separator to c
|
||||
|
||||
[\fB\--shell=\fR<cmdline>] invokes cmdline with env variables containing the latest reading
|
||||
|
||||
[\fB\--shellenvs\fR] list the env variables available for the meter
|
||||
|
||||
[\fB\--t1\fR] listen to T1 messages when no meters are supplied
|
||||
|
||||
[\fB\--useconfig=\fR<dir>] load config files from dir/etc
|
||||
|
||||
[\fB\--verbose\fR] for more information
|
||||
|
||||
.SH DEVICES
|
||||
.TP
|
||||
[\fB/dev/ttyUSB0\fR] to which an im871a or amb8456 dongle is attached
|
||||
|
||||
.TP
|
||||
[\fBauto\fR] look for /dev/im871a or /dev/amb8465
|
||||
|
||||
.TP
|
||||
[\fBrtlwmbus:<freq>\fR] use software defined radio rtl_sdr|rtl_wmbus to received wmbus telegrams
|
||||
|
||||
.TP
|
||||
[\fBsimulation.txt\fR] read telegrams from file to replay telegram feed (use --logtelegrams to acquire feed for replay)
|
||||
|
||||
.SH METER QUADRUPLES
|
||||
.TP
|
||||
[\fBmeter_name\fR] a mnemonic for your utility meter
|
||||
.TP
|
||||
[\fBmeter_type\fR] multical21/flowiq3100/supercom587/iperl/multical302/omnipower/qcaloric
|
||||
.TP
|
||||
[\fBmeter_id\fR] an 8 digit number, usually printed on the meter
|
||||
.TP
|
||||
[\fBmeter_key\fR] a unique key for the meter, if meter telegrams are not encrypted, you must supply an empty key: ""
|
||||
|
||||
.SH EXAMPLES
|
||||
.TP
|
||||
|
||||
Listen to T1 traffic using a wmbus dongle attached to ttyUSB0.
|
||||
|
||||
% wmbusmeters --t1 /dev/ttyUSB0
|
||||
|
||||
.TP
|
||||
Listen to C1 traffic and assume that a wmbus dongle is either /dev/im871a or /dev/amb8465.
|
||||
|
||||
% wmbusmeters --c1 auto
|
||||
|
||||
.TP
|
||||
Listen to both T1 and C1 traffic using rtl_sdr|rtl_wmbus and the standard frequency 868.95M, which
|
||||
might need tweaking depending on the rtl_sdr dongle you are using.
|
||||
|
||||
% wmbusmeters rtlwmbus:868.95M
|
||||
|
||||
.TP
|
||||
Execute using config file /home/me/etc/wmbusmeters.conf and meter config files in /home/me/etc/wmbusmeters.d
|
||||
|
||||
% wmbusmeters --useconfig=/home/me
|
||||
|
||||
.TP
|
||||
Start a daemon using config file /etc/wmbusmeters.conf and meter config files in /etc/wmbusmeters.d
|
||||
|
||||
% wmbusmetersd --useconfig=/
|
||||
|
||||
.TP
|
||||
An example wmbusmeters.conf:
|
||||
|
||||
.nf
|
||||
loglevel=normal
|
||||
device=auto
|
||||
logtelegrams=false
|
||||
meterfiles=/var/log/wmbusmeters/meter_readings
|
||||
logfile=/var/log/wmbusmeters/wmbusmeters.log
|
||||
shell=/usr/bin/mosquitto_pub -h localhost -t wmbusmeters -m "$METER_JSON"
|
||||
.fi
|
||||
|
||||
.TP
|
||||
An example wmbusmeters.d file:
|
||||
|
||||
.nf
|
||||
name=MyTapWater
|
||||
type=multical21
|
||||
id=12345678
|
||||
key=001122334455667788AABBCCDDEEFF
|
||||
|
||||
.SH AUTHOR
|
||||
Written by Fredrik Öhrström.
|
||||
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2017-2019 Fredrik Öhrström.
|
||||
.br
|
||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
|
||||
.br
|
||||
This is free software: you are free to change and redistribute it.
|
||||
.br
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
Ładowanie…
Reference in New Issue