Now auto detects any number rtlwmbus devices.

pull/156/head
Fredrik Öhrström 2020-10-07 21:40:33 +02:00
rodzic d8e7be70c4
commit 0c2eb722d1
23 zmienionych plików z 371 dodań i 116 usunięć

Wyświetl plik

@ -6,4 +6,4 @@ language: cpp
sudo: required
dist: bionic
before_install:
- if [ $TRAVIS_OS_NAME = linux ]; then sudo apt-get install librtlsdr-dev; else brew install librtlsdr; fi
- if [ $TRAVIS_OS_NAME = linux ]; then sudo apt-get install librtlsdr-dev libusb-dev; else brew install librtlsdr libusb; fi

Wyświetl plik

@ -14,6 +14,9 @@ as soon as there is no more data.
This means that the udev rules no longer are needed and must be
removed. This will be done automatically by the install script.
** The background rtlwmbus/rtl433 command must be wrapped in CMD(...)
wmbusmeters rtlwmbus:CMD(
** Use stderr for logging, stdout for data.
wmbusmeters now uses STDERR as default for info/verbose/debug/trace output.

Wyświetl plik

@ -198,10 +198,10 @@ snapcraft:
$(BUILD)/main.o: $(BUILD)/short_manual.h $(BUILD)/version.h
$(BUILD)/wmbusmeters: $(METER_OBJS) $(BUILD)/main.o $(BUILD)/short_manual.h
$(CXX) -o $(BUILD)/wmbusmeters $(METER_OBJS) $(BUILD)/main.o $(LDFLAGS) -lrtlsdr -lpthread
$(CXX) -o $(BUILD)/wmbusmeters $(METER_OBJS) $(BUILD)/main.o $(LDFLAGS) -lrtlsdr -lusb-1.0 -lpthread
$(BUILD)/wmbusmeters-admin: $(METER_OBJS) $(BUILD)/admin.o $(BUILD)/ui.o $(BUILD)/short_manual.h
$(CXX) -o $(BUILD)/wmbusmeters-admin $(METER_OBJS) $(BUILD)/admin.o $(BUILD)/ui.o $(LDFLAGS) -lmenu -lform -lncurses -lrtlsdr -lpthread
$(CXX) -o $(BUILD)/wmbusmeters-admin $(METER_OBJS) $(BUILD)/admin.o $(BUILD)/ui.o $(LDFLAGS) -lmenu -lform -lncurses -lrtlsdr -lusb-1.0 -lpthread
$(BUILD)/short_manual.h: README.md
echo 'R"MANUAL(' > $(BUILD)/short_manual.h
@ -211,7 +211,7 @@ $(BUILD)/short_manual.h: README.md
echo ')MANUAL";' >> $(BUILD)/short_manual.h
$(BUILD)/testinternals: $(METER_OBJS) $(BUILD)/testinternals.o
$(CXX) -o $(BUILD)/testinternals $(METER_OBJS) $(BUILD)/testinternals.o $(LDFLAGS) -lrtlsdr -lpthread
$(CXX) -o $(BUILD)/testinternals $(METER_OBJS) $(BUILD)/testinternals.o $(LDFLAGS) -lrtlsdr -lusb-1.0 -lpthread
$(BUILD)/fuzz: $(METER_OBJS) $(BUILD)/fuzz.o
$(CXX) -o $(BUILD)/fuzz $(METER_OBJS) $(BUILD)/fuzz.o $(LDFLAGS) -lrtlsdr -lpthread

53
configure vendored
Wyświetl plik

@ -1915,9 +1915,6 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rtlsdr" >&5
$as_echo_n "checking for rtlsdr... " >&6; }
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@ -2426,6 +2423,56 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for usb_init in -lusb" >&5
$as_echo_n "checking for usb_init in -lusb... " >&6; }
if ${ac_cv_lib_usb_usb_init+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lusb $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char usb_init ();
int
main ()
{
return usb_init ();
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"; then :
ac_cv_lib_usb_usb_init=yes
else
ac_cv_lib_usb_usb_init=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usb_usb_init" >&5
$as_echo "$ac_cv_lib_usb_usb_init" >&6; }
if test "x$ac_cv_lib_usb_usb_init" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBUSB 1
_ACEOF
LIBS="-lusb $LIBS"
else
as_fn_error $? "Could not find libusb library. Try: sudo apt install libusb-dev" "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rtlsdr_get_device_count in -lrtlsdr" >&5
$as_echo_n "checking for rtlsdr_get_device_count in -lrtlsdr... " >&6; }
if ${ac_cv_lib_rtlsdr_rtlsdr_get_device_count+:} false; then :

Wyświetl plik

@ -31,7 +31,10 @@ mkdir -p "$OUTPUT_ROOT"
AC_LANG_PUSH([C++])
AC_MSG_CHECKING([for rtlsdr])
AC_CHECK_LIB(usb, usb_init, [],
[
AC_MSG_ERROR([Could not find libusb library. Try: sudo apt install libusb-dev])
])
AC_CHECK_LIB(rtlsdr, rtlsdr_get_device_count, [],
[

Wyświetl plik

@ -211,6 +211,9 @@ bool handleDevice(Configuration *c, string devicefile)
bool ok = specified_device.parse(devicefile);
if (ok)
{
// Number the devices
specified_device.index = c->supplied_wmbus_devices.size();
if (specified_device.linkmodes != "")
{
// Prevent an early warning in start
@ -236,6 +239,22 @@ bool handleDevice(Configuration *c, string devicefile)
}
}
if (specified_device.is_stdin ||
specified_device.is_file ||
specified_device.is_simulation ||
specified_device.command != "")
{
if (c->single_device_override)
{
error("You can only specify one stdin or one file or one command!\n");
}
if (c->use_auto_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")
{
c->use_auto_detect = true;

Wyświetl plik

@ -86,6 +86,8 @@ struct Configuration
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 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.
string telegram_reader;

Wyświetl plik

@ -56,7 +56,7 @@ void list_shell_envs(Configuration *config, string meter_type);
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, string device, Detected *detected);
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);
@ -225,12 +225,20 @@ void check_for_dead_wmbus_devices(Configuration *config)
trace("[MAIN] checking for dead wmbus devices...\n");
bool found_dead_rtlwmbus = false;
vector<WMBus*> not_working;
for (auto &w : wmbus_devices_)
{
if (!w->isWorking())
{
not_working.push_back(w.get());
if ((w->type() == DEVICE_RTLWMBUS || w->type() == DEVICE_RTL433)
&& !w->serialOverride())
{
found_dead_rtlwmbus = true;
}
string id = w->getDeviceId();
if (id != "") id = "["+id+"]";
@ -241,6 +249,32 @@ void check_for_dead_wmbus_devices(Configuration *config)
}
}
if (found_dead_rtlwmbus)
{
// Ok, unfortunately the device ids returned by librtlsdr
// are reshuffled when rtlsdr devices are unplugged!
// So we close all rtlwmbus devices (not overriden)
// and re-init them if an rtlwmbus device is lost.
for (auto &w : wmbus_devices_)
{
if (w->isWorking()
&& (w->type() == DEVICE_RTLWMBUS || w->type() == DEVICE_RTL433)
&& !w->serialOverride())
{
not_working.push_back(w.get());
string id = w->getDeviceId();
if (id != "") id = "["+id+"]";
notice("Force closing %s %s%s\n",
w->device().c_str(),
toLowerCaseString(w->type()),
id.c_str());
w->close();
}
}
}
for (auto w : not_working)
{
auto i = wmbus_devices_.begin();
@ -258,11 +292,23 @@ void check_for_dead_wmbus_devices(Configuration *config)
if (wmbus_devices_.size() == 0)
{
if (!printed_warning_)
if (config->single_device_override)
{
info("No wmbus device detected, waiting for a device to be plugged in.\n");
check_if_multiple_wmbus_meters_running();
printed_warning_ = true;
if (!config->simulation_found)
{
// Expect stdin/file to work.
// Simulation is special since it will self stop the serial manager.
serial_manager_->expectDevicesToWork();
}
}
else
{
if (!printed_warning_)
{
info("No wmbus device detected, waiting for a device to be plugged in.\n");
check_if_multiple_wmbus_meters_running();
printed_warning_ = true;
}
}
}
else
@ -330,17 +376,18 @@ shared_ptr<WMBus> create_wmbus_object(Detected *detected, Configuration *config,
case DEVICE_RTLWMBUS:
{
string command;
string name = "";
string identifier = detected->found_file;
int id = 0;
if (!detected->found_tty_override)
{
name = detected->found_file;
id = indexFromRtlSdrName(name);
id = indexFromRtlSdrName(identifier);
command = "";
if (detected->specified_device.command != "")
if (detected->found_command != "")
{
command = detected->specified_device.command;
command = detected->found_command;
identifier = "cmd_"+to_string(detected->specified_device.index);
}
string freq = "868.95M";
if (detected->specified_device.fq != "")
@ -369,7 +416,7 @@ shared_ptr<WMBus> create_wmbus_object(Detected *detected, Configuration *config,
}
verbose("(rtlwmbus) using command: %s\n", command.c_str());
}
wmbus = openRTLWMBUS(name, command, manager,
wmbus = openRTLWMBUS(identifier, command, manager,
[command](){
warning("(rtlwmbus) child process exited! "
"Command was: \"%s\"\n", command.c_str());
@ -380,12 +427,16 @@ shared_ptr<WMBus> create_wmbus_object(Detected *detected, Configuration *config,
case DEVICE_RTL433:
{
string command;
string identifier = detected->found_file;
int id = 0;
if (!detected->found_tty_override)
{
id = indexFromRtlSdrName(identifier);
command = "";
if (detected->specified_device.command != "")
{
command = detected->specified_device.command;
identifier = "cmd_"+to_string(detected->specified_device.index);
}
string freq = "868.95M";
if (detected->specified_device.fq != "")
@ -405,11 +456,11 @@ shared_ptr<WMBus> create_wmbus_object(Detected *detected, Configuration *config,
}
}
if (command == "") {
command = prefix+"rtl_433 -F csv -f "+freq;
command = prefix+"rtl_433 -d "+to_string(id)+" -F csv -f "+freq;
}
verbose("(rtl433) using command: %s\n", command.c_str());
}
wmbus = openRTL433("rtl433"/*detected->found_file*/, command, manager,
wmbus = openRTL433(identifier, command, manager,
[command](){
warning("(rtl433) child process exited! "
"Command was: \"%s\"\n", command.c_str());
@ -481,43 +532,66 @@ void detect_and_configure_wmbus_devices(Configuration *config)
bool must_auto_find = false;
for (SpecifiedDevice &specified_device : config->supplied_wmbus_devices)
{
if (specified_device.file == "")
specified_device.handled = false;
if (specified_device.file == "" && specified_device.command == "")
{
// File/tty not specified, use auto scan later to find actual device file/tty.
// File/tty/command not specified, use auto scan later to find actual device file/tty.
must_auto_find = true;
continue;
}
shared_ptr<SerialDevice> sd = serial_manager_->lookup(specified_device.file);
if (sd != NULL)
if (specified_device.command != "")
{
trace("(main) %s already configured\n", sd->device().c_str());
continue;
string identifier = "cmd_"+to_string(specified_device.index);
shared_ptr<SerialDevice> sd = serial_manager_->lookup(identifier);
if (sd != NULL)
{
debug("(main) command %s already configured\n", identifier.c_str());
specified_device.handled = true;
continue;
}
Detected detected = detectWMBusDeviceWithCommand(specified_device, serial_manager_);
specified_device.handled = true;
open_wmbus_device_and_set_linkmodes(config, "config", &detected);
}
if (simulation_files_.count(specified_device.file) > 0)
if (specified_device.file != "")
{
debug("(main) %s already configured as simulation\n", specified_device.file.c_str());
continue;
}
if (do_not_open_file_again_.count(specified_device.file) > 0)
{
// This was stdin/file, it should only be opened once.
trace("(MAIN) ignoring handled file %s\n", specified_device.file.c_str());
continue;
shared_ptr<SerialDevice> sd = serial_manager_->lookup(specified_device.file);
if (sd != NULL)
{
debug("(main) %s already configured\n", sd->device().c_str());
specified_device.handled = true;
continue;
}
if (simulation_files_.count(specified_device.file) > 0)
{
debug("(main) %s already configured as simulation\n", specified_device.file.c_str());
specified_device.handled = true;
continue;
}
if (do_not_open_file_again_.count(specified_device.file) > 0)
{
// This was stdin/file, it should only be opened once.
debug("(MAIN) ignoring handled file %s\n", specified_device.file.c_str());
specified_device.handled = true;
continue;
}
Detected detected = detectWMBusDeviceWithFile(specified_device, serial_manager_);
if (detected.found_type == DEVICE_UNKNOWN)
{
warning("Warning! Unknown device %s\n", specified_device.str().c_str());
}
if (detected.specified_device.is_stdin || detected.specified_device.is_file || detected.specified_device.is_simulation)
{
// Only read stdin and files once!
do_not_open_file_again_.insert(specified_device.file);
}
open_wmbus_device_and_set_linkmodes(config, "config", &detected);
}
Detected detected = detectWMBusDeviceWithFile(specified_device, serial_manager_);
if (detected.found_type == DEVICE_UNKNOWN)
{
warning("Warning! Unknown device %s\n", specified_device.str().c_str());
}
if (detected.specified_device.is_stdin || detected.specified_device.is_file || detected.specified_device.is_simulation)
{
// Only read stdin and files once!
do_not_open_file_again_.insert(specified_device.file);
}
open_wmbus_device_and_set_linkmodes(config, "config", specified_device.file, &detected);
specified_device.handled = true;
}
@ -530,7 +604,14 @@ void detect_and_configure_wmbus_devices(Configuration *config)
{
if (!specified_device.handled)
{
logAlarm("device_not_found", specified_device.str());
time_t last_alarm = specified_device.last_alarm;
time_t now = time(NULL);
if (now - last_alarm > 10)
{
specified_device.last_alarm = now;
logAlarm("device_not_found", specified_device.str());
}
}
}
}
@ -659,7 +740,7 @@ void oneshot_check(Configuration *config, Telegram *t, Meter *meter)
}
}
void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, string device, Detected *detected)
void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, Detected *detected)
{
LOCK_WMBUS_DEVICES(open_wmbus_device);
@ -694,13 +775,24 @@ void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, stri
string id = detected->found_device_id.c_str();
if (id != "") id = "["+id+"]";
string fq = detected->specified_device.fq;
if (fq != "") fq = " using fq "+fq;
string file = detected->found_file.c_str();
if (file != "") file = " on "+file;
string cmd = detected->found_command.c_str();
if (cmd != "")
{
cmd = " using CMD("+cmd+")";
}
string started = tostrprintf("Started %s %s%s on %s listening on %s\n",
string started = tostrprintf("Started %s %s%s%s listening on %s%s%s\n",
how.c_str(),
toLowerCaseString(detected->found_type),
id.c_str(),
device.c_str(),
using_link_modes.c_str());
file.c_str(),
using_link_modes.c_str(),
fq.c_str(),
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)
@ -723,7 +815,8 @@ void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, stri
int regular_reset = 23*3600;
if (config->resetafter != 0) regular_reset = config->resetafter;
wmbus->setResetInterval(regular_reset);
verbose("(main) regular reset of %s %s will happen every %d seconds\n", toString(detected->found_type), device.c_str(), regular_reset);
verbose("(main) regular reset of %s %s%s will happen every %d seconds\n",
toString(detected->found_type), file.c_str(), cmd.c_str(), regular_reset);
wmbus->setLinkModes(lms);
/*
@ -777,7 +870,7 @@ void perform_auto_scan_of_serial_devices(Configuration *config)
// See if we had a specified device without a file,
// that matches this detected device.
find_specified_device_and_update_detected(config, &detected);
open_wmbus_device_and_set_linkmodes(config, "auto", tty, &detected);
open_wmbus_device_and_set_linkmodes(config, "auto", &detected);
}
else
{
@ -801,10 +894,10 @@ void perform_auto_scan_of_swradio_devices(Configuration *config)
for (string& name : names)
{
trace("[MAIN] rtlsdr device %s\n", name.c_str());
debug("[MAIN] rtlsdr device %s\n", name.c_str());
if (not_swradio_wmbus_devices_.count(name) > 0)
{
trace("[MAIN] skipping already probed rtlsdr %s\n", name.c_str());
debug("[MAIN] skipping already probed rtlsdr %s\n", name.c_str());
continue;
}
shared_ptr<SerialDevice> sd = serial_manager_->lookup(name);
@ -825,7 +918,7 @@ void perform_auto_scan_of_swradio_devices(Configuration *config)
// Use the name as the file.
detected.found_file = name;
find_specified_device_and_update_detected(config, &detected);
open_wmbus_device_and_set_linkmodes(config, "auto", name, &detected);
open_wmbus_device_and_set_linkmodes(config, "auto", &detected);
}
}
}
@ -989,26 +1082,10 @@ bool start(Configuration *config)
detect_and_configure_wmbus_devices(config);
if (!config->use_auto_detect)
if (wmbus_devices_.size() == 0)
{
if (simulation_files_.size() == 0)
{
serial_manager_->expectDevicesToWork();
}
if (wmbus_devices_.size() == 0)
{
notice("No wmbus device configured! Exiting.\n");
check_if_multiple_wmbus_meters_running();
serial_manager_->stop();
}
}
else
{
if (wmbus_devices_.size() == 0)
{
notice("No wmbus device detected, waiting for a device to be plugged in.\n");
check_if_multiple_wmbus_meters_running();
}
notice("No wmbus device detected, waiting for a device to be plugged in.\n");
check_if_multiple_wmbus_meters_running();
}
// Every 2 seconds detect any plugged in or removed wmbus devices.

Wyświetl plik

@ -20,10 +20,47 @@
// Include rtl-sdr which is licensed under GPL v2 or later
// so it happily relicenses with wmbusmeters under GPL v3 or later.
#include<rtl-sdr.h>
// Include libusb, we do not currently make use of this,
// but the intention is to have better detection of usb
// changes in the future. Perhaps even callbacks?
#include<libusb-1.0/libusb.h>
using namespace std;
struct StaticLibUSB
{
libusb_context *ctx_;
StaticLibUSB()
{
libusb_init(&ctx_);
libusb_device **list;
ssize_t count = libusb_get_device_list(ctx_, &list);
for (ssize_t idx = 0; idx < count; ++idx)
{
libusb_device *device = list[idx];
libusb_device_descriptor desc = {0};
libusb_get_device_descriptor(device, &desc);
printf("Vendor:Device = %04x:%04x\n", desc.idVendor, desc.idProduct);
}
libusb_free_device_list(list, true);
}
~StaticLibUSB()
{
libusb_exit(ctx_);
}
};
//StaticLibUSB static_;
vector<string> listRtlSdrDevices()
{
vector<string> devices;
@ -54,7 +91,7 @@ AccessCheck detectRTLSDR(string device, Detected *detected)
// Would be nice to properly test if the device can be opened.
if (i < n)
{
detected->setAsFound("", WMBusDeviceType::DEVICE_RTLWMBUS, 0, false);
detected->setAsFound("", WMBusDeviceType::DEVICE_RTLWMBUS, 0, false, false);
return AccessCheck::AccessOK;
}

Wyświetl plik

@ -72,7 +72,7 @@ struct SerialCommunicationManagerImp : public SerialCommunicationManager
~SerialCommunicationManagerImp();
shared_ptr<SerialDevice> createSerialDeviceTTY(string dev, int baud_rate, string purpose);
shared_ptr<SerialDevice> createSerialDeviceCommand(string device, string command, vector<string> args, vector<string> envs,
shared_ptr<SerialDevice> createSerialDeviceCommand(string identifier, string command, vector<string> args, vector<string> envs,
function<void()> on_exit, string purpose);
shared_ptr<SerialDevice> createSerialDeviceFile(string file, string purpose);
shared_ptr<SerialDevice> createSerialDeviceSimulator();
@ -96,6 +96,7 @@ struct SerialCommunicationManagerImp : public SerialCommunicationManager
vector<string> listSerialTTYs();
shared_ptr<SerialDevice> lookup(std::string device);
bool removeNonWorking(std::string device);
private:
@ -949,19 +950,6 @@ void *SerialCommunicationManagerImp::eventLoop()
trace("[SERIAL] select timeout %d s\n", timeout.tv_sec);
bool num_devices = 0;
{
LOCK_SERIAL_DEVICES(cound_serial_devices);
num_devices = serial_devices_.size();
}
if (num_devices == 0 && expect_devices_to_work_)
{
debug("(serial) no working devices, stopping before entering select.\n");
stop();
break;
}
int max_fd = 0;
for (shared_ptr<SerialDevice> &sp : serial_devices_)
{
@ -1172,6 +1160,27 @@ shared_ptr<SerialDevice> SerialCommunicationManagerImp::lookup(string device)
return NULL;
}
bool SerialCommunicationManagerImp::removeNonWorking(string device)
{
LOCK_SERIAL_DEVICES(remove_non_working);
bool found_and_removed = false;
for (auto i = serial_devices_.begin(); i != serial_devices_.end(); )
{
if ((*i)->opened() && !(*i)->working() && (*i)->device() == device)
{
i = serial_devices_.erase(i);
found_and_removed = true;
}
else
{
i++;
}
}
return found_and_removed;
}
#if defined(__APPLE__)
vector<string> SerialCommunicationManagerImp::listSerialTTYs()

Wyświetl plik

@ -103,6 +103,8 @@ struct SerialCommunicationManager
virtual std::vector<std::string> listSerialTTYs() = 0;
// Return a serial device for the given device, if it exists! Otherwise NULL.
virtual std::shared_ptr<SerialDevice> lookup(std::string device) = 0;
// Remove a closed device, returns false and do not remove, if the device is still in use.
virtual bool removeNonWorking(std::string device) = 0;
virtual ~SerialCommunicationManager();
};

Wyświetl plik

@ -3226,6 +3226,28 @@ LinkModeSet WMBusCommonImplementation::protectedGetLinkModes()
return link_modes_;
}
void WMBusCommonImplementation::deviceClose()
{
}
void WMBusCommonImplementation::close()
{
debug("(wmbus) closing....\n");
if (serial())
{
if (serial()->opened() && serial()->working())
{
debug("(wmbus) yes closing....\n");
serial()->close();
manager_->removeNonWorking(serial()->device());
serial_ = NULL;
}
}
// Invoke any other device specific close for this device.
deviceClose();
}
bool WMBusCommonImplementation::reset()
{
last_reset_ = time(NULL);
@ -4021,7 +4043,7 @@ bool SpecifiedDevice::parse(string &arg)
// It cannot occur in type,fq or bps.
vector<string> parts = splitString(arg, ':');
// Most maxed out device spec:
// Most maxed out device spec, though not valid, since file+cmd is not allowed.
// Example /dev/ttyUSB0:im871a(12345678):9600:868.95M:c1,t1:CMD(rtl_433 -F csv -f 123M)
// file type id bps fq linkmodes command
@ -4085,7 +4107,8 @@ bool SpecifiedDevice::parse(string &arg)
// Auto is only allowed to be combined with linkmodes and/or frequencies!
if (type == "auto" && (file != "" || bps != "")) return false;
// You cannot combine a file with a command.
if (file != "" && command != "") return false;
return true;
}
@ -4139,7 +4162,8 @@ Detected detectWMBusDeviceWithFile(SpecifiedDevice &specified_device,
shared_ptr<SerialCommunicationManager> handler)
{
assert(specified_device.file != "");
debug("(lookup) \"%s\"\n", specified_device.str().c_str());
assert(specified_device.command == "");
debug("(lookup) with file \"%s\"\n", specified_device.str().c_str());
Detected detected;
detected.found_file = specified_device.file;
@ -4148,7 +4172,7 @@ Detected detectWMBusDeviceWithFile(SpecifiedDevice &specified_device,
if (specified_device.is_simulation)
{
debug("(lookup) driver: simulation file\n");
detected.setAsFound("", DEVICE_SIMULATION, 0 , false);
detected.setAsFound("", DEVICE_SIMULATION, 0 , false, false);
specified_device.linkmodes = "any";
return detected;
}
@ -4157,7 +4181,7 @@ Detected detectWMBusDeviceWithFile(SpecifiedDevice &specified_device,
if (specified_device.type == "" && specified_device.bps != "" && specified_device.is_tty)
{
debug("(lookup) driver: rawtty\n");
detected.setAsFound("", DEVICE_RAWTTY, atoi(specified_device.bps.c_str()), false );
detected.setAsFound("", DEVICE_RAWTTY, atoi(specified_device.bps.c_str()), false, false);
return detected;
}
@ -4165,7 +4189,7 @@ Detected detectWMBusDeviceWithFile(SpecifiedDevice &specified_device,
if (specified_device.type == "" && !specified_device.is_tty)
{
debug("(lookup) driver: raw file\n");
detected.setAsFound("", DEVICE_RAWTTY, 0, true );
detected.setAsFound("", DEVICE_RAWTTY, 0, true, false);
return detected;
}
@ -4173,7 +4197,7 @@ Detected detectWMBusDeviceWithFile(SpecifiedDevice &specified_device,
if (specified_device.type != "")
{
debug("(lookup) driver: %s\n", specified_device.type.c_str());
detected.setAsFound("", toWMBusDeviceType(specified_device.type), 0, true );
detected.setAsFound("", toWMBusDeviceType(specified_device.type), 0, true, false);
return detected;
}
// Ok, we are left with a single /dev/ttyUSB0 lets talk to it
@ -4181,6 +4205,21 @@ Detected detectWMBusDeviceWithFile(SpecifiedDevice &specified_device,
return detectWMBusDeviceOnTTY(specified_device.file, handler);
}
Detected detectWMBusDeviceWithCommand(SpecifiedDevice &specified_device,
shared_ptr<SerialCommunicationManager> handler)
{
assert(specified_device.file == "");
assert(specified_device.command != "");
debug("(lookup) with cmd \"%s\"\n", specified_device.str().c_str());
Detected detected;
detected.found_command = specified_device.command;
detected.setSpecifiedDevice(specified_device);
detected.setAsFound("", toWMBusDeviceType(specified_device.type), 0, false, true);
return detected;
}
AccessCheck detectUNKNOWN(Detected *detected, shared_ptr<SerialCommunicationManager> handler)
{
return AccessCheck::NotThere;

Wyświetl plik

@ -34,6 +34,7 @@ bool trimCRCsFrameFormatB(std::vector<uchar> &payload);
// 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
@ -44,6 +45,7 @@ struct SpecifiedDevice
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();
@ -82,6 +84,8 @@ struct Detected
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;
void setSpecifiedDeviceAsAuto()
{
@ -93,12 +97,13 @@ struct Detected
specified_device = sd;
}
void setAsFound(string id, WMBusDeviceType t, int b, bool to)
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()
@ -488,6 +493,8 @@ struct WMBus
virtual void setLinkModes(LinkModeSet lms) = 0;
virtual void onTelegram(function<bool(vector<uchar>)> cb) = 0;
virtual SerialDevice *serial() = 0;
// Return true of the serial has been overridden, usually with stdin or a file.
virtual bool serialOverride() = 0;
virtual void simulate() = 0;
// Return true if underlying device is ok and device in general seems to be working.
virtual bool isWorking() = 0;
@ -503,11 +510,15 @@ struct WMBus
// Set a regular interval for resetting the wmbus device.
// Default is once ever 24 hours.
virtual void setResetInterval(int seconds) = 0;
// Close this device.
virtual void close() = 0;
virtual ~WMBus() = 0;
};
Detected detectWMBusDeviceWithFile(SpecifiedDevice &specified_device,
shared_ptr<SerialCommunicationManager> manager);
Detected detectWMBusDeviceWithCommand(SpecifiedDevice &specified_device,
shared_ptr<SerialCommunicationManager> handler);
shared_ptr<WMBus> openIM871A(string device, shared_ptr<SerialCommunicationManager> manager,
@ -518,9 +529,9 @@ shared_ptr<WMBus> openRawTTY(string device, int baudrate, shared_ptr<SerialCommu
shared_ptr<SerialDevice> serial_override);
shared_ptr<WMBus> openRC1180(string device, shared_ptr<SerialCommunicationManager> manager,
shared_ptr<SerialDevice> serial_override);
shared_ptr<WMBus> openRTLWMBUS(string device, string command, shared_ptr<SerialCommunicationManager> manager, std::function<void()> on_exit,
shared_ptr<WMBus> openRTLWMBUS(string identifier, string command, shared_ptr<SerialCommunicationManager> manager, std::function<void()> on_exit,
shared_ptr<SerialDevice> serial_override);
shared_ptr<WMBus> openRTL433(string device, string command, shared_ptr<SerialCommunicationManager> manager, std::function<void()> on_exit,
shared_ptr<WMBus> openRTL433(string identifier, string command, shared_ptr<SerialCommunicationManager> manager, std::function<void()> on_exit,
shared_ptr<SerialDevice> serial_override);
shared_ptr<WMBus> openCUL(string device, shared_ptr<SerialCommunicationManager> manager,
shared_ptr<SerialDevice> serial_override);

Wyświetl plik

@ -548,7 +548,7 @@ AccessCheck detectAMB8465(Detected *detected, shared_ptr<SerialCommunicationMana
string id = tostrprintf("%08x", idv);
detected->setAsFound(id, WMBusDeviceType::DEVICE_AMB8465, 9600, false);
detected->setAsFound(id, WMBusDeviceType::DEVICE_AMB8465, 9600, false, false);
verbose("(amb8465) are you there? yes %08x\n", idv);

Wyświetl plik

@ -383,7 +383,7 @@ AccessCheck detectCUL(Detected *detected, shared_ptr<SerialCommunicationManager>
serial->close();
detected->setAsFound("12345678", WMBusDeviceType::DEVICE_CUL, 38400, false);
detected->setAsFound("12345678", WMBusDeviceType::DEVICE_CUL, 38400, false, false);
return AccessCheck::AccessOK;
}

Wyświetl plik

@ -222,7 +222,7 @@ AccessCheck detectD1TC(Detected *detected, shared_ptr<SerialCommunicationManager
serial->close();
detected->setAsFound("", WMBusDeviceType::DEVICE_D1TC, bps, false);
detected->setAsFound("", WMBusDeviceType::DEVICE_D1TC, bps, false, false);
return AccessCheck::AccessOK;
}

Wyświetl plik

@ -869,7 +869,7 @@ 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);
detected->setAsFound(co.dongleId(), WMBusDeviceType::DEVICE_IM871A, 57600, false, false);
verbose("(im871a) are you there? yes %08x\n", co.dongleId());

Wyświetl plik

@ -150,7 +150,7 @@ AccessCheck detectRAWTTY(Detected *detected, shared_ptr<SerialCommunicationManag
serial->close();
detected->setAsFound("", WMBusDeviceType::DEVICE_RAWTTY, bps, false);
detected->setAsFound("", WMBusDeviceType::DEVICE_RAWTTY, bps, false, false);
return AccessCheck::AccessOK;
}

Wyświetl plik

@ -278,7 +278,7 @@ AccessCheck detectRC1180(Detected *detected, shared_ptr<SerialCommunicationManag
serial->close();
detected->setAsFound("12345678", WMBusDeviceType::DEVICE_RC1180, 19200, false);
detected->setAsFound("12345678", WMBusDeviceType::DEVICE_RC1180, 19200, false, false);
verbose("(rc1180) are you there? yes xxxxxx\n");

Wyświetl plik

@ -72,9 +72,10 @@ private:
string setup_;
};
shared_ptr<WMBus> openRTL433(string device, string command, shared_ptr<SerialCommunicationManager> manager,
shared_ptr<WMBus> openRTL433(string identifier, string command, shared_ptr<SerialCommunicationManager> manager,
function<void()> on_exit, shared_ptr<SerialDevice> serial_override)
{
assert(identifier != "");
vector<string> args;
vector<string> envs;
args.push_back("-c");
@ -84,7 +85,7 @@ shared_ptr<WMBus> openRTL433(string device, string command, shared_ptr<SerialCom
WMBusRTL433 *imp = new WMBusRTL433(serial_override, manager);
return shared_ptr<WMBus>(imp);
}
auto serial = manager->createSerialDeviceCommand(device, "/bin/sh", args, envs, on_exit, "rtl433");
auto serial = manager->createSerialDeviceCommand(identifier, "/bin/sh", args, envs, on_exit, "rtl433");
WMBusRTL433 *imp = new WMBusRTL433(serial, manager);
return shared_ptr<WMBus>(imp);
}
@ -297,7 +298,7 @@ FrameStatus WMBusRTL433::checkRTL433Frame(vector<uchar> &data,
AccessCheck detectRTL433(Detected *detected, shared_ptr<SerialCommunicationManager> handler)
{
detected->setAsFound("", WMBusDeviceType::DEVICE_RTLWMBUS, 0, false);
detected->setAsFound("", WMBusDeviceType::DEVICE_RTLWMBUS, 0, false, false);
return AccessCheck::AccessOK;
}

Wyświetl plik

@ -84,6 +84,7 @@ shared_ptr<WMBus> openRTLWMBUS(string identifier, string command, shared_ptr<Ser
if (serial_override)
{
WMBusRTLWMBUS *imp = new WMBusRTLWMBUS(serial_override, manager);
imp->markSerialAsOverriden();
return shared_ptr<WMBus>(imp);
}
auto serial = manager->createSerialDeviceCommand(identifier, "/bin/sh", args, envs, on_exit, "rtlwmbus");

Wyświetl plik

@ -45,11 +45,15 @@ struct WMBusCommonImplementation : public virtual WMBus
void disconnectedFromDevice();
bool reset();
SerialDevice *serial() { if (serial_) return serial_.get(); else return NULL; }
bool serialOverride() { return serial_override_; }
void markSerialAsOverriden() { serial_override_ = true; }
string device() { if (serial_) return serial_->device(); else return "?"; }
// Wait for a response to arrive from the device.
bool waitForResponse(int id);
// Notify the waiter that the response has arrived.
bool notifyResponseIsHere(int id);
void close();
protected:
@ -61,6 +65,7 @@ struct WMBusCommonImplementation : public virtual WMBus
virtual void deviceSetLinkModes(LinkModeSet lms) = 0;
// Device specific reset code, apart from serial->open and setLinkModes.
virtual void deviceReset() = 0;
virtual void deviceClose();
LinkModeSet protectedGetLinkModes(); // Used to read private link_modes_ in subclass.
private:
@ -93,7 +98,7 @@ protected:
// while the command_mutex_ is taken.
int waiting_for_response_id_ {};
Semaphore waiting_for_response_sem_;
bool serial_override_ {};
};
#endif

Wyświetl plik

@ -75,9 +75,8 @@ if [ "$?" != "0" ]; then RC="1"; fi
tests/test_additional_json.sh $PROG
if [ "$?" != "0" ]; then RC="1"; fi
#TODO not working right now
#tests/test_rtlwmbus.sh $PROG
#if [ "$?" != "0" ]; then RC="1"; fi
tests/test_rtlwmbus.sh $PROG
if [ "$?" != "0" ]; then RC="1"; fi
tests/test_stdin_and_file.sh $PROG
if [ "$?" != "0" ]; then RC="1"; fi