kopia lustrzana https://github.com/weetmuts/wmbusmeters
Added mbus rawtty driver.
rodzic
448bbcfcf2
commit
658f283f2e
1
Makefile
1
Makefile
|
@ -117,6 +117,7 @@ METER_OBJS:=\
|
||||||
$(BUILD)/cmdline.o \
|
$(BUILD)/cmdline.o \
|
||||||
$(BUILD)/config.o \
|
$(BUILD)/config.o \
|
||||||
$(BUILD)/dvparser.o \
|
$(BUILD)/dvparser.o \
|
||||||
|
$(BUILD)/mbus_rawtty.o \
|
||||||
$(BUILD)/meters.o \
|
$(BUILD)/meters.o \
|
||||||
$(BUILD)/meter_amiplus.o \
|
$(BUILD)/meter_amiplus.o \
|
||||||
$(BUILD)/meter_apator08.o \
|
$(BUILD)/meter_apator08.o \
|
||||||
|
|
|
@ -508,13 +508,13 @@ shared_ptr<Configuration> parseCommandLine(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (c->supplied_wmbus_devices.size() == 0 &&
|
if (c->supplied_bus_devices.size() == 0 &&
|
||||||
c->use_auto_device_detect == false &&
|
c->use_auto_device_detect == false &&
|
||||||
!c->list_shell_envs &&
|
!c->list_shell_envs &&
|
||||||
!c->list_fields &&
|
!c->list_fields &&
|
||||||
!c->list_meters)
|
!c->list_meters)
|
||||||
{
|
{
|
||||||
error("You must supply at least one device (eg auto:c1) to receive wmbus telegrams.\n");
|
error("You must supply at least one device to communicate using (w)mbus.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((argc-i) % 4 != 0) {
|
if ((argc-i) % 4 != 0) {
|
||||||
|
@ -522,7 +522,8 @@ shared_ptr<Configuration> parseCommandLine(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
int num_meters = (argc-i)/4;
|
int num_meters = (argc-i)/4;
|
||||||
|
|
||||||
for (int m=0; m<num_meters; ++m) {
|
for (int m=0; m<num_meters; ++m)
|
||||||
|
{
|
||||||
string name = argv[m*4+i+0];
|
string name = argv[m*4+i+0];
|
||||||
string type = argv[m*4+i+1];
|
string type = argv[m*4+i+1];
|
||||||
string id = argv[m*4+i+2];
|
string id = argv[m*4+i+2];
|
||||||
|
|
|
@ -238,10 +238,18 @@ bool handleDevice(Configuration *c, string devicefile)
|
||||||
error("Not a valid device \"%s\"\n", devicefile.c_str());
|
error("Not a valid device \"%s\"\n", devicefile.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok)
|
if (!ok) return false;
|
||||||
{
|
|
||||||
// Number the devices
|
// Number the devices
|
||||||
specified_device.index = c->supplied_wmbus_devices.size();
|
specified_device.index = c->supplied_bus_devices.size();
|
||||||
|
|
||||||
|
if (specified_device.type == WMBusDeviceType::DEVICE_MBUS)
|
||||||
|
{
|
||||||
|
if (!specified_device.linkmodes.empty())
|
||||||
|
{
|
||||||
|
error("An mbus device must not have linkmode set. \"%s\"\n", devicefile.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (specified_device.linkmodes.empty())
|
if (specified_device.linkmodes.empty())
|
||||||
{
|
{
|
||||||
|
@ -291,10 +299,18 @@ bool handleDevice(Configuration *c, string devicefile)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
c->supplied_wmbus_devices.push_back(specified_device);
|
c->supplied_bus_devices.push_back(specified_device);
|
||||||
|
if (specified_device.type == WMBusDeviceType::DEVICE_MBUS)
|
||||||
|
{
|
||||||
|
c->num_mbus_devices++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c->num_wmbus_devices++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ok;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handleDoNotProbe(Configuration *c, string devicefile)
|
bool handleDoNotProbe(Configuration *c, string devicefile)
|
||||||
|
@ -587,7 +603,7 @@ shared_ptr<Configuration> loadConfiguration(string root, string device_override,
|
||||||
// There is an override, therefore we
|
// There is an override, therefore we
|
||||||
// drop any already loaded devices from the config file.
|
// drop any already loaded devices from the config file.
|
||||||
c->use_auto_device_detect = false;
|
c->use_auto_device_detect = false;
|
||||||
c->supplied_wmbus_devices.clear();
|
c->supplied_bus_devices.clear();
|
||||||
|
|
||||||
if (startsWith(device_override, "/dev/rtlsdr"))
|
if (startsWith(device_override, "/dev/rtlsdr"))
|
||||||
{
|
{
|
||||||
|
|
|
@ -87,7 +87,9 @@ struct Configuration
|
||||||
int exitafter {}; // Seconds to exit.
|
int exitafter {}; // Seconds to exit.
|
||||||
bool nodeviceexit {}; // If no wmbus receiver device is found, then exit immediately!
|
bool nodeviceexit {}; // If no wmbus receiver device is found, then exit immediately!
|
||||||
int resetafter {}; // Reset the wmbus devices regularly.
|
int resetafter {}; // Reset the wmbus devices regularly.
|
||||||
std::vector<SpecifiedDevice> supplied_wmbus_devices; // /dev/ttyUSB0, simulation.txt, rtlwmbus, /dev/ttyUSB1:9600
|
std::vector<SpecifiedDevice> supplied_bus_devices; // /dev/ttyUSB0, simulation.txt, rtlwmbus, /dev/ttyUSB1:9600 /dev/ttyUSB2:mbus
|
||||||
|
int num_wmbus_devices {};
|
||||||
|
int num_mbus_devices {};
|
||||||
bool use_auto_device_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.
|
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
|
LinkModeSet auto_device_linkmodes; // The linkmodes specified by auto:c1,t1
|
||||||
|
|
99
src/main.cc
99
src/main.cc
|
@ -59,7 +59,7 @@ void list_shell_envs(Configuration *config, string meter_type);
|
||||||
void list_meters(Configuration *config);
|
void list_meters(Configuration *config);
|
||||||
void log_start_information(Configuration *config);
|
void log_start_information(Configuration *config);
|
||||||
void oneshot_check(Configuration *config, Telegram *t, Meter *meter);
|
void oneshot_check(Configuration *config, Telegram *t, Meter *meter);
|
||||||
void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, Detected *detected);
|
void open_bus_device_and_potentially_set_linkmodes(Configuration *config, string how, Detected *detected);
|
||||||
void perform_auto_scan_of_serial_devices(Configuration *config);
|
void perform_auto_scan_of_serial_devices(Configuration *config);
|
||||||
void perform_auto_scan_of_swradio_devices(Configuration *config);
|
void perform_auto_scan_of_swradio_devices(Configuration *config);
|
||||||
void regular_checkup(Configuration *config);
|
void regular_checkup(Configuration *config);
|
||||||
|
@ -84,9 +84,9 @@ shared_ptr<MeterManager> meter_manager_;
|
||||||
|
|
||||||
// Current active set of wmbus devices that can receive telegrams.
|
// Current active set of wmbus devices that can receive telegrams.
|
||||||
// This can change during runtime, plugging/unplugging wmbus dongles.
|
// This can change during runtime, plugging/unplugging wmbus dongles.
|
||||||
vector<shared_ptr<WMBus>> wmbus_devices_;
|
vector<shared_ptr<WMBus>> bus_devices_;
|
||||||
RecursiveMutex wmbus_devices_mutex_("wmbus_devices_mutex");
|
RecursiveMutex bus_devices_mutex_("bus_devices_mutex");
|
||||||
#define LOCK_WMBUS_DEVICES(where) WITH(wmbus_devices_mutex_, where)
|
#define LOCK_BUS_DEVICES(where) WITH(bus_devices_mutex_, where)
|
||||||
|
|
||||||
// Remember devices that were not detected as wmbus devices.
|
// Remember devices that were not detected as wmbus devices.
|
||||||
// To avoid probing them again and again.
|
// To avoid probing them again and again.
|
||||||
|
@ -227,12 +227,12 @@ void check_if_multiple_wmbus_meters_running()
|
||||||
|
|
||||||
void check_for_dead_wmbus_devices(Configuration *config)
|
void check_for_dead_wmbus_devices(Configuration *config)
|
||||||
{
|
{
|
||||||
LOCK_WMBUS_DEVICES(check_for_wmbus_devices);
|
LOCK_BUS_DEVICES(check_for_bus_devices);
|
||||||
|
|
||||||
trace("[MAIN] checking for dead wmbus devices...\n");
|
trace("[MAIN] checking for dead wmbus devices...\n");
|
||||||
|
|
||||||
vector<WMBus*> not_working;
|
vector<WMBus*> not_working;
|
||||||
for (auto &w : wmbus_devices_)
|
for (auto &w : bus_devices_)
|
||||||
{
|
{
|
||||||
if (!w->isWorking())
|
if (!w->isWorking())
|
||||||
{
|
{
|
||||||
|
@ -252,20 +252,20 @@ void check_for_dead_wmbus_devices(Configuration *config)
|
||||||
|
|
||||||
for (auto w : not_working)
|
for (auto w : not_working)
|
||||||
{
|
{
|
||||||
auto i = wmbus_devices_.begin();
|
auto i = bus_devices_.begin();
|
||||||
while (i != wmbus_devices_.end())
|
while (i != bus_devices_.end())
|
||||||
{
|
{
|
||||||
if (w == (*i).get())
|
if (w == (*i).get())
|
||||||
{
|
{
|
||||||
// The erased shared_ptr will delete the WMBus object.
|
// The erased shared_ptr will delete the WMBus object.
|
||||||
wmbus_devices_.erase(i);
|
bus_devices_.erase(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wmbus_devices_.size() == 0)
|
if (bus_devices_.size() == 0)
|
||||||
{
|
{
|
||||||
if (config->single_device_override)
|
if (config->single_device_override)
|
||||||
{
|
{
|
||||||
|
@ -349,6 +349,10 @@ shared_ptr<WMBus> create_wmbus_object(Detected *detected, Configuration *config,
|
||||||
assert(0);
|
assert(0);
|
||||||
error("Internal error DEVICE_AUTO should not be used here!\n");
|
error("Internal error DEVICE_AUTO should not be used here!\n");
|
||||||
break;
|
break;
|
||||||
|
case DEVICE_MBUS:
|
||||||
|
verbose("(mbus) on %s\n", detected->found_file.c_str());
|
||||||
|
wmbus = openMBUS(detected->found_file, detected->found_bps, manager, serial_override);
|
||||||
|
break;
|
||||||
case DEVICE_IM871A:
|
case DEVICE_IM871A:
|
||||||
verbose("(im871a) on %s\n", detected->found_file.c_str());
|
verbose("(im871a) on %s\n", detected->found_file.c_str());
|
||||||
wmbus = openIM871A(detected->found_file, manager, serial_override);
|
wmbus = openIM871A(detected->found_file, manager, serial_override);
|
||||||
|
@ -520,7 +524,7 @@ void detect_and_configure_wmbus_devices(Configuration *config, DetectionType dt)
|
||||||
must_auto_find_rtlsdrs = true;
|
must_auto_find_rtlsdrs = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SpecifiedDevice &specified_device : config->supplied_wmbus_devices)
|
for (SpecifiedDevice &specified_device : config->supplied_bus_devices)
|
||||||
{
|
{
|
||||||
specified_device.handled = false;
|
specified_device.handled = false;
|
||||||
if (dt != DetectionType::ALL)
|
if (dt != DetectionType::ALL)
|
||||||
|
@ -551,7 +555,7 @@ void detect_and_configure_wmbus_devices(Configuration *config, DetectionType dt)
|
||||||
}
|
}
|
||||||
Detected detected = detectWMBusDeviceWithCommand(specified_device, config->default_device_linkmodes, serial_manager_);
|
Detected detected = detectWMBusDeviceWithCommand(specified_device, config->default_device_linkmodes, serial_manager_);
|
||||||
specified_device.handled = true;
|
specified_device.handled = true;
|
||||||
open_wmbus_device_and_set_linkmodes(config, "config", &detected);
|
open_bus_device_and_potentially_set_linkmodes(config, "config", &detected);
|
||||||
}
|
}
|
||||||
if (specified_device.file != "")
|
if (specified_device.file != "")
|
||||||
{
|
{
|
||||||
|
@ -615,7 +619,7 @@ void detect_and_configure_wmbus_devices(Configuration *config, DetectionType dt)
|
||||||
// Only read stdin and files once!
|
// Only read stdin and files once!
|
||||||
do_not_open_file_again_.insert(specified_device.file);
|
do_not_open_file_again_.insert(specified_device.file);
|
||||||
}
|
}
|
||||||
open_wmbus_device_and_set_linkmodes(config, "config", &detected);
|
open_bus_device_and_potentially_set_linkmodes(config, "config", &detected);
|
||||||
}
|
}
|
||||||
|
|
||||||
specified_device.handled = true;
|
specified_device.handled = true;
|
||||||
|
@ -631,13 +635,13 @@ void detect_and_configure_wmbus_devices(Configuration *config, DetectionType dt)
|
||||||
perform_auto_scan_of_swradio_devices(config);
|
perform_auto_scan_of_swradio_devices(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (shared_ptr<WMBus> &wmbus : wmbus_devices_)
|
for (shared_ptr<WMBus> &wmbus : bus_devices_)
|
||||||
{
|
{
|
||||||
assert(wmbus->getDetected() != NULL);
|
assert(wmbus->getDetected() != NULL);
|
||||||
find_specified_device_and_mark_as_handled(config, wmbus->getDetected());
|
find_specified_device_and_mark_as_handled(config, wmbus->getDetected());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SpecifiedDevice &specified_device : config->supplied_wmbus_devices)
|
for (SpecifiedDevice &specified_device : config->supplied_bus_devices)
|
||||||
{
|
{
|
||||||
if (dt == DetectionType::ALL && !specified_device.handled)
|
if (dt == DetectionType::ALL && !specified_device.handled)
|
||||||
{
|
{
|
||||||
|
@ -660,7 +664,7 @@ SpecifiedDevice *find_specified_device_from_detected(Configuration *c, Detected
|
||||||
{
|
{
|
||||||
// Iterate over the supplied devices and look for an exact type+id match.
|
// Iterate over the supplied devices and look for an exact type+id match.
|
||||||
// This will find specified devices like: im871a[12345678]
|
// This will find specified devices like: im871a[12345678]
|
||||||
for (SpecifiedDevice & sd : c->supplied_wmbus_devices)
|
for (SpecifiedDevice & sd : c->supplied_bus_devices)
|
||||||
{
|
{
|
||||||
if (sd.file == "" && sd.id != "" && sd.id == d->found_device_id && sd.type == d->found_type)
|
if (sd.file == "" && sd.id != "" && sd.id == d->found_device_id && sd.type == d->found_type)
|
||||||
{
|
{
|
||||||
|
@ -670,7 +674,7 @@ SpecifiedDevice *find_specified_device_from_detected(Configuration *c, Detected
|
||||||
|
|
||||||
// Iterate over the supplied devices and look for a type match.
|
// Iterate over the supplied devices and look for a type match.
|
||||||
// This will find specified devices like: im871a, rtlwmbus
|
// This will find specified devices like: im871a, rtlwmbus
|
||||||
for (SpecifiedDevice & sd : c->supplied_wmbus_devices)
|
for (SpecifiedDevice & sd : c->supplied_bus_devices)
|
||||||
{
|
{
|
||||||
if (sd.file == "" && sd.id == "" && sd.type == d->found_type)
|
if (sd.file == "" && sd.id == "" && sd.type == d->found_type)
|
||||||
{
|
{
|
||||||
|
@ -786,7 +790,7 @@ void log_start_information(Configuration *config)
|
||||||
verbose("(config) store meter files in: \"%s\"\n", config->meterfiles_dir.c_str());
|
verbose("(config) store meter files in: \"%s\"\n", config->meterfiles_dir.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SpecifiedDevice &specified_device : config->supplied_wmbus_devices)
|
for (SpecifiedDevice &specified_device : config->supplied_bus_devices)
|
||||||
{
|
{
|
||||||
verbose("(config) using device: %s \n", specified_device.str().c_str());
|
verbose("(config) using device: %s \n", specified_device.str().c_str());
|
||||||
}
|
}
|
||||||
|
@ -805,7 +809,7 @@ void oneshot_check(Configuration *config, Telegram *t, Meter *meter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, Detected *detected)
|
void open_bus_device_and_potentially_set_linkmodes(Configuration *config, string how, Detected *detected)
|
||||||
{
|
{
|
||||||
if (detected->found_type == WMBusDeviceType::DEVICE_UNKNOWN)
|
if (detected->found_type == WMBusDeviceType::DEVICE_UNKNOWN)
|
||||||
{
|
{
|
||||||
|
@ -813,20 +817,10 @@ void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, Dete
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK_WMBUS_DEVICES(open_wmbus_device);
|
LOCK_BUS_DEVICES(open_bus_device);
|
||||||
|
|
||||||
debug("(main) opening %s\n", detected->specified_device.str().c_str());
|
debug("(main) opening %s\n", detected->specified_device.str().c_str());
|
||||||
|
|
||||||
/* if (detected->found_type == DEVICE_UNKNOWN)
|
|
||||||
{
|
|
||||||
// This is a manual config, lets detect and check the device properly.
|
|
||||||
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 = detected->specified_device.linkmodes;
|
LinkModeSet lms = detected->specified_device.linkmodes;
|
||||||
if (lms.empty())
|
if (lms.empty())
|
||||||
{
|
{
|
||||||
|
@ -853,14 +847,20 @@ void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, Dete
|
||||||
cmd = " using CMD("+cmd+")";
|
cmd = " using CMD("+cmd+")";
|
||||||
}
|
}
|
||||||
|
|
||||||
string started = tostrprintf("Started %s %s%s%s listening on %s%s%s\n",
|
string listening = "";
|
||||||
|
if (detected->found_type != WMBusDeviceType::DEVICE_MBUS)
|
||||||
|
{
|
||||||
|
listening = tostrprintf(" listening on %s%s%s",
|
||||||
|
using_link_modes.c_str(),
|
||||||
|
fq.c_str(),
|
||||||
|
cmd.c_str());
|
||||||
|
}
|
||||||
|
string started = tostrprintf("Started %s %s%s%s%s\n",
|
||||||
how.c_str(),
|
how.c_str(),
|
||||||
toLowerCaseString(detected->found_type),
|
toLowerCaseString(detected->found_type),
|
||||||
id.c_str(),
|
id.c_str(),
|
||||||
file.c_str(),
|
file.c_str(),
|
||||||
using_link_modes.c_str(),
|
listening.c_str());
|
||||||
fq.c_str(),
|
|
||||||
cmd.c_str());
|
|
||||||
|
|
||||||
// A newly plugged in device has been manually configured or automatically detected! Start using it!
|
// A newly plugged in device has been manually configured or automatically detected! Start using it!
|
||||||
if (config->use_auto_device_detect || detected->found_type != DEVICE_SIMULATION)
|
if (config->use_auto_device_detect || detected->found_type != DEVICE_SIMULATION)
|
||||||
|
@ -875,7 +875,7 @@ void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, Dete
|
||||||
|
|
||||||
shared_ptr<WMBus> wmbus = create_wmbus_object(detected, config, serial_manager_);
|
shared_ptr<WMBus> wmbus = create_wmbus_object(detected, config, serial_manager_);
|
||||||
if (wmbus == NULL) return;
|
if (wmbus == NULL) return;
|
||||||
wmbus_devices_.push_back(wmbus);
|
bus_devices_.push_back(wmbus);
|
||||||
|
|
||||||
// By default, reset your dongle once every 23 hours,
|
// By default, reset your dongle once every 23 hours,
|
||||||
// so that the reset is not at the exact same time every day.
|
// so that the reset is not at the exact same time every day.
|
||||||
|
@ -894,13 +894,6 @@ void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, Dete
|
||||||
warning("Warning! Desired link modes %s cannot be set for device %s\n",
|
warning("Warning! Desired link modes %s cannot be set for device %s\n",
|
||||||
lms.hr().c_str(), wmbus->hr().c_str());
|
lms.hr().c_str(), wmbus->hr().c_str());
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
LinkModeCalculationResult lmcr = calculateLinkModes(config, wmbus.get(), link_modes_matter);
|
|
||||||
if (lmcr.type != LinkModeCalculationResultType::Success)
|
|
||||||
{
|
|
||||||
error("%s\n", lmcr.msg.c_str());
|
|
||||||
}*/
|
|
||||||
|
|
||||||
bool simulated = false;
|
bool simulated = false;
|
||||||
if (detected->found_type == DEVICE_SIMULATION)
|
if (detected->found_type == DEVICE_SIMULATION)
|
||||||
{
|
{
|
||||||
|
@ -957,7 +950,7 @@ void perform_auto_scan_of_serial_devices(Configuration *config)
|
||||||
if (config->use_auto_device_detect || found)
|
if (config->use_auto_device_detect || found)
|
||||||
{
|
{
|
||||||
// Open the device, only if auto is enabled, or if the device was specified.
|
// Open the device, only if auto is enabled, or if the device was specified.
|
||||||
open_wmbus_device_and_set_linkmodes(config, found?"config":"auto", &detected);
|
open_bus_device_and_potentially_set_linkmodes(config, found?"config":"auto", &detected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1029,7 +1022,7 @@ void perform_auto_scan_of_swradio_devices(Configuration *config)
|
||||||
if (config->use_auto_device_detect || found)
|
if (config->use_auto_device_detect || found)
|
||||||
{
|
{
|
||||||
// Open the device, only if auto is enabled, or if the device was specified.
|
// Open the device, only if auto is enabled, or if the device was specified.
|
||||||
open_wmbus_device_and_set_linkmodes(config, found?"config":"auto", &detected);
|
open_bus_device_and_potentially_set_linkmodes(config, found?"config":"auto", &detected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1061,9 +1054,9 @@ void regular_checkup(Configuration *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
LOCK_WMBUS_DEVICES(regular_checkup);
|
LOCK_BUS_DEVICES(regular_checkup);
|
||||||
|
|
||||||
for (auto &w : wmbus_devices_)
|
for (auto &w : bus_devices_)
|
||||||
{
|
{
|
||||||
if (w->isWorking())
|
if (w->isWorking())
|
||||||
{
|
{
|
||||||
|
@ -1156,9 +1149,12 @@ bool start(Configuration *config)
|
||||||
// Configure where the logging information should end up.
|
// Configure where the logging information should end up.
|
||||||
setup_log_file(config);
|
setup_log_file(config);
|
||||||
|
|
||||||
if (config->meters.size() == 0 && config->all_device_linkmodes_specified.empty())
|
if (config->meters.size() == 0)
|
||||||
{
|
{
|
||||||
error("No meters supplied. You must supply which link modes to listen to. 11 Eg. auto:c1\n");
|
if (config->num_wmbus_devices > 0 && config->all_device_linkmodes_specified.empty())
|
||||||
|
{
|
||||||
|
error("Wmbus devices found but no meters supplied. You must supply which link modes to listen to. Eg. auto:c1\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure settings.
|
// Configure settings.
|
||||||
|
@ -1212,7 +1208,7 @@ bool start(Configuration *config)
|
||||||
serial_manager_->startEventLoop();
|
serial_manager_->startEventLoop();
|
||||||
detect_and_configure_wmbus_devices(config, DetectionType::ALL);
|
detect_and_configure_wmbus_devices(config, DetectionType::ALL);
|
||||||
|
|
||||||
if (wmbus_devices_.size() == 0)
|
if (bus_devices_.size() == 0)
|
||||||
{
|
{
|
||||||
if (config->nodeviceexit)
|
if (config->nodeviceexit)
|
||||||
{
|
{
|
||||||
|
@ -1254,7 +1250,8 @@ bool start(Configuration *config)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &w : wmbus_devices_)
|
|
||||||
|
for (auto &w : bus_devices_)
|
||||||
{
|
{
|
||||||
// Real devices do nothing, but the simulator device will simulate.
|
// Real devices do nothing, but the simulator device will simulate.
|
||||||
w->simulate();
|
w->simulate();
|
||||||
|
@ -1273,7 +1270,7 @@ bool start(Configuration *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy any remaining allocated objects.
|
// Destroy any remaining allocated objects.
|
||||||
wmbus_devices_.clear();
|
bus_devices_.clear();
|
||||||
meter_manager_->removeAllMeters();
|
meter_manager_->removeAllMeters();
|
||||||
printer_.reset();
|
printer_.reset();
|
||||||
serial_manager_.reset();
|
serial_manager_.reset();
|
||||||
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2021 Fredrik Öhrström
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include"wmbus.h"
|
||||||
|
#include"wmbus_common_implementation.h"
|
||||||
|
#include"wmbus_utils.h"
|
||||||
|
#include"serial.h"
|
||||||
|
|
||||||
|
#include<assert.h>
|
||||||
|
#include<pthread.h>
|
||||||
|
#include<semaphore.h>
|
||||||
|
#include<errno.h>
|
||||||
|
#include<unistd.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
struct MBusRawTTY : public virtual WMBusCommonImplementation
|
||||||
|
{
|
||||||
|
bool ping();
|
||||||
|
string getDeviceId();
|
||||||
|
string getDeviceUniqueId();
|
||||||
|
LinkModeSet getLinkModes();
|
||||||
|
void deviceReset();
|
||||||
|
void deviceSetLinkModes(LinkModeSet lms);
|
||||||
|
LinkModeSet supportedLinkModes() { return Any_bit; }
|
||||||
|
int numConcurrentLinkModes() { return 0; }
|
||||||
|
bool canSetLinkModes(LinkModeSet desired_modes) { return true; }
|
||||||
|
|
||||||
|
void processSerialData();
|
||||||
|
void simulate() { }
|
||||||
|
|
||||||
|
MBusRawTTY(shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager);
|
||||||
|
~MBusRawTTY() { }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
vector<uchar> read_buffer_;
|
||||||
|
LinkModeSet link_modes_;
|
||||||
|
vector<uchar> received_payload_;
|
||||||
|
};
|
||||||
|
|
||||||
|
shared_ptr<WMBus> openMBUS(string device, int baudrate, shared_ptr<SerialCommunicationManager> manager, shared_ptr<SerialDevice> serial_override)
|
||||||
|
{
|
||||||
|
assert(device != "");
|
||||||
|
|
||||||
|
if (serial_override)
|
||||||
|
{
|
||||||
|
MBusRawTTY *imp = new MBusRawTTY(serial_override, manager);
|
||||||
|
imp->markAsNoLongerSerial();
|
||||||
|
return shared_ptr<WMBus>(imp);
|
||||||
|
}
|
||||||
|
auto serial = manager->createSerialDeviceTTY(device.c_str(), baudrate, "rawtty");
|
||||||
|
MBusRawTTY *imp = new MBusRawTTY(serial, manager);
|
||||||
|
return shared_ptr<WMBus>(imp);
|
||||||
|
}
|
||||||
|
|
||||||
|
MBusRawTTY::MBusRawTTY(shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager) :
|
||||||
|
WMBusCommonImplementation(DEVICE_RAWTTY, manager, serial, true)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MBusRawTTY::ping()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
string MBusRawTTY::getDeviceId()
|
||||||
|
{
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
string MBusRawTTY::getDeviceUniqueId()
|
||||||
|
{
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkModeSet MBusRawTTY::getLinkModes() {
|
||||||
|
return link_modes_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MBusRawTTY::deviceReset()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MBusRawTTY::deviceSetLinkModes(LinkModeSet lms)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MBusRawTTY::processSerialData()
|
||||||
|
{
|
||||||
|
vector<uchar> data;
|
||||||
|
|
||||||
|
// Receive and accumulated serial data until a full frame has been received.
|
||||||
|
serial()->receive(&data);
|
||||||
|
|
||||||
|
read_buffer_.insert(read_buffer_.end(), data.begin(), data.end());
|
||||||
|
|
||||||
|
size_t frame_length;
|
||||||
|
int payload_len, payload_offset;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
FrameStatus status = checkWMBusFrame(read_buffer_, &frame_length, &payload_len, &payload_offset);
|
||||||
|
|
||||||
|
if (status == PartialFrame)
|
||||||
|
{
|
||||||
|
// Partial frame, stop eating.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (status == ErrorInFrame)
|
||||||
|
{
|
||||||
|
verbose("(rawtty) protocol error in message received!\n");
|
||||||
|
string msg = bin2hex(read_buffer_);
|
||||||
|
debug("(rawtty) protocol error \"%s\"\n", msg.c_str());
|
||||||
|
read_buffer_.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (status == FullFrame)
|
||||||
|
{
|
||||||
|
vector<uchar> payload;
|
||||||
|
if (payload_len > 0)
|
||||||
|
{
|
||||||
|
uchar l = payload_len;
|
||||||
|
payload.insert(payload.end(), &l, &l+1); // Re-insert the len byte.
|
||||||
|
payload.insert(payload.end(), read_buffer_.begin()+payload_offset, read_buffer_.begin()+payload_offset+payload_len);
|
||||||
|
}
|
||||||
|
read_buffer_.erase(read_buffer_.begin(), read_buffer_.begin()+frame_length);
|
||||||
|
AboutTelegram about("", 0);
|
||||||
|
handleTelegram(about, payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AccessCheck detectMBUS(Detected *detected, shared_ptr<SerialCommunicationManager> manager)
|
||||||
|
{
|
||||||
|
string tty = detected->specified_device.file;
|
||||||
|
int bps = atoi(detected->specified_device.bps.c_str());
|
||||||
|
|
||||||
|
// Since we do not know how to talk to the other end, it might not
|
||||||
|
// even respond. The only thing we can do is to try to open the serial device.
|
||||||
|
auto serial = manager->createSerialDeviceTTY(tty.c_str(), bps, "detect rawtty");
|
||||||
|
AccessCheck rc = serial->open(false);
|
||||||
|
if (rc != AccessCheck::AccessOK) return AccessCheck::NotThere;
|
||||||
|
|
||||||
|
serial->close();
|
||||||
|
|
||||||
|
detected->setAsFound("", WMBusDeviceType::DEVICE_RAWTTY, bps, false, false,
|
||||||
|
detected->specified_device.linkmodes);
|
||||||
|
|
||||||
|
return AccessCheck::AccessOK;
|
||||||
|
}
|
|
@ -1329,7 +1329,8 @@ string makeQuotedJson(string &s)
|
||||||
return string("\"")+key+"\":\""+value+"\"";
|
return string("\"")+key+"\":\""+value+"\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
string currentYear() {
|
string currentYear()
|
||||||
|
{
|
||||||
char datetime[40];
|
char datetime[40];
|
||||||
memset(datetime, 0, sizeof(datetime));
|
memset(datetime, 0, sizeof(datetime));
|
||||||
|
|
||||||
|
@ -1411,7 +1412,7 @@ struct TimePeriod
|
||||||
int day_in_week_from {}; // 0 = mon 6 = sun
|
int day_in_week_from {}; // 0 = mon 6 = sun
|
||||||
int day_in_week_to {}; // 0 = mon 6 = sun
|
int day_in_week_to {}; // 0 = mon 6 = sun
|
||||||
int hour_from {}; // Greater than or equal.
|
int hour_from {}; // Greater than or equal.
|
||||||
int hour_to {}; // Less than.
|
int hour_to {}; // Less than or equal.
|
||||||
};
|
};
|
||||||
|
|
||||||
bool is_inside(struct tm *nowt, TimePeriod *tp)
|
bool is_inside(struct tm *nowt, TimePeriod *tp)
|
||||||
|
|
|
@ -4456,6 +4456,14 @@ Detected detectWMBusDeviceWithFile(SpecifiedDevice &specified_device,
|
||||||
return detected;
|
return detected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special case to cater for /dev/ttyUSB0:mbus:9600, ie an mbus master device.
|
||||||
|
if (specified_device.type == WMBusDeviceType::DEVICE_MBUS)
|
||||||
|
{
|
||||||
|
debug("(lookup) driver: mbus\n");
|
||||||
|
detected.setAsFound("", DEVICE_MBUS, atoi(specified_device.bps.c_str()), false, false, lms);
|
||||||
|
return detected;
|
||||||
|
}
|
||||||
|
|
||||||
// Special case to cater for raw_data.bin, ie the rawtty is implicit.
|
// Special case to cater for raw_data.bin, ie the rawtty is implicit.
|
||||||
if (specified_device.type == WMBusDeviceType::DEVICE_UNKNOWN && !specified_device.is_tty)
|
if (specified_device.type == WMBusDeviceType::DEVICE_UNKNOWN && !specified_device.is_tty)
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,6 +32,7 @@ bool trimCRCsFrameFormatB(std::vector<uchar> &payload);
|
||||||
|
|
||||||
#define LIST_OF_MBUS_DEVICES \
|
#define LIST_OF_MBUS_DEVICES \
|
||||||
X(UNKNOWN,unknown,false,false) \
|
X(UNKNOWN,unknown,false,false) \
|
||||||
|
X(MBUS,mbus,true,false) \
|
||||||
X(AUTO,auto,false,false) \
|
X(AUTO,auto,false,false) \
|
||||||
X(AMB8465,amb8465,true,false) \
|
X(AMB8465,amb8465,true,false) \
|
||||||
X(CUL,cul,true,false) \
|
X(CUL,cul,true,false) \
|
||||||
|
@ -578,6 +579,8 @@ shared_ptr<WMBus> openAMB8465(string device, shared_ptr<SerialCommunicationManag
|
||||||
shared_ptr<SerialDevice> serial_override);
|
shared_ptr<SerialDevice> serial_override);
|
||||||
shared_ptr<WMBus> openRawTTY(string device, int baudrate, shared_ptr<SerialCommunicationManager> manager,
|
shared_ptr<WMBus> openRawTTY(string device, int baudrate, shared_ptr<SerialCommunicationManager> manager,
|
||||||
shared_ptr<SerialDevice> serial_override);
|
shared_ptr<SerialDevice> serial_override);
|
||||||
|
shared_ptr<WMBus> openMBUS(string device, int baudrate, shared_ptr<SerialCommunicationManager> manager,
|
||||||
|
shared_ptr<SerialDevice> serial_override);
|
||||||
shared_ptr<WMBus> openRC1180(string device, shared_ptr<SerialCommunicationManager> manager,
|
shared_ptr<WMBus> openRC1180(string device, shared_ptr<SerialCommunicationManager> manager,
|
||||||
shared_ptr<SerialDevice> serial_override);
|
shared_ptr<SerialDevice> serial_override);
|
||||||
shared_ptr<WMBus> openRTLWMBUS(string identifier, 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,
|
||||||
|
@ -651,6 +654,7 @@ AccessCheck detectCUL(Detected *detected, shared_ptr<SerialCommunicationManager>
|
||||||
AccessCheck detectD1TC(Detected *detected, shared_ptr<SerialCommunicationManager> manager);
|
AccessCheck detectD1TC(Detected *detected, shared_ptr<SerialCommunicationManager> manager);
|
||||||
AccessCheck detectIM871A(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
AccessCheck detectIM871A(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||||
AccessCheck detectRAWTTY(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
AccessCheck detectRAWTTY(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||||
|
AccessCheck detectMBUS(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||||
AccessCheck detectRC1180(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
AccessCheck detectRC1180(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||||
AccessCheck detectRTL433(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
AccessCheck detectRTL433(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||||
AccessCheck detectRTLWMBUS(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
AccessCheck detectRTLWMBUS(Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||||
|
|
|
@ -386,7 +386,6 @@ AccessCheck detectCUL(Detected *detected, shared_ptr<SerialCommunicationManager>
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
{
|
{
|
||||||
verbose("(cul) get version\n");
|
|
||||||
// Try three times, it seems slow sometimes.
|
// Try three times, it seems slow sometimes.
|
||||||
vector<uchar> data;
|
vector<uchar> data;
|
||||||
|
|
||||||
|
@ -397,7 +396,11 @@ AccessCheck detectCUL(Detected *detected, shared_ptr<SerialCommunicationManager>
|
||||||
msg[2] = 0x0d;
|
msg[2] = 0x0d;
|
||||||
|
|
||||||
bool ok = serial->send(msg);
|
bool ok = serial->send(msg);
|
||||||
if (!ok) return AccessCheck::NotThere;
|
if (!ok)
|
||||||
|
{
|
||||||
|
verbose("(cul) are you there? no\n");
|
||||||
|
return AccessCheck::NotThere;
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for 200ms so that the USB stick have time to prepare a response.
|
// Wait for 200ms so that the USB stick have time to prepare a response.
|
||||||
usleep(1000*200);
|
usleep(1000*200);
|
||||||
|
@ -416,10 +419,13 @@ AccessCheck detectCUL(Detected *detected, shared_ptr<SerialCommunicationManager>
|
||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
|
verbose("(cul) are you there? no\n");
|
||||||
return AccessCheck::NotThere;
|
return AccessCheck::NotThere;
|
||||||
}
|
}
|
||||||
|
|
||||||
detected->setAsFound("", WMBusDeviceType::DEVICE_CUL, 38400, false, false, detected->specified_device.linkmodes);
|
detected->setAsFound("", WMBusDeviceType::DEVICE_CUL, 38400, false, false, detected->specified_device.linkmodes);
|
||||||
|
|
||||||
|
verbose("(cul) are you there? yes\n");
|
||||||
|
|
||||||
return AccessCheck::AccessOK;
|
return AccessCheck::AccessOK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -380,6 +380,7 @@ AccessCheck detectRC1180(Detected *detected, shared_ptr<SerialCommunicationManag
|
||||||
// 5 means 19200 bps, which is the speed we are using.
|
// 5 means 19200 bps, which is the speed we are using.
|
||||||
// If not 5, then this is not a rc1180 dongle.
|
// If not 5, then this is not a rc1180 dongle.
|
||||||
serial->close();
|
serial->close();
|
||||||
|
verbose("(rc1180) are you there? no.\n");
|
||||||
return AccessCheck::NotThere;
|
return AccessCheck::NotThere;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue