kopia lustrzana https://github.com/weetmuts/wmbusmeters
Added donotprobe=<device> and fixed so that it does not probe if a device is specified or rtlwmbus is specified.
rodzic
171887e2f9
commit
5e273ddb7e
8
CHANGES
8
CHANGES
|
@ -1,4 +1,12 @@
|
|||
|
||||
Added --donotprobe=/dev/ttyUSB0
|
||||
|
||||
(Also made sure that specifying only rtlwmbus/rtl433 will not probe
|
||||
serial ttys. Specifying fully specified devices like
|
||||
/dev/ttyUSB0:im871a:c1 will also not probe the other serial ttys.
|
||||
Only specifying auto or a generic device type im871a that requires a
|
||||
serial tty, will probe the serial devices, exluding donotprobe ones.)
|
||||
|
||||
Added support for the sontex868 heat cost allocator.
|
||||
|
||||
Version 1.0.1: 2020-10-26
|
||||
|
|
20
README.md
20
README.md
|
@ -49,11 +49,24 @@ You can trigger a reload of the config files with `sudo killall -HUP wmbusmeters
|
|||
(Note! make install only works for GNU/Linux. For MacOSX try to start
|
||||
`wmbusmetersd /tmp/thepidfile` from a script instead.)
|
||||
|
||||
Check the config file /etc/wmbusmeters.conf and edit the device to
|
||||
point to your dongle or use auto
|
||||
Check the config file /etc/wmbusmeters.conf and edit the device. For example:
|
||||
`auto:c1` or `im871a:c1`
|
||||
|
||||
Adding a device like auto or im871a will trigger an automatic probe of all serial ttys.
|
||||
|
||||
If you specify a full device path like `/dev/ttyUSB0:im871a:c1` or `rtlwmbus` or `rtl433`
|
||||
then it will not probe the serial devices. If you must be really sure that it will not probe something
|
||||
you can add `donotprobe=/dev/ttyUSB0` or `donotprobe=all`.
|
||||
|
||||
You can specify combinations like: `device=rc1180:t1` `device=auto:c1`
|
||||
to set the rc1180 dongle to t1 but any other auto-detected dongle to c1.
|
||||
|
||||
```
|
||||
loglevel=normal
|
||||
device=im871a:c1
|
||||
# Search for a wmbus device and set it to c1.
|
||||
device=auto:c1
|
||||
# But do not probe this serial tty.
|
||||
donotprobe=/dev/ttyACM2
|
||||
logtelegrams=false
|
||||
format=json
|
||||
meterfiles=/var/log/wmbusmeters/meter_readings
|
||||
|
@ -147,6 +160,7 @@ As <options> you can use:
|
|||
--alarmshell=<cmdline> invokes cmdline when an alarm triggers
|
||||
--alarmtimeout=<time> Expect a telegram to arrive within <time> seconds, eg 60s, 60m, 24h during expected activity.
|
||||
--debug for a lot of information
|
||||
--donotprobe=<tty> do not auto-probe this tty. Use multiple times for several ttys or specify "all" for all ttys.
|
||||
--exitafter=<time> exit program after time, eg 20h, 10m 5s
|
||||
--format=<hr/json/fields> for human readable, json or semicolon separated fields
|
||||
--json_xxx=yyy always add "xxx"="yyy" to the json output and add shell env METER_xxx=yyy
|
||||
|
|
|
@ -107,27 +107,37 @@ shared_ptr<Configuration> parseCommandLine(int argc, char **argv) {
|
|||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(argv[i], "--listento=", 11)) {
|
||||
if (!strncmp(argv[i], "--donotprobe=", 13))
|
||||
{
|
||||
string df = string(argv[i]+13);
|
||||
debug("(cmdline) do not probe \"%s\"\n", df.c_str());
|
||||
c->do_not_probe_ttys.insert(df);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(argv[i], "--listento=", 11))
|
||||
{
|
||||
LinkModeSet lms = parseLinkModes(argv[i]+11);
|
||||
if (lms.bits() == 0) {
|
||||
error("Unknown link mode \"%s\"!\n", argv[i]+11);
|
||||
if (lms.empty())
|
||||
{
|
||||
error("Unknown default link mode \"%s\"!\n", argv[i]+11);
|
||||
}
|
||||
if (c->linkmodes_configured) {
|
||||
error("You have already specified a link mode!\n");
|
||||
if (!c->default_device_linkmodes.empty()) {
|
||||
error("You have already specified a default link mode!\n");
|
||||
}
|
||||
c->linkmodes = lms;
|
||||
c->linkmodes_configured = true;
|
||||
c->default_device_linkmodes = lms;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
LinkMode lm = isLinkModeOption(argv[i]);
|
||||
if (lm != LinkMode::UNKNOWN) {
|
||||
if (c->linkmodes_configured) {
|
||||
error("You have already specified a link mode!\n");
|
||||
if (!c->default_device_linkmodes.empty())
|
||||
{
|
||||
error("You have already specified a default link mode!\n");
|
||||
}
|
||||
c->linkmodes.addLinkMode(lm);
|
||||
c->linkmodes_configured = true;
|
||||
// Add to the empty set.
|
||||
c->default_device_linkmodes.addLinkMode(lm);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
@ -476,7 +486,7 @@ shared_ptr<Configuration> parseCommandLine(int argc, char **argv) {
|
|||
}
|
||||
|
||||
if (c->supplied_wmbus_devices.size() == 0 &&
|
||||
c->use_auto_detect == false &&
|
||||
c->use_auto_device_detect == false &&
|
||||
!c->list_shell_envs &&
|
||||
!c->list_fields &&
|
||||
!c->list_meters)
|
||||
|
|
107
src/config.cc
107
src/config.cc
|
@ -229,31 +229,26 @@ bool handleDevice(Configuration *c, string devicefile)
|
|||
// Number the devices
|
||||
specified_device.index = c->supplied_wmbus_devices.size();
|
||||
|
||||
if (specified_device.linkmodes != "")
|
||||
{
|
||||
// Prevent an early warning in start
|
||||
// since we at least have one configured linkmode.
|
||||
c->linkmodes_configured = true;
|
||||
c->linkmodes.unionLinkModeSet(parseLinkModes(specified_device.linkmodes));
|
||||
}
|
||||
else
|
||||
if (specified_device.linkmodes.empty())
|
||||
{
|
||||
// No linkmode set, but if simulation, stdin and file,
|
||||
// then assume that it will produce telegrams on all linkmodes.
|
||||
if (specified_device.is_simulation || specified_device.is_stdin || specified_device.is_file)
|
||||
{
|
||||
c->linkmodes_configured = true;
|
||||
c->linkmodes.unionLinkModeSet(LinkModeBits::Any_bit);
|
||||
// Essentially link mode calculations are now irrelevant.
|
||||
specified_device.linkmodes.addLinkMode(LinkMode::Any);
|
||||
}
|
||||
|
||||
if (specified_device.type == "rtlwmbus")
|
||||
else
|
||||
if (specified_device.type == WMBusDeviceType::DEVICE_RTLWMBUS ||
|
||||
specified_device.type == WMBusDeviceType::DEVICE_RTL433)
|
||||
{
|
||||
c->linkmodes_configured = true;
|
||||
c->linkmodes.addLinkMode(LinkMode::C1);
|
||||
c->linkmodes.addLinkMode(LinkMode::T1);
|
||||
c->all_device_linkmodes_specified.addLinkMode(LinkMode::C1);
|
||||
c->all_device_linkmodes_specified.addLinkMode(LinkMode::T1);
|
||||
}
|
||||
}
|
||||
|
||||
c->all_device_linkmodes_specified.unionLinkModeSet(specified_device.linkmodes);
|
||||
|
||||
if (specified_device.is_stdin ||
|
||||
specified_device.is_file ||
|
||||
specified_device.is_simulation ||
|
||||
|
@ -263,16 +258,19 @@ bool handleDevice(Configuration *c, string devicefile)
|
|||
{
|
||||
error("You can only specify one stdin or one file or one command!\n");
|
||||
}
|
||||
if (c->use_auto_detect)
|
||||
if (c->use_auto_device_detect)
|
||||
{
|
||||
error("You cannot mix auto with stdin or a file.\n");
|
||||
}
|
||||
if (specified_device.is_simulation) c->simulation_found = true;
|
||||
c->single_device_override = true;
|
||||
}
|
||||
if (specified_device.type == "auto")
|
||||
|
||||
if (specified_device.type == WMBusDeviceType::DEVICE_AUTO)
|
||||
{
|
||||
c->use_auto_detect = true;
|
||||
c->use_auto_device_detect = true;
|
||||
c->auto_device_linkmodes = specified_device.linkmodes;
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
error("You cannot use auto on macosx. You must specify the device tty or rtlwmbus.\n");
|
||||
#endif
|
||||
|
@ -285,20 +283,25 @@ bool handleDevice(Configuration *c, string devicefile)
|
|||
return ok;
|
||||
}
|
||||
|
||||
bool handleDoNotProbe(Configuration *c, string devicefile)
|
||||
{
|
||||
c->do_not_probe_ttys.insert(devicefile);
|
||||
return true;
|
||||
}
|
||||
|
||||
void handleListenTo(Configuration *c, string mode)
|
||||
{
|
||||
LinkModeSet lms = parseLinkModes(mode.c_str());
|
||||
if (lms.bits() == 0)
|
||||
if (lms.empty())
|
||||
{
|
||||
error("Unknown link mode \"%s\"!\n", mode.c_str());
|
||||
error("Unknown link modes \"%s\"!\n", mode.c_str());
|
||||
}
|
||||
if (c->linkmodes_configured)
|
||||
if (!c->default_device_linkmodes.empty())
|
||||
{
|
||||
error("You have already specified a link mode!\n");
|
||||
error("You have already specified the default link modes!\n");
|
||||
}
|
||||
|
||||
c->linkmodes = lms;
|
||||
c->linkmodes_configured = true;
|
||||
c->default_device_linkmodes = lms;
|
||||
}
|
||||
|
||||
void handleLogtelegrams(Configuration *c, string logtelegrams)
|
||||
|
@ -524,6 +527,7 @@ shared_ptr<Configuration> loadConfiguration(string root, string device_override,
|
|||
else if (p.first == "internaltesting") handleInternalTesting(c, p.second);
|
||||
else if (p.first == "ignoreduplicates") handleIgnoreDuplicateTelegrams(c, p.second);
|
||||
else if (p.first == "device") handleDevice(c, p.second);
|
||||
else if (p.first == "donotprobe") handleDoNotProbe(c, p.second);
|
||||
else if (p.first == "listento") handleListenTo(c, p.second);
|
||||
else if (p.first == "logtelegrams") handleLogtelegrams(c, p.second);
|
||||
else if (p.first == "meterfiles") handleMeterfiles(c, p.second);
|
||||
|
@ -602,45 +606,21 @@ LinkModeCalculationResult calculateLinkModes(Configuration *config, WMBus *wmbus
|
|||
}
|
||||
string metersu = meters_union.hr();
|
||||
debug("(config) all possible link modes that the meters might transmit on: %s\n", metersu.c_str());
|
||||
if (meters_union.bits() == 0)
|
||||
if (meters_union.empty())
|
||||
{
|
||||
if (link_modes_matter && !config->linkmodes_configured)
|
||||
if (link_modes_matter && config->all_device_linkmodes_specified.empty())
|
||||
{
|
||||
string msg;
|
||||
strprintf(msg,"(config) No meters supplied. You must supply which link modes to listen to. Eg. --listento=<modes>");
|
||||
strprintf(msg,"(config) No meters supplied. You must supply which link modes to listen to. 22 Eg. auto:t1");
|
||||
debug("%s\n", msg.c_str());
|
||||
return { LinkModeCalculationResultType::NoMetersMustSupplyModes , msg};
|
||||
}
|
||||
return { LinkModeCalculationResultType::Success, "" };
|
||||
}
|
||||
if (!config->linkmodes_configured)
|
||||
{
|
||||
// A listen_to link mode has not been set explicitly. Pick a listen_to link
|
||||
// mode that is supported by the wmbus dongle and works for the meters.
|
||||
config->linkmodes = wmbus->supportedLinkModes();
|
||||
config->linkmodes.disjunctionLinkModeSet(meters_union);
|
||||
if (!wmbus->canSetLinkModes(config->linkmodes))
|
||||
{
|
||||
// The automatically calculated link modes cannot be set in the dongle.
|
||||
// Ie the dongle needs help....
|
||||
string msg;
|
||||
strprintf(msg,"(config) Automatic deduction of which link mode to listen to failed since the meters might transmit using: %s\n"
|
||||
"(config) But the dongle can only listen to: %s Please supply the exact link mode(s) to listen to, eg: --listento=<mode>\n"
|
||||
"(config) and/or specify the expected transmit modes for the meters, eg: apator162:t1\n"
|
||||
"(config) or use a dongle that can listen to all the required link modes at the same time.",
|
||||
metersu.c_str(), dongle.c_str());
|
||||
|
||||
debug("%s\n", msg.c_str());
|
||||
return { LinkModeCalculationResultType::AutomaticDeductionFailed , msg};
|
||||
}
|
||||
config->linkmodes_configured = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
string listen = config->linkmodes.hr();
|
||||
debug("(config) explicitly listening to: %s\n", listen.c_str());
|
||||
}
|
||||
string all_lms = config->all_device_linkmodes_specified.hr();
|
||||
verbose("(config) all specified link modes: %s\n", all_lms.c_str());
|
||||
|
||||
/*
|
||||
string listen = config->linkmodes.hr();
|
||||
if (!wmbus->canSetLinkModes(config->linkmodes))
|
||||
{
|
||||
|
@ -650,19 +630,28 @@ LinkModeCalculationResult calculateLinkModes(Configuration *config, WMBus *wmbus
|
|||
debug("%s\n", msg.c_str());
|
||||
return { LinkModeCalculationResultType::DongleCannotListenTo , msg};
|
||||
}
|
||||
|
||||
if (!config->linkmodes.hasAll(meters_union))
|
||||
*/
|
||||
/*
|
||||
string listen = config->linkmodes.hr();
|
||||
if (!wmbus->canSetLinkModes(config->linkmodes))
|
||||
{
|
||||
string msg;
|
||||
strprintf(msg, "(config) You have specified to listen to the link modes: %s but the dongle can only listen to: %s",
|
||||
listen.c_str(), dongle.c_str());
|
||||
debug("%s\n", msg.c_str());
|
||||
return { LinkModeCalculationResultType::DongleCannotListenTo , msg};
|
||||
}
|
||||
*/
|
||||
if (!config->all_device_linkmodes_specified.hasAll(meters_union))
|
||||
{
|
||||
string msg;
|
||||
strprintf(msg, "(config) You have specified to listen to the link modes: %s but the meters might transmit on: %s\n"
|
||||
"(config) Therefore you might miss telegrams! Please specify the expected transmit mode for the meters, eg: apator162:t1\n"
|
||||
"(config) Or use a dongle that can listen to all the required link modes at the same time.",
|
||||
listen.c_str(), metersu.c_str());
|
||||
all_lms.c_str(), metersu.c_str());
|
||||
debug("%s\n", msg.c_str());
|
||||
return { LinkModeCalculationResultType::MightMissTelegrams, msg};
|
||||
}
|
||||
|
||||
debug("(config) listen link modes calculated to be: %s\n", listen.c_str());
|
||||
|
||||
return { LinkModeCalculationResultType::Success, "" };
|
||||
}
|
||||
|
|
13
src/config.h
13
src/config.h
|
@ -22,6 +22,7 @@
|
|||
#include"util.h"
|
||||
#include"wmbus.h"
|
||||
#include"meters.h"
|
||||
#include<set>
|
||||
#include<vector>
|
||||
|
||||
using namespace std;
|
||||
|
@ -86,11 +87,17 @@ struct Configuration
|
|||
int exitafter {}; // Seconds to exit.
|
||||
int resetafter {}; // Reset the wmbus devices regularly.
|
||||
std::vector<SpecifiedDevice> supplied_wmbus_devices; // /dev/ttyUSB0, simulation.txt, rtlwmbus, /dev/ttyUSB1:9600
|
||||
bool use_auto_detect {}; // Set to true if auto was supplied as device.
|
||||
bool use_auto_device_detect {}; // Set to true if auto was supplied as device.
|
||||
std::set<std::string> do_not_probe_ttys; // Do not probe these ttys! all = all of them.
|
||||
LinkModeSet auto_device_linkmodes; // The linkmodes specified by auto:c1,t1
|
||||
bool single_device_override {}; // Set to true if there is a stdin/file or simulation device.
|
||||
bool simulation_found {};
|
||||
LinkModeSet linkmodes; // If --c1 or auto:c1 then store c1 here.
|
||||
bool linkmodes_configured {}; // Either auto:c1 or --c1 is specified.
|
||||
LinkModeSet default_device_linkmodes; // Backwards compatible --listento=c1 or --c1 will set the default_linkmodes.
|
||||
// A device without a :t1 suffix, will use this linkmode.
|
||||
// Is empty when not set.
|
||||
LinkModeSet all_device_linkmodes_specified; // A union of all device specified linkmodes.
|
||||
// Eventually not all devices might be found, so a realtime check is done later.
|
||||
LinkModeSet all_meters_linkmodes_specified; // A union of all meters linkmodes.
|
||||
string telegram_reader;
|
||||
// A set of all link modes (union) that the user requests the wmbus dongle to listen to.
|
||||
bool no_init {};
|
||||
|
|
92
src/main.cc
92
src/main.cc
|
@ -58,7 +58,6 @@ void list_meters(Configuration *config);
|
|||
void log_start_information(Configuration *config);
|
||||
void oneshot_check(Configuration *config, Telegram *t, Meter *meter);
|
||||
void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, Detected *detected);
|
||||
void perform_auto_scan_of_devices(Configuration *config);
|
||||
void perform_auto_scan_of_serial_devices(Configuration *config);
|
||||
void perform_auto_scan_of_swradio_devices(Configuration *config);
|
||||
void regular_checkup(Configuration *config);
|
||||
|
@ -325,6 +324,10 @@ shared_ptr<WMBus> create_wmbus_object(Detected *detected, Configuration *config,
|
|||
|
||||
switch (detected->found_type)
|
||||
{
|
||||
case DEVICE_AUTO:
|
||||
assert(0);
|
||||
error("Internal error DEVICE_AUTO should not be used here!\n");
|
||||
break;
|
||||
case DEVICE_IM871A:
|
||||
verbose("(im871a) on %s\n", detected->found_file.c_str());
|
||||
wmbus = openIM871A(detected->found_file, manager, serial_override);
|
||||
|
@ -486,14 +489,24 @@ void detect_and_configure_wmbus_devices(Configuration *config)
|
|||
{
|
||||
check_for_dead_wmbus_devices(config);
|
||||
|
||||
bool must_auto_find = false;
|
||||
bool must_auto_find_ttys = false;
|
||||
bool must_auto_find_rtlsdrs = false;
|
||||
|
||||
// The device=auto has been specified....
|
||||
if (config->use_auto_device_detect)
|
||||
{
|
||||
must_auto_find_ttys = true;
|
||||
must_auto_find_rtlsdrs = true;
|
||||
}
|
||||
|
||||
for (SpecifiedDevice &specified_device : config->supplied_wmbus_devices)
|
||||
{
|
||||
specified_device.handled = false;
|
||||
if (specified_device.file == "" && specified_device.command == "")
|
||||
{
|
||||
// File/tty/command not specified, use auto scan later to find actual device file/tty.
|
||||
must_auto_find = true;
|
||||
must_auto_find_ttys |= usesTTY(specified_device.type);
|
||||
must_auto_find_rtlsdrs |= usesRTLSDR(specified_device.type);
|
||||
continue;
|
||||
}
|
||||
if (specified_device.command != "")
|
||||
|
@ -506,8 +519,7 @@ void detect_and_configure_wmbus_devices(Configuration *config)
|
|||
specified_device.handled = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
Detected detected = detectWMBusDeviceWithCommand(specified_device, serial_manager_);
|
||||
Detected detected = detectWMBusDeviceWithCommand(specified_device, config->default_device_linkmodes, serial_manager_);
|
||||
specified_device.handled = true;
|
||||
open_wmbus_device_and_set_linkmodes(config, "config", &detected);
|
||||
}
|
||||
|
@ -534,7 +546,7 @@ void detect_and_configure_wmbus_devices(Configuration *config)
|
|||
continue;
|
||||
}
|
||||
|
||||
Detected detected = detectWMBusDeviceWithFile(specified_device, serial_manager_);
|
||||
Detected detected = detectWMBusDeviceWithFile(specified_device, config->default_device_linkmodes, serial_manager_);
|
||||
|
||||
if (detected.found_type == DEVICE_UNKNOWN)
|
||||
{
|
||||
|
@ -552,9 +564,14 @@ void detect_and_configure_wmbus_devices(Configuration *config)
|
|||
specified_device.handled = true;
|
||||
}
|
||||
|
||||
if (config->use_auto_detect || must_auto_find)
|
||||
if (must_auto_find_ttys)
|
||||
{
|
||||
perform_auto_scan_of_devices(config);
|
||||
perform_auto_scan_of_serial_devices(config);
|
||||
}
|
||||
|
||||
if (must_auto_find_rtlsdrs)
|
||||
{
|
||||
perform_auto_scan_of_swradio_devices(config);
|
||||
}
|
||||
|
||||
for (shared_ptr<WMBus> &wmbus : wmbus_devices_)
|
||||
|
@ -588,7 +605,7 @@ bool find_specified_device_and_update_detected(Configuration *c, Detected *d)
|
|||
// This will find specified devices like: im871a[12345678]
|
||||
for (SpecifiedDevice & sd : c->supplied_wmbus_devices)
|
||||
{
|
||||
if (sd.file == "" && sd.id != "" && sd.id == d->found_device_id && toWMBusDeviceType(sd.type) == d->found_type)
|
||||
if (sd.file == "" && sd.id != "" && sd.id == d->found_device_id && sd.type == d->found_type)
|
||||
{
|
||||
d->specified_device = sd;
|
||||
debug("(main) found specified device (%s) that matches detected device (%s)\n",
|
||||
|
@ -602,7 +619,7 @@ bool find_specified_device_and_update_detected(Configuration *c, Detected *d)
|
|||
// This will find specified devices like: im871a, rtlwmbus
|
||||
for (SpecifiedDevice & sd : c->supplied_wmbus_devices)
|
||||
{
|
||||
if (sd.file == "" && sd.id == "" && toWMBusDeviceType(sd.type) == d->found_type)
|
||||
if (sd.file == "" && sd.id == "" && sd.type == d->found_type)
|
||||
{
|
||||
d->specified_device = sd;
|
||||
debug("(main) found specified device (%s) that matches detected device (%s)\n",
|
||||
|
@ -621,7 +638,7 @@ void find_specified_device_and_mark_as_handled(Configuration *c, Detected *d)
|
|||
// This will find specified devices like: im871a[12345678]
|
||||
for (SpecifiedDevice & sd : c->supplied_wmbus_devices)
|
||||
{
|
||||
if (sd.file == "" && sd.id != "" && sd.id == d->found_device_id && toWMBusDeviceType(sd.type) == d->found_type)
|
||||
if (sd.file == "" && sd.id != "" && sd.id == d->found_device_id && sd.type == d->found_type)
|
||||
{
|
||||
sd.handled = true;
|
||||
}
|
||||
|
@ -631,7 +648,7 @@ void find_specified_device_and_mark_as_handled(Configuration *c, Detected *d)
|
|||
// This will find specified devices like: im871a, rtlwmbus
|
||||
for (SpecifiedDevice & sd : c->supplied_wmbus_devices)
|
||||
{
|
||||
if (sd.file == "" && sd.id == "" && toWMBusDeviceType(sd.type) == d->found_type)
|
||||
if (sd.file == "" && sd.id == "" && sd.type == d->found_type)
|
||||
{
|
||||
sd.handled = true;
|
||||
}
|
||||
|
@ -743,30 +760,14 @@ void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, Dete
|
|||
if (detected->found_type == DEVICE_UNKNOWN)
|
||||
{
|
||||
// This is a manual config, lets detect and check the device properly.
|
||||
AccessCheck ac = detectDevice(detected, serial_manager_);
|
||||
AccessCheck ac = reDetectDevice(detected, serial_manager_);
|
||||
if (ac != AccessCheck::AccessOK)
|
||||
{
|
||||
error("Could not open device %s\n", detected->specified_device.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
LinkModeSet lms {};
|
||||
string linkmodes = detected->specified_device.linkmodes;
|
||||
if (linkmodes != "")
|
||||
{
|
||||
lms = parseLinkModes(detected->specified_device.linkmodes);
|
||||
debug("(main) parsed specified device link modes %s to %s\n",
|
||||
linkmodes.c_str(), lms.hr().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
lms = config->linkmodes;
|
||||
debug("(main) using globally set link modes %s\n",
|
||||
lms.hr().c_str());
|
||||
}
|
||||
|
||||
assert(lms.bits() != 0);
|
||||
|
||||
LinkModeSet lms = detected->calculated_linkmodes;
|
||||
string using_link_modes = lms.hr();
|
||||
|
||||
string id = detected->found_device_id.c_str();
|
||||
|
@ -791,7 +792,7 @@ void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, Dete
|
|||
cmd.c_str());
|
||||
|
||||
// A newly plugged in device has been manually configured or automatically detected! Start using it!
|
||||
if (config->use_auto_detect || detected->found_type != DEVICE_SIMULATION)
|
||||
if (config->use_auto_device_detect || detected->found_type != DEVICE_SIMULATION)
|
||||
{
|
||||
notice("%s", started.c_str());
|
||||
}
|
||||
|
@ -840,12 +841,6 @@ void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, Dete
|
|||
wmbus->setTimeout(config->alarm_timeout, config->alarm_expected_activity);
|
||||
}
|
||||
|
||||
void perform_auto_scan_of_devices(Configuration *config)
|
||||
{
|
||||
perform_auto_scan_of_serial_devices(config);
|
||||
perform_auto_scan_of_swradio_devices(config);
|
||||
}
|
||||
|
||||
void perform_auto_scan_of_serial_devices(Configuration *config)
|
||||
{
|
||||
// Enumerate all serial devices that might connect to a wmbus device.
|
||||
|
@ -862,12 +857,27 @@ void perform_auto_scan_of_serial_devices(Configuration *config)
|
|||
trace("[MAIN] skipping already probed not wmbus serial device %s\n", tty.c_str());
|
||||
continue;
|
||||
}
|
||||
if (config->do_not_probe_ttys.count("all") > 0 ||
|
||||
config->do_not_probe_ttys.count(tty) > 0)
|
||||
{
|
||||
trace("[MAIN] not probing forbidden tty %s\n", tty.c_str());
|
||||
continue;
|
||||
}
|
||||
shared_ptr<SerialDevice> sd = serial_manager_->lookup(tty);
|
||||
if (!sd)
|
||||
{
|
||||
debug("(main) device %s not currently used, detect contents...\n", tty.c_str());
|
||||
// This serial device is not in use, but is there a device on it?
|
||||
Detected detected = detectWMBusDeviceOnTTY(tty, serial_manager_);
|
||||
debug("(main) device %s not currently used, detect contents...\n", tty.c_str());
|
||||
|
||||
// What should the desired linkmodes be? We have no specified device since this an auto detect.
|
||||
// But we might have an auto linkmodes?
|
||||
LinkModeSet desired_linkmodes = config->auto_device_linkmodes;
|
||||
if (desired_linkmodes.empty())
|
||||
{
|
||||
// Nope, lets fall back on the default_linkmodes.
|
||||
desired_linkmodes = config->default_device_linkmodes;
|
||||
}
|
||||
Detected detected = detectWMBusDeviceOnTTY(tty, desired_linkmodes, serial_manager_);
|
||||
if (detected.found_type != DEVICE_UNKNOWN)
|
||||
{
|
||||
// See if we had a specified device without a file,
|
||||
|
@ -1047,9 +1057,9 @@ bool start(Configuration *config)
|
|||
// Configure where the logging information should end up.
|
||||
setup_log_file(config);
|
||||
|
||||
if (config->meters.size() == 0 && !config->linkmodes_configured)
|
||||
if (config->meters.size() == 0 && config->all_device_linkmodes_specified.empty())
|
||||
{
|
||||
error("No meters supplied. You must supply which link modes to listen to. Eg. --listento=<modes>\n");
|
||||
error("No meters supplied. You must supply which link modes to listen to. 11 Eg. auto:c1\n");
|
||||
}
|
||||
|
||||
// Configure settings.
|
||||
|
|
|
@ -103,6 +103,11 @@ int indexFromRtlSdrSerial(std::string serialnr)
|
|||
|
||||
AccessCheck detectRTLSDR(string serialnr, Detected *detected)
|
||||
{
|
||||
if (detected->specified_device.type != WMBusDeviceType::DEVICE_RTLWMBUS ||
|
||||
detected->specified_device.type != WMBusDeviceType::DEVICE_RTL433)
|
||||
{
|
||||
return AccessCheck::NotThere;
|
||||
}
|
||||
uint32_t n = rtlsdr_get_device_count();
|
||||
|
||||
char mfct[256];
|
||||
|
@ -112,9 +117,12 @@ AccessCheck detectRTLSDR(string serialnr, Detected *detected)
|
|||
for (uint32_t i=0; i<n; ++i)
|
||||
{
|
||||
rtlsdr_get_device_usb_strings(i, mfct, product, serial);
|
||||
if (serialnr == serial)
|
||||
if (serialnr == "" || serialnr == serial)
|
||||
{
|
||||
detected->setAsFound(serialnr, WMBusDeviceType::DEVICE_RTLWMBUS, 0, false, false);
|
||||
LinkModeSet lms;
|
||||
lms.addLinkMode(LinkMode::C1);
|
||||
lms.addLinkMode(LinkMode::T1);
|
||||
detected->setAsFound(serialnr, detected->specified_device.type, 0, false, false, lms);
|
||||
return AccessCheck::AccessOK;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -244,7 +244,6 @@ int test_linkmodes()
|
|||
|
||||
Configuration nometers_config;
|
||||
// Check that if no meters are supplied then you must set a link mode.
|
||||
nometers_config.linkmodes_configured = false;
|
||||
lmcr = calculateLinkModes(&nometers_config, wmbus_im871a.get());
|
||||
if (lmcr.type != LinkModeCalculationResultType::NoMetersMustSupplyModes)
|
||||
{
|
||||
|
@ -252,8 +251,7 @@ int test_linkmodes()
|
|||
}
|
||||
debug("test0 OK\n\n");
|
||||
|
||||
nometers_config.linkmodes_configured = true;
|
||||
nometers_config.linkmodes.addLinkMode(LinkMode::T1);
|
||||
nometers_config.default_device_linkmodes.addLinkMode(LinkMode::T1);
|
||||
lmcr = calculateLinkModes(&nometers_config, wmbus_im871a.get());
|
||||
if (lmcr.type != LinkModeCalculationResultType::Success)
|
||||
{
|
||||
|
@ -271,7 +269,6 @@ int test_linkmodes()
|
|||
// Check that if no explicit link modes are provided to apator162, then
|
||||
// automatic deduction will fail, since apator162 can be configured to transmit
|
||||
// either C1 or T1 telegrams.
|
||||
apator_config.linkmodes_configured = false;
|
||||
lmcr = calculateLinkModes(&apator_config, wmbus_im871a.get());
|
||||
if (lmcr.type != LinkModeCalculationResultType::AutomaticDeductionFailed)
|
||||
{
|
||||
|
@ -281,10 +278,9 @@ int test_linkmodes()
|
|||
|
||||
// Check that if we supply the link mode T1 when using an apator162, then
|
||||
// automatic deduction will succeeed.
|
||||
apator_config.linkmodes_configured = true;
|
||||
apator_config.linkmodes = LinkModeSet();
|
||||
apator_config.linkmodes.addLinkMode(LinkMode::T1);
|
||||
apator_config.linkmodes.addLinkMode(LinkMode::C1);
|
||||
apator_config.default_device_linkmodes = LinkModeSet();
|
||||
apator_config.default_device_linkmodes.addLinkMode(LinkMode::T1);
|
||||
apator_config.default_device_linkmodes.addLinkMode(LinkMode::C1);
|
||||
lmcr = calculateLinkModes(&apator_config, wmbus_im871a.get());
|
||||
if (lmcr.type != LinkModeCalculationResultType::DongleCannotListenTo)
|
||||
{
|
||||
|
@ -313,7 +309,6 @@ int test_linkmodes()
|
|||
|
||||
// Check that meters that transmit on two different link modes cannot be listened to
|
||||
// at the same time using im871a.
|
||||
multical21_and_supercom587_config.linkmodes_configured = false;
|
||||
lmcr = calculateLinkModes(&multical21_and_supercom587_config, wmbus_im871a.get());
|
||||
if (lmcr.type != LinkModeCalculationResultType::AutomaticDeductionFailed)
|
||||
{
|
||||
|
@ -322,9 +317,8 @@ int test_linkmodes()
|
|||
debug("test4 OK\n\n");
|
||||
|
||||
// Explicitly set T1
|
||||
multical21_and_supercom587_config.linkmodes_configured = true;
|
||||
multical21_and_supercom587_config.linkmodes = LinkModeSet();
|
||||
multical21_and_supercom587_config.linkmodes.addLinkMode(LinkMode::T1);
|
||||
multical21_and_supercom587_config.default_device_linkmodes = LinkModeSet();
|
||||
multical21_and_supercom587_config.default_device_linkmodes.addLinkMode(LinkMode::T1);
|
||||
lmcr = calculateLinkModes(&multical21_and_supercom587_config, wmbus_im871a.get());
|
||||
if (lmcr.type != LinkModeCalculationResultType::MightMissTelegrams)
|
||||
{
|
||||
|
@ -333,9 +327,8 @@ int test_linkmodes()
|
|||
debug("test5 OK\n\n");
|
||||
|
||||
// Explicitly set N1a, but the meters transmit on C1 and T1.
|
||||
multical21_and_supercom587_config.linkmodes_configured = true;
|
||||
multical21_and_supercom587_config.linkmodes = LinkModeSet();
|
||||
multical21_and_supercom587_config.linkmodes.addLinkMode(LinkMode::N1a);
|
||||
multical21_and_supercom587_config.default_device_linkmodes = LinkModeSet();
|
||||
multical21_and_supercom587_config.default_device_linkmodes.addLinkMode(LinkMode::N1a);
|
||||
lmcr = calculateLinkModes(&multical21_and_supercom587_config, wmbus_im871a.get());
|
||||
if (lmcr.type != LinkModeCalculationResultType::MightMissTelegrams)
|
||||
{
|
||||
|
@ -344,9 +337,8 @@ int test_linkmodes()
|
|||
debug("test6 OK\n\n");
|
||||
|
||||
// Explicitly set N1a, but it is an amber dongle.
|
||||
multical21_and_supercom587_config.linkmodes_configured = true;
|
||||
multical21_and_supercom587_config.linkmodes = LinkModeSet();
|
||||
multical21_and_supercom587_config.linkmodes.addLinkMode(LinkMode::N1a);
|
||||
multical21_and_supercom587_config.default_device_linkmodes = LinkModeSet();
|
||||
multical21_and_supercom587_config.default_device_linkmodes.addLinkMode(LinkMode::N1a);
|
||||
lmcr = calculateLinkModes(&multical21_and_supercom587_config, wmbus_amb8465.get());
|
||||
if (lmcr.type != LinkModeCalculationResultType::DongleCannotListenTo)
|
||||
{
|
||||
|
@ -526,12 +518,13 @@ void testd(string arg, bool xok, string xfile, string xtype, string xid, string
|
|||
return;
|
||||
}
|
||||
if (ok == false) return;
|
||||
|
||||
if (d.file != xfile ||
|
||||
d.type != xtype ||
|
||||
toString(d.type) != xtype ||
|
||||
d.id != xid ||
|
||||
d.fq != xfq ||
|
||||
d.bps != xbps ||
|
||||
d.linkmodes != xlm ||
|
||||
d.linkmodes.hr() != xlm ||
|
||||
d.command != xcmd)
|
||||
{
|
||||
printf("ERROR in device parsing parts \"%s\"\n", arg.c_str());
|
||||
|
@ -573,7 +566,7 @@ void test_devices()
|
|||
"", // id
|
||||
"", // fq
|
||||
"", // bps
|
||||
"", // linkmodes
|
||||
"none", // linkmodes
|
||||
""); // command
|
||||
|
||||
testd("/dev/ttyUSB0:rawtty:9600", true,
|
||||
|
@ -582,7 +575,7 @@ void test_devices()
|
|||
"", // id
|
||||
"", // fq
|
||||
"9600", // bps
|
||||
"", // linkmodes
|
||||
"none", // linkmodes
|
||||
""); // command
|
||||
|
||||
// testinternals must be run from a location where
|
||||
|
@ -593,7 +586,7 @@ void test_devices()
|
|||
"", // id
|
||||
"", // fq
|
||||
"", // bps
|
||||
"", // linkmodes
|
||||
"none", // linkmodes
|
||||
""); // command
|
||||
|
||||
testd("auto:c1,t1", true,
|
||||
|
@ -611,7 +604,7 @@ void test_devices()
|
|||
"", // id
|
||||
"", // fq
|
||||
"", // bps
|
||||
"", // linkmodes
|
||||
"none", // linkmodes
|
||||
""); // command
|
||||
|
||||
testd("Vatten", false,
|
||||
|
@ -620,7 +613,7 @@ void test_devices()
|
|||
"", // id
|
||||
"", // fq
|
||||
"", // bps
|
||||
"", // linkmodes
|
||||
"none", // linkmodes
|
||||
""); // command
|
||||
|
||||
|
||||
|
|
126
src/wmbus.cc
126
src/wmbus.cc
|
@ -138,13 +138,14 @@ bool isValidLinkModes(string m)
|
|||
return true;
|
||||
}
|
||||
|
||||
void LinkModeSet::addLinkMode(LinkMode lm)
|
||||
LinkModeSet &LinkModeSet::addLinkMode(LinkMode lm)
|
||||
{
|
||||
for (auto& s : link_modes_) {
|
||||
if (s.mode == lm) {
|
||||
set_ |= s.val;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void LinkModeSet::unionLinkModeSet(LinkModeSet lms)
|
||||
|
@ -3193,8 +3194,10 @@ WMBusCommonImplementation::~WMBusCommonImplementation()
|
|||
|
||||
WMBusCommonImplementation::WMBusCommonImplementation(WMBusDeviceType t,
|
||||
shared_ptr<SerialCommunicationManager> manager,
|
||||
shared_ptr<SerialDevice> serial)
|
||||
shared_ptr<SerialDevice> serial,
|
||||
bool is_serial)
|
||||
: manager_(manager),
|
||||
is_serial_(is_serial),
|
||||
is_working_(true),
|
||||
type_(t),
|
||||
serial_(serial),
|
||||
|
@ -3220,6 +3223,17 @@ string WMBusCommonImplementation::hr()
|
|||
return cached_hr_;
|
||||
}
|
||||
|
||||
bool WMBusCommonImplementation::isSerial()
|
||||
{
|
||||
return is_serial_;
|
||||
}
|
||||
|
||||
void WMBusCommonImplementation::markAsNoLongerSerial()
|
||||
{
|
||||
// When you override the serial device with a file for an im871a, then
|
||||
// it is no longer a serial device.
|
||||
is_serial_ = false;
|
||||
}
|
||||
|
||||
WMBusDeviceType WMBusCommonImplementation::type()
|
||||
{
|
||||
|
@ -3928,7 +3942,7 @@ const char *toString(WMBusDeviceType t)
|
|||
{
|
||||
switch (t)
|
||||
{
|
||||
#define X(name,text) case DEVICE_ ## name: return #name;
|
||||
#define X(name,text,tty,rtlsdr) case DEVICE_ ## name: return #text;
|
||||
LIST_OF_MBUS_DEVICES
|
||||
#undef X
|
||||
|
||||
|
@ -3940,7 +3954,7 @@ const char *toLowerCaseString(WMBusDeviceType t)
|
|||
{
|
||||
switch (t)
|
||||
{
|
||||
#define X(name,text) case DEVICE_ ## name: return #text;
|
||||
#define X(name,text,tty,rtlsdr) case DEVICE_ ## name: return #text;
|
||||
LIST_OF_MBUS_DEVICES
|
||||
#undef X
|
||||
|
||||
|
@ -3950,7 +3964,7 @@ LIST_OF_MBUS_DEVICES
|
|||
|
||||
WMBusDeviceType toWMBusDeviceType(string &t)
|
||||
{
|
||||
#define X(name,text) if (t == #text) return DEVICE_ ## name;
|
||||
#define X(name,text,tty,rtlsdr) if (t == #text) return DEVICE_ ## name;
|
||||
LIST_OF_MBUS_DEVICES
|
||||
#undef X
|
||||
return DEVICE_UNKNOWN;
|
||||
|
@ -4015,14 +4029,14 @@ bool check_file(string f, bool *is_tty, bool *is_stdin, bool *is_file, bool *is_
|
|||
return false;
|
||||
}
|
||||
|
||||
bool is_type_id(string t, string *out_type, string *out_id)
|
||||
bool is_type_id(string t, WMBusDeviceType *out_type, string *out_id)
|
||||
{
|
||||
// im871a im871a(12345678)
|
||||
// auto
|
||||
// rtlwmbus
|
||||
if (t == "auto")
|
||||
{
|
||||
*out_type = t;
|
||||
*out_type = WMBusDeviceType::DEVICE_AUTO;
|
||||
*out_id = "";
|
||||
return true;
|
||||
}
|
||||
|
@ -4035,7 +4049,7 @@ bool is_type_id(string t, string *out_type, string *out_id)
|
|||
// No parentheses found, is t a known wmbus device? like im871a amb8465 etc....
|
||||
WMBusDeviceType tt = toWMBusDeviceType(t);
|
||||
if (tt == DEVICE_UNKNOWN) return false;
|
||||
*out_type = t;
|
||||
*out_type = toWMBusDeviceType(t);
|
||||
*out_id = "";
|
||||
return true;
|
||||
}
|
||||
|
@ -4048,7 +4062,7 @@ bool is_type_id(string t, string *out_type, string *out_id)
|
|||
WMBusDeviceType tt = toWMBusDeviceType(type);
|
||||
if (tt == DEVICE_UNKNOWN) return false;
|
||||
if (!isValidId(id, true)) return false;
|
||||
*out_type = type;
|
||||
*out_type = toWMBusDeviceType(type);
|
||||
*out_id = id;
|
||||
return true;
|
||||
}
|
||||
|
@ -4060,17 +4074,17 @@ bool is_type_id(string t, string *out_type, string *out_id)
|
|||
void SpecifiedDevice::clear()
|
||||
{
|
||||
file = "";
|
||||
type = "";
|
||||
type = WMBusDeviceType::DEVICE_UNKNOWN;
|
||||
id = "";
|
||||
fq = "";
|
||||
linkmodes = "";
|
||||
linkmodes.clear();
|
||||
}
|
||||
|
||||
string SpecifiedDevice::str()
|
||||
{
|
||||
string r;
|
||||
if (file != "") r += file+":";
|
||||
if (type != "")
|
||||
if (type != WMBusDeviceType::DEVICE_UNKNOWN)
|
||||
{
|
||||
r += type;
|
||||
if (id != "")
|
||||
|
@ -4081,7 +4095,7 @@ string SpecifiedDevice::str()
|
|||
}
|
||||
if (bps != "") r += bps+":";
|
||||
if (fq != "") r += fq+":";
|
||||
if (linkmodes != "") r += linkmodes+":";
|
||||
if (!linkmodes.empty()) r += linkmodes.hr()+":";
|
||||
if (command != "") r += "CMD("+command+"):";
|
||||
|
||||
if (r.size() > 0) r.pop_back();
|
||||
|
@ -4112,7 +4126,7 @@ bool SpecifiedDevice::parse(string &arg)
|
|||
// file type id bps fq linkmodes command
|
||||
for (auto& p : parts)
|
||||
{
|
||||
if (file_checked && typeid_checked && file == "" && type == "" && id == "")
|
||||
if (file_checked && typeid_checked && file == "" && type == WMBusDeviceType::DEVICE_UNKNOWN && id == "")
|
||||
{
|
||||
// There must be either a file and/or type(id). If none are found,
|
||||
// then the specified device string is faulty.
|
||||
|
@ -4150,7 +4164,7 @@ bool SpecifiedDevice::parse(string &arg)
|
|||
bps_checked = true;
|
||||
fq_checked = true;
|
||||
linkmodes_checked = true;
|
||||
linkmodes = p;
|
||||
linkmodes = parseLinkModes(p);
|
||||
}
|
||||
else if (!command_checked && is_command(p, &command))
|
||||
{
|
||||
|
@ -4169,18 +4183,21 @@ bool SpecifiedDevice::parse(string &arg)
|
|||
}
|
||||
|
||||
// Auto is only allowed to be combined with linkmodes and/or frequencies!
|
||||
if (type == "auto" && (file != "" || bps != "")) return false;
|
||||
if (type == WMBusDeviceType::DEVICE_AUTO && (file != "" || bps != "")) return false;
|
||||
// You cannot combine a file with a command.
|
||||
if (file != "" && command != "") return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Detected detectWMBusDeviceOnTTY(string tty, shared_ptr<SerialCommunicationManager> handler)
|
||||
Detected detectWMBusDeviceOnTTY(string tty,
|
||||
LinkModeSet desired_linkmodes,
|
||||
shared_ptr<SerialCommunicationManager> handler)
|
||||
{
|
||||
Detected detected;
|
||||
// Fake a specified device.
|
||||
detected.found_file = tty;
|
||||
detected.specified_device.is_tty = true;
|
||||
detected.specified_device.linkmodes = desired_linkmodes;
|
||||
|
||||
// If im87a is tested first, a delay of 1s must be inserted
|
||||
// before amb8465 is tested, lest it will not respond properly.
|
||||
|
@ -4222,6 +4239,7 @@ Detected detectWMBusDeviceOnTTY(string tty, shared_ptr<SerialCommunicationManage
|
|||
}
|
||||
|
||||
Detected detectWMBusDeviceWithFile(SpecifiedDevice &specified_device,
|
||||
LinkModeSet default_linkmodes,
|
||||
shared_ptr<SerialCommunicationManager> handler)
|
||||
{
|
||||
assert(specified_device.file != "");
|
||||
|
@ -4231,44 +4249,59 @@ Detected detectWMBusDeviceWithFile(SpecifiedDevice &specified_device,
|
|||
Detected detected;
|
||||
detected.found_file = specified_device.file;
|
||||
detected.setSpecifiedDevice(specified_device);
|
||||
|
||||
// If <device>:c1 is missing :c1 then use --c1.
|
||||
LinkModeSet lms = specified_device.linkmodes;
|
||||
if (lms.empty())
|
||||
{
|
||||
lms = default_linkmodes;
|
||||
}
|
||||
if (specified_device.is_simulation)
|
||||
{
|
||||
debug("(lookup) driver: simulation file\n");
|
||||
detected.setAsFound("", DEVICE_SIMULATION, 0 , false, false);
|
||||
specified_device.linkmodes = "any";
|
||||
// A simulation file has a lms of all by default, eg no simulation_foo.txt:t1 nor --t1
|
||||
if (specified_device.linkmodes.empty()) lms.setAll();
|
||||
detected.setAsFound("", DEVICE_SIMULATION, 0 , false, false, lms);
|
||||
return detected;
|
||||
}
|
||||
|
||||
// Special case to cater for /dev/ttyUSB0:9600, ie the rawtty is implicit.
|
||||
if (specified_device.type == "" && specified_device.bps != "" && specified_device.is_tty)
|
||||
if (specified_device.type == WMBusDeviceType::DEVICE_UNKNOWN && specified_device.bps != "" && specified_device.is_tty)
|
||||
{
|
||||
debug("(lookup) driver: rawtty\n");
|
||||
detected.setAsFound("", DEVICE_RAWTTY, atoi(specified_device.bps.c_str()), false, false);
|
||||
// A rawtty has a lms of all by default, eg no simulation_foo.txt:t1 nor --t1
|
||||
if (specified_device.linkmodes.empty()) lms.setAll();
|
||||
detected.setAsFound("", DEVICE_RAWTTY, atoi(specified_device.bps.c_str()), false, false, lms);
|
||||
return detected;
|
||||
}
|
||||
|
||||
// Special case to cater for raw_data.bin, ie the rawtty is implicit.
|
||||
if (specified_device.type == "" && !specified_device.is_tty)
|
||||
if (specified_device.type == WMBusDeviceType::DEVICE_UNKNOWN && !specified_device.is_tty)
|
||||
{
|
||||
debug("(lookup) driver: raw file\n");
|
||||
detected.setAsFound("", DEVICE_RAWTTY, 0, true, false);
|
||||
// A rawtty has a lms of all by default, eg no simulation_foo.txt:t1 nor --t1
|
||||
if (specified_device.linkmodes.empty()) lms.setAll();
|
||||
detected.setAsFound("", DEVICE_RAWTTY, 0, true, false, lms);
|
||||
return detected;
|
||||
}
|
||||
|
||||
// Now handle all files with specified type.
|
||||
if (specified_device.type != "")
|
||||
if (specified_device.type != WMBusDeviceType::DEVICE_UNKNOWN &&
|
||||
specified_device.type != WMBusDeviceType::DEVICE_AUTO)
|
||||
{
|
||||
debug("(lookup) driver: %s\n", specified_device.type.c_str());
|
||||
detected.setAsFound("", toWMBusDeviceType(specified_device.type), 0, specified_device.is_file || specified_device.is_stdin, false);
|
||||
debug("(lookup) driver: %s\n", toString(specified_device.type));
|
||||
assert(!lms.empty());
|
||||
detected.setAsFound("", specified_device.type, 0, specified_device.is_file || specified_device.is_stdin,
|
||||
false, lms);
|
||||
return detected;
|
||||
}
|
||||
// Ok, we are left with a single /dev/ttyUSB0 lets talk to it
|
||||
// to figure out what is connected to it.
|
||||
return detectWMBusDeviceOnTTY(specified_device.file, handler);
|
||||
LinkModeSet desired_linkmodes = default_linkmodes;
|
||||
return detectWMBusDeviceOnTTY(specified_device.file, desired_linkmodes, handler);
|
||||
}
|
||||
|
||||
Detected detectWMBusDeviceWithCommand(SpecifiedDevice &specified_device,
|
||||
LinkModeSet default_linkmodes,
|
||||
shared_ptr<SerialCommunicationManager> handler)
|
||||
{
|
||||
assert(specified_device.file == "");
|
||||
|
@ -4278,7 +4311,10 @@ Detected detectWMBusDeviceWithCommand(SpecifiedDevice &specified_device,
|
|||
Detected detected;
|
||||
detected.found_command = specified_device.command;
|
||||
detected.setSpecifiedDevice(specified_device);
|
||||
detected.setAsFound("", toWMBusDeviceType(specified_device.type), 0, false, true);
|
||||
LinkModeSet lms = specified_device.linkmodes;
|
||||
// If the specified device did not set any linkmodes fall back on the default linkmodes.
|
||||
if (lms.empty()) lms = default_linkmodes;
|
||||
detected.setAsFound("", specified_device.type, 0, false, true, lms);
|
||||
|
||||
return detected;
|
||||
}
|
||||
|
@ -4293,14 +4329,40 @@ AccessCheck detectSIMULATION(Detected *detected, shared_ptr<SerialCommunicationM
|
|||
return AccessCheck::NotThere;
|
||||
}
|
||||
|
||||
AccessCheck detectDevice(Detected *detected, shared_ptr<SerialCommunicationManager> handler)
|
||||
AccessCheck detectAUTO(Detected *detected, shared_ptr<SerialCommunicationManager> handler)
|
||||
{
|
||||
string type = detected->specified_device.type;
|
||||
// Detection of auto is currently not implemented here, but elsewhere.
|
||||
return AccessCheck::NotThere;
|
||||
}
|
||||
|
||||
#define X(name,text) if (type == #text) return detect ## name(detected,handler);
|
||||
AccessCheck reDetectDevice(Detected *detected, shared_ptr<SerialCommunicationManager> handler)
|
||||
{
|
||||
WMBusDeviceType type = detected->specified_device.type;
|
||||
|
||||
#define X(name,text,tty,rtlsdr) if (type == WMBusDeviceType::DEVICE_ ## name) return detect ## name(detected,handler);
|
||||
LIST_OF_MBUS_DEVICES
|
||||
#undef X
|
||||
|
||||
assert(0);
|
||||
return AccessCheck::NotThere;
|
||||
}
|
||||
|
||||
bool usesRTLSDR(WMBusDeviceType t)
|
||||
{
|
||||
#define X(name,text,tty,rtlsdr) if (t == WMBusDeviceType::DEVICE_ ## name) return rtlsdr;
|
||||
LIST_OF_MBUS_DEVICES
|
||||
#undef X
|
||||
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool usesTTY(WMBusDeviceType t)
|
||||
{
|
||||
#define X(name,text,tty,rtlsdr) if (t == WMBusDeviceType::DEVICE_ ## name) return tty;
|
||||
LIST_OF_MBUS_DEVICES
|
||||
#undef X
|
||||
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
|
185
src/wmbus.h
185
src/wmbus.h
|
@ -30,87 +30,44 @@
|
|||
bool trimCRCsFrameFormatA(std::vector<uchar> &payload);
|
||||
bool trimCRCsFrameFormatB(std::vector<uchar> &payload);
|
||||
|
||||
// A wmbus specified device is supplied on the command line or in the config file.
|
||||
// It has this format "file:type(id):fq:bps:linkmods:CMD(command)"
|
||||
struct SpecifiedDevice
|
||||
{
|
||||
int index; // 0,1,2,3 the order on the command line / config file.
|
||||
std::string file; // simulation_meter.txt, stdin, file.raw, /dev/ttyUSB0
|
||||
bool is_tty{}, is_stdin{}, is_file{}, is_simulation{};
|
||||
std::string type; // im871a, rtlwmbus
|
||||
std::string id; // 12345678 for wmbus dongles or 0,1 for rtlwmbus indexes.
|
||||
std::string fq; // 868.95M
|
||||
std::string bps; // 9600
|
||||
std::string linkmodes; // c1,t1,s1
|
||||
std::string command; // command line of background process that streams data into wmbusmeters
|
||||
|
||||
bool handled {}; // Set to true when this device has been detected/handled.
|
||||
time_t last_alarm {}; // Last time an alarm was sent for this device not being found.
|
||||
|
||||
void clear();
|
||||
string str();
|
||||
bool parse(string &s);
|
||||
};
|
||||
|
||||
#define LIST_OF_MBUS_DEVICES \
|
||||
X(UNKNOWN,unknown) \
|
||||
X(AMB8465,amb8465) \
|
||||
X(CUL,cul) \
|
||||
X(IM871A,im871a) \
|
||||
X(RAWTTY,rawtty) \
|
||||
X(RC1180,rc1180) \
|
||||
X(RTL433,rtl433) \
|
||||
X(RTLWMBUS,rtlwmbus) \
|
||||
X(SIMULATION,simulation)
|
||||
X(UNKNOWN,unknown,false,false) \
|
||||
X(AUTO,auto,false,false) \
|
||||
X(AMB8465,amb8465,true,false) \
|
||||
X(CUL,cul,true,false) \
|
||||
X(IM871A,im871a,true,false) \
|
||||
X(RAWTTY,rawtty,true,false) \
|
||||
X(RC1180,rc1180,true,false) \
|
||||
X(RTL433,rtl433,false,true) \
|
||||
X(RTLWMBUS,rtlwmbus,false,true)\
|
||||
X(SIMULATION,simulation,false,false)
|
||||
|
||||
enum WMBusDeviceType {
|
||||
#define X(name,text) DEVICE_ ## name,
|
||||
#define X(name,text,tty,rtlsdr) DEVICE_ ## name,
|
||||
LIST_OF_MBUS_DEVICES
|
||||
#undef X
|
||||
};
|
||||
|
||||
bool usesTTY(WMBusDeviceType t);
|
||||
bool usesRTLSDR(WMBusDeviceType t);
|
||||
const char *toString(WMBusDeviceType t);
|
||||
const char *toLowerCaseString(WMBusDeviceType t);
|
||||
WMBusDeviceType toWMBusDeviceType(string &t);
|
||||
|
||||
void setIgnoreDuplicateTelegrams(bool idt);
|
||||
|
||||
struct Detected
|
||||
{
|
||||
SpecifiedDevice specified_device {}; // Device as specified from the command line / config file.
|
||||
// In link mode S1, is used when both the transmitter and receiver are stationary.
|
||||
// It can be transmitted relatively seldom.
|
||||
|
||||
string found_file; // The device file to use.
|
||||
string found_device_id; // An "unique" identifier, typically the id used by the dongle as its own wmbus id, if it transmits.
|
||||
WMBusDeviceType found_type {}; // IM871A, AMB8465 etc.
|
||||
int found_bps {}; // Serial speed of tty, overrides
|
||||
bool found_tty_override {}; // override tty
|
||||
bool found_cmd_override {}; // override cmd
|
||||
string found_command;
|
||||
// In link mode T1, the meter transmits a telegram every few seconds or minutes.
|
||||
// Suitable for drive-by/walk-by collection of meter values.
|
||||
|
||||
void setSpecifiedDeviceAsAuto()
|
||||
{
|
||||
specified_device.clear();
|
||||
}
|
||||
// Link mode C1 is like T1 but uses less energy when transmitting due to
|
||||
// a different radio encoding. Also significant is:
|
||||
// S1/T1 usually uses the A format for the data link layer, more CRCs.
|
||||
// C1 usually uses the B format for the data link layer, less CRCs = less overhead.
|
||||
|
||||
void setSpecifiedDevice(SpecifiedDevice sd)
|
||||
{
|
||||
specified_device = sd;
|
||||
}
|
||||
|
||||
void setAsFound(string id, WMBusDeviceType t, int b, bool to, bool co)
|
||||
{
|
||||
found_device_id = id;
|
||||
found_type = t;
|
||||
found_bps = b;
|
||||
found_tty_override = to;
|
||||
found_cmd_override = co;
|
||||
}
|
||||
|
||||
std::string str()
|
||||
{
|
||||
return found_file+":"+string(toString(found_type))+"["+found_device_id+"]"+":"+to_string(found_bps)+"/"+to_string(found_tty_override);
|
||||
}
|
||||
};
|
||||
// The im871a can for example receive C1a, but it is unclear if there are any meters that use it.
|
||||
|
||||
#define LIST_OF_LINK_MODES \
|
||||
X(Any,any,--anylinkmode,0xffff) \
|
||||
|
@ -126,19 +83,6 @@ struct Detected
|
|||
X(N1f,n1f,--n1f,0x200) \
|
||||
X(UNKNOWN,unknown,----,0x0)
|
||||
|
||||
// In link mode S1, is used when both the transmitter and receiver are stationary.
|
||||
// It can be transmitted relatively seldom.
|
||||
|
||||
// In link mode T1, the meter transmits a telegram every few seconds or minutes.
|
||||
// Suitable for drive-by/walk-by collection of meter values.
|
||||
|
||||
// Link mode C1 is like T1 but uses less energy when transmitting due to
|
||||
// a different radio encoding. Also significant is:
|
||||
// S1/T1 usually uses the A format for the data link layer, more CRCs.
|
||||
// C1 usually uses the B format for the data link layer, less CRCs = less overhead.
|
||||
|
||||
// The im871a can for example receive C1a, but it is unclear if there are any meters that use it.
|
||||
|
||||
enum class LinkMode {
|
||||
#define X(name,lcname,option,val) name,
|
||||
LIST_OF_LINK_MODES
|
||||
|
@ -157,7 +101,7 @@ LinkMode isLinkModeOption(const char *arg);
|
|||
struct LinkModeSet
|
||||
{
|
||||
// Add the link mode to the set of link modes.
|
||||
void addLinkMode(LinkMode lm);
|
||||
LinkModeSet &addLinkMode(LinkMode lm);
|
||||
void unionLinkModeSet(LinkModeSet lms);
|
||||
void disjunctionLinkModeSet(LinkModeSet lms);
|
||||
// Does this set support listening to the given link mode set?
|
||||
|
@ -177,8 +121,14 @@ struct LinkModeSet
|
|||
bool has(LinkMode lm);
|
||||
// Check if all link modes are supported.
|
||||
bool hasAll(LinkModeSet lms);
|
||||
|
||||
int bits() { return set_; }
|
||||
// Check if any link mode has been set.
|
||||
bool empty() { return set_ == 0; }
|
||||
// Clear the set to empty.
|
||||
void clear() { set_ = 0; }
|
||||
// Mark set as all linkmodes!
|
||||
void setAll() { set_ = (int)LinkMode::Any; }
|
||||
// For bit counting etc.
|
||||
int asBits() { return set_; }
|
||||
|
||||
// Return a human readable string.
|
||||
std::string hr();
|
||||
|
@ -194,6 +144,67 @@ private:
|
|||
LinkModeSet parseLinkModes(string modes);
|
||||
bool isValidLinkModes(string modes);
|
||||
|
||||
// A wmbus specified device is supplied on the command line or in the config file.
|
||||
// It has this format "file:type(id):fq:bps:linkmods:CMD(command)"
|
||||
struct SpecifiedDevice
|
||||
{
|
||||
int index; // 0,1,2,3 the order on the command line / config file.
|
||||
std::string file; // simulation_meter.txt, stdin, file.raw, /dev/ttyUSB0
|
||||
bool is_tty{}, is_stdin{}, is_file{}, is_simulation{};
|
||||
WMBusDeviceType type; // im871a, rtlwmbus
|
||||
std::string id; // 12345678 for wmbus dongles or 0,1 for rtlwmbus indexes.
|
||||
std::string fq; // 868.95M
|
||||
std::string bps; // 9600
|
||||
LinkModeSet linkmodes; // c1,t1,s1
|
||||
std::string command; // command line of background process that streams data into wmbusmeters
|
||||
|
||||
bool handled {}; // Set to true when this device has been detected/handled.
|
||||
time_t last_alarm {}; // Last time an alarm was sent for this device not being found.
|
||||
|
||||
void clear();
|
||||
string str();
|
||||
bool parse(string &s);
|
||||
};
|
||||
|
||||
struct Detected
|
||||
{
|
||||
SpecifiedDevice specified_device {}; // Device as specified from the command line / config file.
|
||||
|
||||
string found_file; // The device file to use.
|
||||
string found_device_id; // An "unique" identifier, typically the id used by the dongle as its own wmbus id, if it transmits.
|
||||
WMBusDeviceType found_type {}; // IM871A, AMB8465 etc.
|
||||
int found_bps {}; // Serial speed of tty, overrides
|
||||
bool found_tty_override {}; // override tty
|
||||
bool found_cmd_override {}; // override cmd
|
||||
string found_command;
|
||||
LinkModeSet calculated_linkmodes; // Calculated from specified lms and default lms.
|
||||
|
||||
void setSpecifiedDeviceAsAuto()
|
||||
{
|
||||
specified_device.clear();
|
||||
}
|
||||
|
||||
void setSpecifiedDevice(SpecifiedDevice sd)
|
||||
{
|
||||
specified_device = sd;
|
||||
}
|
||||
|
||||
void setAsFound(string id, WMBusDeviceType t, int b, bool to, bool co, LinkModeSet clm)
|
||||
{
|
||||
found_device_id = id;
|
||||
found_type = t;
|
||||
found_bps = b;
|
||||
found_tty_override = to;
|
||||
found_cmd_override = co;
|
||||
calculated_linkmodes = clm;
|
||||
}
|
||||
|
||||
std::string str()
|
||||
{
|
||||
return found_file+":"+string(toString(found_type))+"["+found_device_id+"]"+":"+to_string(found_bps)+"/"+to_string(found_tty_override);
|
||||
}
|
||||
};
|
||||
|
||||
enum class CONNECTION
|
||||
{
|
||||
MBUS, WMBUS, BOTH
|
||||
|
@ -511,8 +522,9 @@ struct WMBus
|
|||
// The im871a and amb8465 dongles does have a unique, immutable id as well.
|
||||
// Not all dongles have this.
|
||||
virtual string getDeviceUniqueId() = 0;
|
||||
|
||||
// Human readable explanation of this device, eg: /dev/ttysUB0:im871a[12345678]:t1
|
||||
virtual std::string hr() = 0;
|
||||
virtual bool isSerial() = 0;
|
||||
|
||||
virtual LinkModeSet getLinkModes() = 0;
|
||||
virtual bool ping() = 0;
|
||||
|
@ -548,8 +560,10 @@ struct WMBus
|
|||
};
|
||||
|
||||
Detected detectWMBusDeviceWithFile(SpecifiedDevice &specified_device,
|
||||
LinkModeSet default_linkmodes,
|
||||
shared_ptr<SerialCommunicationManager> manager);
|
||||
Detected detectWMBusDeviceWithCommand(SpecifiedDevice &specified_device,
|
||||
LinkModeSet default_linkmodes,
|
||||
shared_ptr<SerialCommunicationManager> handler);
|
||||
|
||||
|
||||
|
@ -624,8 +638,9 @@ FrameStatus checkWMBusFrame(vector<uchar> &data,
|
|||
int *payload_len_out,
|
||||
int *payload_offset);
|
||||
|
||||
AccessCheck detectDevice(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||
AccessCheck reDetectDevice(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||
|
||||
AccessCheck detectAUTO(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||
AccessCheck detectAMB8465(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||
AccessCheck detectCUL(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||
AccessCheck detectD1TC(Detected *detected, shared_ptr<SerialCommunicationManager> manager);
|
||||
|
@ -640,6 +655,8 @@ AccessCheck detectWMB13U(Detected *detected, shared_ptr<SerialCommunicationManag
|
|||
// restore to factory settings.
|
||||
AccessCheck factoryResetAMB8465(string tty, shared_ptr<SerialCommunicationManager> handler, int *was_baud);
|
||||
|
||||
Detected detectWMBusDeviceOnTTY(string tty, shared_ptr<SerialCommunicationManager> handler);
|
||||
Detected detectWMBusDeviceOnTTY(string tty,
|
||||
LinkModeSet desired_linkmodes,
|
||||
shared_ptr<SerialCommunicationManager> handler);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -95,14 +95,14 @@ struct WMBusAmber : public virtual WMBusCommonImplementation
|
|||
int numConcurrentLinkModes() { return 1; }
|
||||
bool canSetLinkModes(LinkModeSet desired_modes)
|
||||
{
|
||||
if (0 == countSetBits(desired_modes.bits())) return false;
|
||||
if (desired_modes.empty()) return false;
|
||||
// Simple check first, are they all supported?
|
||||
if (!supportedLinkModes().supports(desired_modes)) return false;
|
||||
// So far so good, is the desired combination supported?
|
||||
// If only a single bit is desired, then it is supported.
|
||||
if (1 == countSetBits(desired_modes.bits())) return true;
|
||||
if (1 == countSetBits(desired_modes.asBits())) return true;
|
||||
// More than 2 listening modes at the same time will always fail.
|
||||
if (2 != countSetBits(desired_modes.bits())) return false;
|
||||
if (2 != countSetBits(desired_modes.asBits())) return false;
|
||||
// C1 and T1 can be listened to at the same time!
|
||||
if (desired_modes.has(LinkMode::C1) && desired_modes.has(LinkMode::T1)) return true;
|
||||
// Likewise for S1 and S1-m
|
||||
|
@ -146,6 +146,7 @@ shared_ptr<WMBus> openAMB8465(string device, shared_ptr<SerialCommunicationManag
|
|||
if (serial_override)
|
||||
{
|
||||
WMBusAmber *imp = new WMBusAmber(serial_override, manager);
|
||||
imp->markAsNoLongerSerial();
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
||||
|
@ -155,7 +156,7 @@ shared_ptr<WMBus> openAMB8465(string device, shared_ptr<SerialCommunicationManag
|
|||
}
|
||||
|
||||
WMBusAmber::WMBusAmber(shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager) :
|
||||
WMBusCommonImplementation(DEVICE_AMB8465, manager, serial)
|
||||
WMBusCommonImplementation(DEVICE_AMB8465, manager, serial, true)
|
||||
{
|
||||
rssi_expected_ = true;
|
||||
reset();
|
||||
|
@ -604,7 +605,8 @@ AccessCheck detectAMB8465(Detected *detected, shared_ptr<SerialCommunicationMana
|
|||
ConfigAMB8465 config;
|
||||
config.decode(response);
|
||||
|
||||
detected->setAsFound(config.dongleId(), WMBusDeviceType::DEVICE_AMB8465, 9600, false, false);
|
||||
detected->setAsFound(config.dongleId(), WMBusDeviceType::DEVICE_AMB8465, 9600, false, false,
|
||||
detected->specified_device.linkmodes);
|
||||
|
||||
verbose("(amb8465) detect %s\n", config.str().c_str());
|
||||
verbose("(amb8465) are you there? yes %s\n", config.dongleId().c_str());
|
||||
|
|
|
@ -24,10 +24,14 @@
|
|||
|
||||
struct WMBusCommonImplementation : public virtual WMBus
|
||||
{
|
||||
WMBusCommonImplementation(WMBusDeviceType t, shared_ptr<SerialCommunicationManager> manager, shared_ptr<SerialDevice> serial_override);
|
||||
WMBusCommonImplementation(WMBusDeviceType t,
|
||||
shared_ptr<SerialCommunicationManager> manager,
|
||||
shared_ptr<SerialDevice> serial_override,
|
||||
bool is_serial);
|
||||
~WMBusCommonImplementation();
|
||||
|
||||
string hr();
|
||||
bool isSerial();
|
||||
WMBusDeviceType type();
|
||||
void onTelegram(function<bool(AboutTelegram&,vector<uchar>)> cb);
|
||||
bool handleTelegram(AboutTelegram &about, vector<uchar> frame);
|
||||
|
@ -52,6 +56,7 @@ struct WMBusCommonImplementation : public virtual WMBus
|
|||
void close();
|
||||
void setDetected(Detected detected) { detected_ = detected; }
|
||||
Detected *getDetected() { return &detected_; }
|
||||
void markAsNoLongerSerial();
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -68,6 +73,8 @@ struct WMBusCommonImplementation : public virtual WMBus
|
|||
|
||||
private:
|
||||
|
||||
// Uses a serial tty?
|
||||
bool is_serial_ {};
|
||||
bool is_working_ {};
|
||||
vector<function<bool(AboutTelegram&,vector<uchar>)>> telegram_listeners_;
|
||||
WMBusDeviceType type_ {};
|
||||
|
|
|
@ -54,11 +54,11 @@ struct WMBusCUL : public virtual WMBusCommonImplementation
|
|||
int numConcurrentLinkModes() { return 1; }
|
||||
bool canSetLinkModes(LinkModeSet lms)
|
||||
{
|
||||
if (0 == countSetBits(lms.bits())) return false;
|
||||
if (lms.empty()) return false;
|
||||
if (!supportedLinkModes().supports(lms)) return false;
|
||||
// Ok, the supplied link modes are compatible,
|
||||
// but im871a can only listen to one at a time.
|
||||
return 1 == countSetBits(lms.bits());
|
||||
return 1 == countSetBits(lms.asBits());
|
||||
}
|
||||
void processSerialData();
|
||||
void simulate();
|
||||
|
@ -86,6 +86,7 @@ shared_ptr<WMBus> openCUL(string device, shared_ptr<SerialCommunicationManager>
|
|||
if (serial_override)
|
||||
{
|
||||
WMBusCUL *imp = new WMBusCUL(serial_override, manager);
|
||||
imp->markAsNoLongerSerial();
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
||||
|
@ -95,7 +96,7 @@ shared_ptr<WMBus> openCUL(string device, shared_ptr<SerialCommunicationManager>
|
|||
}
|
||||
|
||||
WMBusCUL::WMBusCUL(shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager) :
|
||||
WMBusCommonImplementation(DEVICE_CUL, manager, serial)
|
||||
WMBusCommonImplementation(DEVICE_CUL, manager, serial, true)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
@ -391,7 +392,7 @@ AccessCheck detectCUL(Detected *detected, shared_ptr<SerialCommunicationManager>
|
|||
return AccessCheck::NotThere;
|
||||
}
|
||||
|
||||
detected->setAsFound("", WMBusDeviceType::DEVICE_CUL, 38400, false, false);
|
||||
detected->setAsFound("", WMBusDeviceType::DEVICE_CUL, 38400, false, false, detected->specified_device.linkmodes);
|
||||
|
||||
return AccessCheck::AccessOK;
|
||||
}
|
||||
|
|
|
@ -176,11 +176,11 @@ struct WMBusIM871A : public virtual WMBusCommonImplementation
|
|||
int numConcurrentLinkModes() { return 1; }
|
||||
bool canSetLinkModes(LinkModeSet lms)
|
||||
{
|
||||
if (0 == countSetBits(lms.bits())) return false;
|
||||
if (lms.empty()) return false;
|
||||
if (!supportedLinkModes().supports(lms)) return false;
|
||||
// Ok, the supplied link modes are compatible,
|
||||
// but im871a can only listen to one at a time.
|
||||
return 1 == countSetBits(lms.bits());
|
||||
return 1 == countSetBits(lms.asBits());
|
||||
}
|
||||
void processSerialData();
|
||||
void simulate() { }
|
||||
|
@ -234,6 +234,7 @@ shared_ptr<WMBus> openIM871A(string device, shared_ptr<SerialCommunicationManage
|
|||
if (serial_override)
|
||||
{
|
||||
WMBusIM871A *imp = new WMBusIM871A(serial_override, manager);
|
||||
imp->markAsNoLongerSerial();
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
||||
|
@ -243,7 +244,7 @@ shared_ptr<WMBus> openIM871A(string device, shared_ptr<SerialCommunicationManage
|
|||
}
|
||||
|
||||
WMBusIM871A::WMBusIM871A(shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager) :
|
||||
WMBusCommonImplementation(DEVICE_IM871A, manager, serial)
|
||||
WMBusCommonImplementation(DEVICE_IM871A, manager, serial, true)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
@ -910,7 +911,8 @@ AccessCheck detectIM871A(Detected *detected, shared_ptr<SerialCommunicationManag
|
|||
|
||||
debug("(im871a) config: %s\n", co.str().c_str());
|
||||
|
||||
detected->setAsFound(co.dongleId(), WMBusDeviceType::DEVICE_IM871A, 57600, false, false);
|
||||
detected->setAsFound(co.dongleId(), WMBusDeviceType::DEVICE_IM871A, 57600, false, false,
|
||||
detected->specified_device.linkmodes);
|
||||
|
||||
verbose("(im871a) are you there? yes %s\n", co.dongleId().c_str());
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ shared_ptr<WMBus> openRawTTY(string device, int baudrate, shared_ptr<SerialCommu
|
|||
if (serial_override)
|
||||
{
|
||||
WMBusRawTTY *imp = new WMBusRawTTY(serial_override, manager);
|
||||
imp->markAsNoLongerSerial();
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), baudrate, "rawtty");
|
||||
|
@ -68,7 +69,7 @@ shared_ptr<WMBus> openRawTTY(string device, int baudrate, shared_ptr<SerialCommu
|
|||
}
|
||||
|
||||
WMBusRawTTY::WMBusRawTTY(shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager) :
|
||||
WMBusCommonImplementation(DEVICE_RAWTTY, manager, serial)
|
||||
WMBusCommonImplementation(DEVICE_RAWTTY, manager, serial, true)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
@ -158,7 +159,8 @@ AccessCheck detectRAWTTY(Detected *detected, shared_ptr<SerialCommunicationManag
|
|||
|
||||
serial->close();
|
||||
|
||||
detected->setAsFound("", WMBusDeviceType::DEVICE_RAWTTY, bps, false, false);
|
||||
detected->setAsFound("", WMBusDeviceType::DEVICE_RAWTTY, bps, false, false,
|
||||
detected->specified_device.linkmodes);
|
||||
|
||||
return AccessCheck::AccessOK;
|
||||
}
|
||||
|
|
|
@ -131,11 +131,11 @@ struct WMBusRC1180 : public virtual WMBusCommonImplementation
|
|||
int numConcurrentLinkModes() { return 1; }
|
||||
bool canSetLinkModes(LinkModeSet lms)
|
||||
{
|
||||
if (0 == countSetBits(lms.bits())) return false;
|
||||
if (lms.empty()) return false;
|
||||
if (!supportedLinkModes().supports(lms)) return false;
|
||||
// Ok, the supplied link modes are compatible,
|
||||
// but rc1180 can only listen to one at a time.
|
||||
return 1 == countSetBits(lms.bits());
|
||||
return 1 == countSetBits(lms.asBits());
|
||||
}
|
||||
void processSerialData();
|
||||
void simulate();
|
||||
|
@ -168,6 +168,7 @@ shared_ptr<WMBus> openRC1180(string device, shared_ptr<SerialCommunicationManage
|
|||
if (serial_override)
|
||||
{
|
||||
WMBusRC1180 *imp = new WMBusRC1180(serial_override, manager);
|
||||
imp->markAsNoLongerSerial();
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
||||
|
@ -177,7 +178,7 @@ shared_ptr<WMBus> openRC1180(string device, shared_ptr<SerialCommunicationManage
|
|||
}
|
||||
|
||||
WMBusRC1180::WMBusRC1180(shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager) :
|
||||
WMBusCommonImplementation(DEVICE_RC1180, manager, serial)
|
||||
WMBusCommonImplementation(DEVICE_RC1180, manager, serial, true)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
@ -384,6 +385,22 @@ AccessCheck detectRC1180(Detected *detected, shared_ptr<SerialCommunicationManag
|
|||
|
||||
debug("(rc1180) config: %s\n", co.str().c_str());
|
||||
|
||||
/*
|
||||
Modification of the non-volatile memory should be done using the
|
||||
wmbusmeters-admin program. So this code should not execute here.
|
||||
if (co.rssi_mode == 0)
|
||||
{
|
||||
// Change the config so that the device appends an rssi byte.
|
||||
vector<uchar> updat(4);
|
||||
update[0] = 'M';
|
||||
update[1] = 0x05; // Register 5, rssi_mode
|
||||
update[2] = 1; // Set value to 1 = enabled.
|
||||
update[3] = 0xff; // Stop modifying memory.
|
||||
serial->send(update);
|
||||
usleep(1000*200);
|
||||
// Reboot dongle.
|
||||
}
|
||||
*/
|
||||
// Now exit config mode and continue listeing.
|
||||
msg[0] = 'X';
|
||||
serial->send(msg);
|
||||
|
@ -392,7 +409,8 @@ AccessCheck detectRC1180(Detected *detected, shared_ptr<SerialCommunicationManag
|
|||
|
||||
serial->close();
|
||||
|
||||
detected->setAsFound(co.dongleId(), WMBusDeviceType::DEVICE_RC1180, 19200, false, false);
|
||||
detected->setAsFound(co.dongleId(), WMBusDeviceType::DEVICE_RC1180, 19200, false, false,
|
||||
detected->specified_device.linkmodes);
|
||||
|
||||
verbose("(rc1180) are you there? yes %s\n", co.dongleId().c_str());
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ shared_ptr<WMBus> openRTL433(string identifier, string command, shared_ptr<Seria
|
|||
}
|
||||
|
||||
WMBusRTL433::WMBusRTL433(shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager) :
|
||||
WMBusCommonImplementation(DEVICE_RTL433, manager, serial)
|
||||
WMBusCommonImplementation(DEVICE_RTL433, manager, serial, false)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
@ -305,7 +305,8 @@ FrameStatus WMBusRTL433::checkRTL433Frame(vector<uchar> &data,
|
|||
|
||||
AccessCheck detectRTL433(Detected *detected, shared_ptr<SerialCommunicationManager> handler)
|
||||
{
|
||||
detected->setAsFound("", WMBusDeviceType::DEVICE_RTLWMBUS, 0, false, false);
|
||||
detected->setAsFound("", WMBusDeviceType::DEVICE_RTL433, 0, false, false,
|
||||
detected->specified_device.linkmodes);
|
||||
|
||||
return AccessCheck::AccessOK;
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ shared_ptr<WMBus> openRTLWMBUS(string serialnr, string command, shared_ptr<Seria
|
|||
}
|
||||
|
||||
WMBusRTLWMBUS::WMBusRTLWMBUS(string serialnr, shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager) :
|
||||
WMBusCommonImplementation(DEVICE_RTLWMBUS, manager, serial), serialnr_(serialnr)
|
||||
WMBusCommonImplementation(DEVICE_RTLWMBUS, manager, serial, false), serialnr_(serialnr)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ shared_ptr<WMBus> openSimulator(string device, shared_ptr<SerialCommunicationMan
|
|||
}
|
||||
|
||||
WMBusSimulator::WMBusSimulator(string file, shared_ptr<SerialCommunicationManager> manager)
|
||||
: WMBusCommonImplementation(DEVICE_SIMULATION, manager, NULL), file_(file)
|
||||
: WMBusCommonImplementation(DEVICE_SIMULATION, manager, NULL, false), file_(file)
|
||||
{
|
||||
assert(file != "");
|
||||
loadFile(file, &lines_);
|
||||
|
|
|
@ -25,7 +25,7 @@ cat /tmp/wmbusmeters_alarm_test
|
|||
echo "---------------------------------------"
|
||||
|
||||
cat > $TEST/test_expected.txt <<EOF
|
||||
(alarm DeviceInactivity) 4 seconds of inactivity resetting simulations/simulation_alarm.txt SIMULATION (timeout 4s expected mon-sun(00-23) now 1111-11-11 11:11)
|
||||
(alarm DeviceInactivity) 4 seconds of inactivity resetting simulations/simulation_alarm.txt simulation (timeout 4s expected mon-sun(00-23) now 1111-11-11 11:11)
|
||||
(wmbus) successfully reset wmbus device
|
||||
EOF
|
||||
|
||||
|
@ -35,7 +35,7 @@ METER =={"media":"cold water","meter":"multical21","name":"Water","id":"76348799
|
|||
EOF
|
||||
|
||||
cat > /tmp/wmbusmeters_alarm_expected <<EOF
|
||||
ALARM_SHELL DeviceInactivity (alarm DeviceInactivity) 4 seconds of inactivity resetting simulations/simulation_alarm.txt SIMULATION (timeout 4s expected mon-sun(00-23) now 1111-11-11 11:11)
|
||||
ALARM_SHELL DeviceInactivity (alarm DeviceInactivity) 4 seconds of inactivity resetting simulations/simulation_alarm.txt simulation (timeout 4s expected mon-sun(00-23) now 1111-11-11 11:11)
|
||||
EOF
|
||||
|
||||
cat $TEST/test_stderr.txt | sed 's/now ....-..-.. ..:../now 1111-11-11 11:11/' > $TEST/test_responses.txt
|
||||
|
|
|
@ -31,6 +31,8 @@ mqtt_publish) sent to a REST API (eg curl) or store it in a database
|
|||
|
||||
\fB\--debug\fR for a lot of information
|
||||
|
||||
\fB\--donotprobe=\fR<tty> do not auto-probe this tty. Use multiple times for several ttys or specify "all" for all ttys.
|
||||
|
||||
\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
|
||||
|
|
Ładowanie…
Reference in New Issue