2018-04-01 06:53:37 +00:00
|
|
|
/*
|
2019-02-23 17:30:16 +00:00
|
|
|
Copyright (C) 2017-2019 Fredrik Öhrström
|
2018-04-01 06:53:37 +00:00
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2017-08-31 08:58:39 +00:00
|
|
|
|
|
|
|
#include"cmdline.h"
|
2019-02-23 12:41:17 +00:00
|
|
|
#include"config.h"
|
2017-08-31 08:58:39 +00:00
|
|
|
#include"meters.h"
|
2017-09-02 21:26:57 +00:00
|
|
|
#include"printer.h"
|
2017-08-09 10:00:11 +00:00
|
|
|
#include"serial.h"
|
2017-08-31 08:58:39 +00:00
|
|
|
#include"util.h"
|
2019-04-15 19:17:15 +00:00
|
|
|
#include"version.h"
|
2017-08-09 10:00:11 +00:00
|
|
|
#include"wmbus.h"
|
|
|
|
|
|
|
|
#include<string.h>
|
|
|
|
|
2019-02-23 12:41:17 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <fcntl.h>
|
2019-02-23 20:36:00 +00:00
|
|
|
#include <sys/errno.h>
|
2019-02-23 12:41:17 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <syslog.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2017-08-09 10:00:11 +00:00
|
|
|
using namespace std;
|
2017-08-30 12:10:23 +00:00
|
|
|
|
2019-03-05 20:19:05 +00:00
|
|
|
void oneshotCheck(Configuration *cmdline, SerialCommunicationManager *manager, Telegram *t, Meter *meter, vector<unique_ptr<Meter>> &meters);
|
2019-06-11 16:49:26 +00:00
|
|
|
bool startUsingCommandline(Configuration *cmdline);
|
2019-02-24 08:58:31 +00:00
|
|
|
void startUsingConfigFiles(string root, bool is_daemon);
|
|
|
|
void startDaemon(string pid_file); // Will use config files.
|
2017-08-31 08:58:39 +00:00
|
|
|
|
2017-08-09 10:00:11 +00:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
2018-12-28 17:35:32 +00:00
|
|
|
auto cmdline = parseCommandLine(argc, argv);
|
2018-02-28 21:14:16 +00:00
|
|
|
|
2019-04-15 19:17:15 +00:00
|
|
|
if (cmdline->version) {
|
|
|
|
printf("wmbusmeters: " VERSION "\n");
|
|
|
|
printf(COMMIT "\n");
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
if (cmdline->license) {
|
|
|
|
const char * license = R"LICENSE(
|
|
|
|
Copyright (C) 2017-2019 Fredrik Öhrström
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
You can download the source here: https://github.com/weetmuts/wmbusmeters
|
|
|
|
But you can also request the source from the person/company that
|
|
|
|
provided you with this binary. Read the full license for all details.
|
|
|
|
|
|
|
|
)LICENSE";
|
|
|
|
puts(license);
|
|
|
|
exit(0);
|
|
|
|
}
|
2017-09-02 10:17:54 +00:00
|
|
|
if (cmdline->need_help) {
|
2019-04-15 19:17:15 +00:00
|
|
|
printf("wmbusmeters version: " VERSION "\n");
|
2019-02-26 21:19:16 +00:00
|
|
|
const char *msg = R"MANUAL(
|
2019-10-20 19:46:48 +00:00
|
|
|
Usage: wmbusmeters {options} <device>{:suffix} ( [meter_name] [meter_type]{:<modes>} [meter_id] [meter_key] )*
|
2019-02-26 21:19:16 +00:00
|
|
|
|
|
|
|
As <options> you can use:
|
|
|
|
|
2019-06-06 16:16:24 +00:00
|
|
|
--addconversions=<unit>+ add conversion to these units to json and meter env variables (GJ)
|
2019-02-26 21:19:16 +00:00
|
|
|
--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
|
2019-10-20 17:19:17 +00:00
|
|
|
--json_xxx=yyy always add "xxx"="yyy" to the json output and add shell env METER_xxx=yyy
|
2019-06-06 15:28:20 +00:00
|
|
|
--listento=<mode> tell the wmbus dongle to listen to this single link mode where mode can be
|
|
|
|
c1,t1,s1,s1m,n1a,n1b,n1c,n1d,n1e,n1f
|
|
|
|
--listento=c1,t1,s1 tell the wmbus dongle to listen to these link modes
|
|
|
|
different dongles support different combinations of modes
|
|
|
|
--c1 --t1 --s1 --s1m ... another way to set the link mode for the dongle
|
2019-02-26 21:19:16 +00:00
|
|
|
--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
|
2019-06-20 12:28:52 +00:00
|
|
|
--meterfilesnaming=(name|id|name-id) the meter file is the meter's: name, id or name-id
|
2019-02-26 21:19:16 +00:00
|
|
|
--oneshot wait for an update from each meter, then quit
|
2019-10-20 19:46:48 +00:00
|
|
|
--reopenafter=<time> close/reopen dongle connection repeatedly every <time> seconds, eg 60s, 60m, 24h
|
2019-02-26 21:19:16 +00:00
|
|
|
--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
|
|
|
|
|
2019-10-20 19:46:48 +00:00
|
|
|
For the <device> you can add a suffix: /dev/ttyUSB0:amb8465 to
|
|
|
|
specify which wmbus dongle is connected to that device.
|
|
|
|
Supported wmbus dongles are: IMST 871a (i, Amber 8465, RFM-RX2 and
|
|
|
|
|
|
|
|
If you specify a baudrate as a suffix: /dev/ttyUSB0:38400 then wmbusmeters will
|
|
|
|
simple listen to that serial port with that baudrate and expect raw
|
|
|
|
wmbus telegrams.
|
2019-02-26 21:19:16 +00:00
|
|
|
|
2019-10-20 19:46:48 +00:00
|
|
|
As a <device> you can also use: auto which will look for the
|
|
|
|
links /dev/im87a,/dev/amb8475,/dev/rfmrx2 and /dev/rtlsdr (the links are
|
|
|
|
automatically generated by udev if you have run the install scripts.)
|
|
|
|
and start wmbusmeters with the proper tty device or rtlwmbus background process.
|
2019-02-26 21:19:16 +00:00
|
|
|
|
2019-04-03 15:31:51 +00:00
|
|
|
As a <device> you can also use: rtlwmbus
|
2019-10-20 19:46:48 +00:00
|
|
|
to spawn the background process: "rtl_sdr -f 868.95M -s 1600000 - | rtl_wmbus"
|
2019-04-03 15:31:51 +00:00
|
|
|
You can also use: rtlwmbus:868.9M to use this fq instead. Fq tuning can sometimes
|
2019-10-20 19:46:48 +00:00
|
|
|
be necessary. Or you can specify the entire background process command line: "rtlwmbus:<commandline>"
|
2019-02-26 21:19:16 +00:00
|
|
|
|
|
|
|
As meter quadruples you specify:
|
|
|
|
<meter_name> a mnemonic for this particular meter
|
|
|
|
<meter_type> one of the supported meters
|
2019-10-20 19:46:48 +00:00
|
|
|
(can be suffixed with :<mode> to specify which mode you expect the meter to use when transmitting)
|
2019-02-26 21:19:16 +00:00
|
|
|
<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)
|
2019-10-20 19:46:48 +00:00
|
|
|
Apator at-wmbus-16-2 (apator162) (non-standard protocol)
|
|
|
|
Water meter Techem MK Radio 3 (mkradio3) (non-standard protocol)
|
2019-02-26 21:19:16 +00:00
|
|
|
|
2019-05-22 18:06:05 +00:00
|
|
|
Supported heat cost allocators:
|
2019-03-01 14:51:54 +00:00
|
|
|
Qundis Q caloric (qcaloric)
|
2019-10-20 19:46:48 +00:00
|
|
|
Innotas EurisII (eurisii)
|
2019-03-01 14:51:54 +00:00
|
|
|
|
2019-10-20 19:46:48 +00:00
|
|
|
Supported heat meter:
|
|
|
|
Heat meter Techem Vario 4 (vario451) (non-standard protocol)
|
|
|
|
|
|
|
|
Supported room sensors:
|
|
|
|
Lansen Thermometer/Hygrometer (lansenth)
|
|
|
|
Bmeters RFM-AMB Thermometer/Hygrometer (rfmamb)
|
|
|
|
|
|
|
|
Supported electricity meters:
|
|
|
|
Tauron Amiplus (amiplus) (includes vendor apator and echelon)
|
2019-05-04 06:52:25 +00:00
|
|
|
|
2019-02-26 21:19:16 +00:00
|
|
|
Work in progress:
|
|
|
|
Heat meter Kamstrup Multical 302 (multical302)
|
2019-10-20 19:46:48 +00:00
|
|
|
Electricity meter Kamstrup Omnipower (omnipower)
|
2019-02-26 21:19:16 +00:00
|
|
|
)MANUAL";
|
|
|
|
puts(msg);
|
2017-08-30 12:10:23 +00:00
|
|
|
}
|
2019-02-23 17:30:16 +00:00
|
|
|
else
|
2019-02-23 12:41:17 +00:00
|
|
|
if (cmdline->daemon) {
|
2019-02-24 08:58:31 +00:00
|
|
|
startDaemon(cmdline->pid_file);
|
2019-02-23 12:41:17 +00:00
|
|
|
exit(0);
|
|
|
|
}
|
2019-02-23 17:30:16 +00:00
|
|
|
else
|
2019-02-23 12:41:17 +00:00
|
|
|
if (cmdline->useconfig) {
|
2019-02-26 08:33:10 +00:00
|
|
|
startUsingConfigFiles(cmdline->config_root, false);
|
2019-02-23 12:41:17 +00:00
|
|
|
exit(0);
|
|
|
|
}
|
2019-02-23 17:30:16 +00:00
|
|
|
else {
|
|
|
|
// We want the data visible in the log file asap!
|
|
|
|
setbuf(stdout, NULL);
|
|
|
|
startUsingCommandline(cmdline.get());
|
|
|
|
}
|
2019-02-23 12:41:17 +00:00
|
|
|
}
|
|
|
|
|
2019-06-11 16:49:26 +00:00
|
|
|
bool startUsingCommandline(Configuration *config)
|
2019-02-23 12:41:17 +00:00
|
|
|
{
|
2019-06-11 16:49:26 +00:00
|
|
|
if (config->use_logfile)
|
|
|
|
{
|
2019-02-26 22:40:44 +00:00
|
|
|
verbose("(wmbusmeters) using log file %s\n", config->logfile.c_str());
|
|
|
|
bool ok = enableLogfile(config->logfile, config->daemon);
|
|
|
|
if (!ok) {
|
|
|
|
if (config->daemon) {
|
|
|
|
warning("Could not open log file, will use syslog instead.\n");
|
|
|
|
} else {
|
|
|
|
error("Could not open log file.\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-06-11 16:49:26 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
disableLogfile();
|
|
|
|
}
|
2019-02-26 22:40:44 +00:00
|
|
|
|
2019-02-24 15:51:18 +00:00
|
|
|
warningSilenced(config->silence);
|
|
|
|
verboseEnabled(config->verbose);
|
|
|
|
logTelegramsEnabled(config->logtelegrams);
|
|
|
|
debugEnabled(config->debug);
|
2018-02-28 21:14:16 +00:00
|
|
|
|
2019-04-15 19:17:15 +00:00
|
|
|
debug("(wmbusmeters) version: " VERSION "\n");
|
2019-02-28 15:53:09 +00:00
|
|
|
|
2019-02-24 15:51:18 +00:00
|
|
|
if (config->exitafter != 0) {
|
|
|
|
verbose("(config) wmbusmeters will exit after %d seconds\n", config->exitafter);
|
2018-03-05 14:12:58 +00:00
|
|
|
}
|
|
|
|
|
2019-10-16 17:56:59 +00:00
|
|
|
if (config->reopenafter != 0) {
|
|
|
|
verbose("(config) wmbusmeters close/open the wmbus dongle fd after every %d seconds\n", config->reopenafter);
|
|
|
|
}
|
|
|
|
|
2019-02-24 15:51:18 +00:00
|
|
|
if (config->meterfiles) {
|
|
|
|
verbose("(config) store meter files in: \"%s\"\n", config->meterfiles_dir.c_str());
|
2018-03-05 14:12:58 +00:00
|
|
|
}
|
2019-02-25 21:03:20 +00:00
|
|
|
verbose("(config) using device: %s\n", config->device.c_str());
|
|
|
|
if (config->device_extra.length() > 0) {
|
|
|
|
verbose("(config) with: %s\n", config->device_extra.c_str());
|
|
|
|
}
|
2019-02-24 15:51:18 +00:00
|
|
|
verbose("(config) number of meters: %d\n", config->meters.size());
|
2018-03-05 14:12:58 +00:00
|
|
|
|
2019-10-16 17:56:59 +00:00
|
|
|
auto manager = createSerialCommunicationManager(config->exitafter, config->reopenafter);
|
2018-12-28 17:35:32 +00:00
|
|
|
onExit(call(manager.get(),stop));
|
2017-08-09 10:00:11 +00:00
|
|
|
|
2019-10-15 12:32:32 +00:00
|
|
|
auto type_and_device = detectMBusDevice(config->device, config->device_extra, manager.get());
|
2018-02-28 21:14:16 +00:00
|
|
|
|
2019-10-20 18:39:12 +00:00
|
|
|
unique_ptr<WMBus> wmbus;
|
|
|
|
|
2018-02-28 21:14:16 +00:00
|
|
|
switch (type_and_device.first) {
|
|
|
|
case DEVICE_IM871A:
|
|
|
|
verbose("(im871a) detected on %s\n", type_and_device.second.c_str());
|
2018-12-28 17:35:32 +00:00
|
|
|
wmbus = openIM871A(type_and_device.second, manager.get());
|
2018-02-28 21:14:16 +00:00
|
|
|
break;
|
|
|
|
case DEVICE_AMB8465:
|
|
|
|
verbose("(amb8465) detected on %s\n", type_and_device.second.c_str());
|
2018-12-28 17:35:32 +00:00
|
|
|
wmbus = openAMB8465(type_and_device.second, manager.get());
|
2018-02-28 21:14:16 +00:00
|
|
|
break;
|
2018-03-05 10:29:25 +00:00
|
|
|
case DEVICE_SIMULATOR:
|
|
|
|
verbose("(simulator) found %s\n", type_and_device.second.c_str());
|
2018-12-28 17:35:32 +00:00
|
|
|
wmbus = openSimulator(type_and_device.second, manager.get());
|
2018-03-05 10:29:25 +00:00
|
|
|
break;
|
2019-10-15 12:32:32 +00:00
|
|
|
case DEVICE_RAWTTY:
|
|
|
|
verbose("(rawtty) found %s\n", type_and_device.second.c_str());
|
|
|
|
wmbus = openRawTTY(type_and_device.second, atoi(config->device_extra.c_str()), manager.get());
|
|
|
|
break;
|
2019-10-20 18:39:12 +00:00
|
|
|
case DEVICE_RFMRX2:
|
|
|
|
verbose("(rfmrx2) detected on %s\n", type_and_device.second.c_str());
|
|
|
|
if (config->reopenafter == 0)
|
|
|
|
{
|
|
|
|
manager->setReopenAfter(600); // Close and reopen the fd, because of some bug in the device.
|
|
|
|
}
|
|
|
|
wmbus = openRawTTY(type_and_device.second, 38400, manager.get());
|
|
|
|
break;
|
2019-02-25 21:03:20 +00:00
|
|
|
case DEVICE_RTLWMBUS:
|
|
|
|
{
|
|
|
|
string command = config->device_extra;
|
2019-02-26 21:47:12 +00:00
|
|
|
string freq = "868.95M";
|
|
|
|
string prefix = "";
|
|
|
|
if (isFrequency(command)) {
|
|
|
|
freq = command;
|
|
|
|
command = "";
|
|
|
|
}
|
|
|
|
if (config->daemon) {
|
|
|
|
prefix = "/usr/bin/";
|
|
|
|
}
|
2019-02-25 21:03:20 +00:00
|
|
|
if (command == "") {
|
2019-08-13 08:19:59 +00:00
|
|
|
command = prefix+"rtl_sdr -f "+freq+" -s 1.6e6 - | "+prefix+"rtl_wmbus";
|
2019-02-25 21:03:20 +00:00
|
|
|
}
|
2019-02-26 21:47:12 +00:00
|
|
|
verbose("(rtlwmbus) using command: %s\n", command.c_str());
|
2019-04-03 15:31:51 +00:00
|
|
|
|
|
|
|
wmbus = openRTLWMBUS(command, manager.get(),
|
|
|
|
[command](){
|
|
|
|
warning("(rtlwmbus) child process exited! "
|
|
|
|
"Command was: \"%s\"\n", command.c_str());
|
|
|
|
});
|
2019-02-25 21:03:20 +00:00
|
|
|
break;
|
|
|
|
}
|
2018-02-28 21:14:16 +00:00
|
|
|
case DEVICE_UNKNOWN:
|
2019-02-24 08:58:31 +00:00
|
|
|
warning("No wmbus device found! Exiting!\n");
|
2019-02-24 15:51:18 +00:00
|
|
|
if (config->daemon) {
|
2019-02-24 08:58:31 +00:00
|
|
|
// If starting as a daemon, wait a bit so that systemd have time to catch up.
|
|
|
|
sleep(1);
|
|
|
|
}
|
2018-02-28 21:14:16 +00:00
|
|
|
exit(1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-06-06 15:28:20 +00:00
|
|
|
LinkModeCalculationResult lmcr = calculateLinkModes(config, wmbus.get());
|
|
|
|
if (lmcr.type != LinkModeCalculationResultType::Success) {
|
|
|
|
error("%s\n", lmcr.msg.c_str());
|
2018-11-01 16:17:23 +00:00
|
|
|
}
|
|
|
|
|
2019-06-06 15:28:20 +00:00
|
|
|
wmbus->setLinkModes(config->listen_to_link_modes);
|
|
|
|
string using_link_modes = wmbus->getLinkModes().hr();
|
|
|
|
|
|
|
|
verbose("(config) listen to link modes: %s\n", using_link_modes.c_str());
|
2017-09-02 21:26:57 +00:00
|
|
|
|
2019-02-24 15:51:18 +00:00
|
|
|
auto output = unique_ptr<Printer>(new Printer(config->json, config->fields,
|
2019-02-24 16:31:32 +00:00
|
|
|
config->separator, config->meterfiles, config->meterfiles_dir,
|
2019-02-26 22:40:44 +00:00
|
|
|
config->use_logfile, config->logfile,
|
2019-02-24 16:31:32 +00:00
|
|
|
config->shells,
|
2019-06-20 12:28:52 +00:00
|
|
|
config->meterfiles_action == MeterFileType::Overwrite,
|
|
|
|
config->meterfiles_naming));
|
2018-12-28 17:35:32 +00:00
|
|
|
vector<unique_ptr<Meter>> meters;
|
2018-02-28 21:14:16 +00:00
|
|
|
|
2019-02-24 15:51:18 +00:00
|
|
|
if (config->meters.size() > 0) {
|
|
|
|
for (auto &m : config->meters) {
|
2018-11-25 11:33:14 +00:00
|
|
|
const char *keymsg = (m.key[0] == 0) ? "not-encrypted" : "encrypted";
|
2018-03-05 10:29:25 +00:00
|
|
|
switch (toMeterType(m.type)) {
|
2019-05-04 08:52:18 +00:00
|
|
|
#define X(mname,link,info,type,cname) \
|
|
|
|
case MeterType::type: \
|
2019-05-21 12:19:54 +00:00
|
|
|
meters.push_back(create##cname(wmbus.get(), m)); \
|
2019-05-04 08:52:18 +00:00
|
|
|
verbose("(wmbusmeters) configured \"%s\" \"" #mname "\" \"%s\" %s\n", \
|
|
|
|
m.name.c_str(), m.id.c_str(), keymsg); \
|
2019-05-04 11:55:52 +00:00
|
|
|
meters.back()->addConversions(config->conversions); \
|
2018-03-05 10:29:25 +00:00
|
|
|
break;
|
2019-05-04 08:52:18 +00:00
|
|
|
LIST_OF_METERS
|
|
|
|
#undef X
|
|
|
|
case MeterType::UNKNOWN:
|
2019-02-23 13:01:04 +00:00
|
|
|
error("No such meter type \"%s\"\n", m.type.c_str());
|
2018-03-05 10:29:25 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-05-04 20:01:38 +00:00
|
|
|
|
2019-02-24 15:51:18 +00:00
|
|
|
if (config->list_shell_envs) {
|
2018-11-02 12:50:12 +00:00
|
|
|
string ignore1, ignore2, ignore3;
|
|
|
|
vector<string> envs;
|
2019-03-05 20:19:05 +00:00
|
|
|
Telegram t;
|
|
|
|
meters.back()->printMeter(&t,
|
2019-03-05 17:38:54 +00:00
|
|
|
&ignore1,
|
2019-02-24 15:51:18 +00:00
|
|
|
&ignore2, config->separator,
|
2018-12-28 17:35:32 +00:00
|
|
|
&ignore3,
|
2019-10-20 17:19:17 +00:00
|
|
|
&envs,
|
|
|
|
&config->jsons);
|
2019-02-23 12:41:17 +00:00
|
|
|
printf("Environment variables provided to shell for meter %s:\n", m.type.c_str());
|
2018-11-02 12:50:12 +00:00
|
|
|
for (auto &e : envs) {
|
|
|
|
int p = e.find('=');
|
|
|
|
string key = e.substr(0,p);
|
|
|
|
printf("%s\n", key.c_str());
|
|
|
|
}
|
|
|
|
exit(0);
|
|
|
|
}
|
2019-10-20 17:19:17 +00:00
|
|
|
meters.back()->onUpdate([&](Telegram*t,Meter* meter) { output->print(t,meter,&config->jsons); });
|
2019-03-05 20:19:05 +00:00
|
|
|
meters.back()->onUpdate([&](Telegram*t, Meter* meter) { oneshotCheck(config, manager.get(), t, meter, meters); });
|
2017-08-30 12:10:23 +00:00
|
|
|
}
|
|
|
|
} else {
|
2019-02-26 22:40:44 +00:00
|
|
|
notice("No meters configured. Printing id:s of all telegrams heard!\n\n");
|
2017-08-30 12:10:23 +00:00
|
|
|
|
2017-09-02 21:26:57 +00:00
|
|
|
wmbus->onTelegram([](Telegram *t){t->print();});
|
2017-08-30 12:10:23 +00:00
|
|
|
}
|
|
|
|
|
2018-03-05 10:29:25 +00:00
|
|
|
if (type_and_device.first == DEVICE_SIMULATOR) {
|
|
|
|
wmbus->simulate();
|
|
|
|
}
|
|
|
|
|
2019-02-26 22:40:44 +00:00
|
|
|
if (config->daemon) {
|
2019-02-24 15:51:18 +00:00
|
|
|
notice("(wmbusmeters) waiting for telegrams\n");
|
|
|
|
}
|
2019-02-26 22:40:44 +00:00
|
|
|
|
2018-02-28 21:14:16 +00:00
|
|
|
manager->waitForStop();
|
2019-02-24 15:51:18 +00:00
|
|
|
|
2019-02-26 22:40:44 +00:00
|
|
|
if (config->daemon) {
|
2019-02-24 15:51:18 +00:00
|
|
|
notice("(wmbusmeters) shutting down\n");
|
|
|
|
}
|
2019-06-11 16:49:26 +00:00
|
|
|
|
|
|
|
restoreSignalHandlers();
|
|
|
|
return gotHupped();
|
2017-08-09 10:00:11 +00:00
|
|
|
}
|
2017-09-02 21:26:57 +00:00
|
|
|
|
2019-03-05 20:19:05 +00:00
|
|
|
void oneshotCheck(Configuration *config, SerialCommunicationManager *manager, Telegram *t, Meter *meter, vector<unique_ptr<Meter>> &meters)
|
2017-09-02 21:26:57 +00:00
|
|
|
{
|
2019-02-24 15:51:18 +00:00
|
|
|
if (!config->oneshot) return;
|
2018-02-28 21:14:16 +00:00
|
|
|
|
2018-12-28 17:35:32 +00:00
|
|
|
for (auto &m : meters) {
|
|
|
|
if (m->numUpdates() == 0) return;
|
2017-09-02 21:26:57 +00:00
|
|
|
}
|
|
|
|
// All meters have received at least one update! Stop!
|
2019-03-05 20:19:05 +00:00
|
|
|
verbose("(main) all meters have received at least one update, stopping.\n");
|
2017-09-02 21:26:57 +00:00
|
|
|
manager->stop();
|
|
|
|
}
|
2019-02-23 12:41:17 +00:00
|
|
|
|
2019-02-24 08:58:31 +00:00
|
|
|
void writePid(string pid_file, int pid)
|
2019-02-23 12:41:17 +00:00
|
|
|
{
|
2019-02-24 08:58:31 +00:00
|
|
|
FILE *pidf = fopen(pid_file.c_str(), "w");
|
|
|
|
if (!pidf) {
|
|
|
|
error("Could not open pid file \"%s\" for writing!\n", pid_file.c_str());
|
|
|
|
}
|
|
|
|
if (pid > 0) {
|
|
|
|
int n = fprintf(pidf, "%d\n", pid);
|
|
|
|
if (!n) {
|
|
|
|
error("Could not write pid (%d) to file \"%s\"!\n", pid, pid_file.c_str());
|
|
|
|
}
|
2019-02-24 15:51:18 +00:00
|
|
|
notice("(wmbusmeters) started %s\n", pid_file.c_str());
|
2019-02-24 08:58:31 +00:00
|
|
|
}
|
|
|
|
fclose(pidf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void startDaemon(string pid_file)
|
|
|
|
{
|
|
|
|
setlogmask(LOG_UPTO (LOG_INFO));
|
|
|
|
openlog("wmbusmetersd", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
|
|
|
|
|
|
|
|
enableSyslog();
|
|
|
|
|
|
|
|
// Pre check that the pid file can be writte to.
|
|
|
|
// Exit before fork, if it fails.
|
|
|
|
writePid(pid_file, 0);
|
|
|
|
|
2019-02-23 12:41:17 +00:00
|
|
|
pid_t pid = fork();
|
|
|
|
if (pid < 0)
|
|
|
|
{
|
|
|
|
error("Could not fork.\n");
|
|
|
|
}
|
|
|
|
if (pid > 0)
|
|
|
|
{
|
2019-02-24 08:58:31 +00:00
|
|
|
// Success! The parent stores the pid and exits.
|
|
|
|
writePid(pid_file, pid);
|
2019-02-23 12:41:17 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Change the file mode mask
|
|
|
|
umask(0);
|
|
|
|
|
|
|
|
// Create a new SID for the daemon
|
|
|
|
pid_t sid = setsid();
|
|
|
|
if (sid < 0) {
|
|
|
|
// log
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((chdir("/")) < 0) {
|
|
|
|
error("Could not change to root as current working directory.");
|
|
|
|
}
|
|
|
|
|
|
|
|
close(STDIN_FILENO);
|
|
|
|
close(STDOUT_FILENO);
|
|
|
|
close(STDERR_FILENO);
|
|
|
|
|
2019-08-13 18:46:50 +00:00
|
|
|
if (open("/dev/null", O_RDONLY) == -1) {
|
|
|
|
error("Failed to reopen stdin while daemonising (errno=%d)",errno);
|
|
|
|
}
|
|
|
|
if (open("/dev/null", O_WRONLY) == -1) {
|
|
|
|
error("Failed to reopen stdout while daemonising (errno=%d)",errno);
|
|
|
|
}
|
|
|
|
if (open("/dev/null", O_RDWR) == -1) {
|
|
|
|
error("Failed to reopen stderr while daemonising (errno=%d)",errno);
|
|
|
|
}
|
2019-02-24 08:58:31 +00:00
|
|
|
startUsingConfigFiles("", true);
|
2019-02-23 12:41:17 +00:00
|
|
|
}
|
|
|
|
|
2019-02-24 08:58:31 +00:00
|
|
|
void startUsingConfigFiles(string root, bool is_daemon)
|
2019-02-23 12:41:17 +00:00
|
|
|
{
|
2019-06-11 16:49:26 +00:00
|
|
|
bool restart = false;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
unique_ptr<Configuration> config = loadConfiguration(root);
|
|
|
|
config->daemon = is_daemon;
|
|
|
|
restart = startUsingCommandline(config.get());
|
|
|
|
if (restart)
|
|
|
|
{
|
|
|
|
notice("(wmbusmeters) HUP received, restarting and reloading config files.\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (restart);
|
2019-02-23 12:41:17 +00:00
|
|
|
}
|