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)/config.o \
|
||||
$(BUILD)/dvparser.o \
|
||||
$(BUILD)/mbus_rawtty.o \
|
||||
$(BUILD)/meters.o \
|
||||
$(BUILD)/meter_amiplus.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->list_shell_envs &&
|
||||
!c->list_fields &&
|
||||
!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) {
|
||||
|
@ -522,7 +522,8 @@ shared_ptr<Configuration> parseCommandLine(int argc, char **argv) {
|
|||
}
|
||||
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 type = argv[m*4+i+1];
|
||||
string id = argv[m*4+i+2];
|
||||
|
|
102
src/config.cc
102
src/config.cc
|
@ -238,63 +238,79 @@ bool handleDevice(Configuration *c, string devicefile)
|
|||
error("Not a valid device \"%s\"\n", devicefile.c_str());
|
||||
}
|
||||
|
||||
if (ok)
|
||||
if (!ok) return false;
|
||||
|
||||
// Number the devices
|
||||
specified_device.index = c->supplied_bus_devices.size();
|
||||
|
||||
if (specified_device.type == WMBusDeviceType::DEVICE_MBUS)
|
||||
{
|
||||
// Number the devices
|
||||
specified_device.index = c->supplied_wmbus_devices.size();
|
||||
|
||||
if (specified_device.linkmodes.empty())
|
||||
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)
|
||||
{
|
||||
// Essentially link mode calculations are now irrelevant.
|
||||
specified_device.linkmodes.addLinkMode(LinkMode::Any);
|
||||
}
|
||||
else
|
||||
if (specified_device.type == WMBusDeviceType::DEVICE_RTLWMBUS ||
|
||||
specified_device.type == WMBusDeviceType::DEVICE_RTL433)
|
||||
{
|
||||
c->all_device_linkmodes_specified.addLinkMode(LinkMode::C1);
|
||||
c->all_device_linkmodes_specified.addLinkMode(LinkMode::T1);
|
||||
}
|
||||
error("An mbus device must not have linkmode set. \"%s\"\n", devicefile.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
c->all_device_linkmodes_specified.unionLinkModeSet(specified_device.linkmodes);
|
||||
|
||||
if (specified_device.is_stdin ||
|
||||
specified_device.is_file ||
|
||||
specified_device.is_simulation ||
|
||||
specified_device.command != "")
|
||||
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)
|
||||
{
|
||||
if (c->single_device_override)
|
||||
{
|
||||
error("You can only specify one stdin or one file or one command!\n");
|
||||
}
|
||||
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;
|
||||
// Essentially link mode calculations are now irrelevant.
|
||||
specified_device.linkmodes.addLinkMode(LinkMode::Any);
|
||||
}
|
||||
|
||||
if (specified_device.type == WMBusDeviceType::DEVICE_AUTO)
|
||||
else
|
||||
if (specified_device.type == WMBusDeviceType::DEVICE_RTLWMBUS ||
|
||||
specified_device.type == WMBusDeviceType::DEVICE_RTL433)
|
||||
{
|
||||
c->use_auto_device_detect = true;
|
||||
c->auto_device_linkmodes = specified_device.linkmodes;
|
||||
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 ||
|
||||
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_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 == WMBusDeviceType::DEVICE_AUTO)
|
||||
{
|
||||
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");
|
||||
error("You cannot use auto on macosx. You must specify the device tty or rtlwmbus.\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
c->supplied_bus_devices.push_back(specified_device);
|
||||
if (specified_device.type == WMBusDeviceType::DEVICE_MBUS)
|
||||
{
|
||||
c->num_mbus_devices++;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->supplied_wmbus_devices.push_back(specified_device);
|
||||
c->num_wmbus_devices++;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
// drop any already loaded devices from the config file.
|
||||
c->use_auto_device_detect = false;
|
||||
c->supplied_wmbus_devices.clear();
|
||||
c->supplied_bus_devices.clear();
|
||||
|
||||
if (startsWith(device_override, "/dev/rtlsdr"))
|
||||
{
|
||||
|
|
|
@ -87,7 +87,9 @@ struct Configuration
|
|||
int exitafter {}; // Seconds to exit.
|
||||
bool nodeviceexit {}; // If no wmbus receiver device is found, then exit immediately!
|
||||
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.
|
||||
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
|
||||
|
|
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 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 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_swradio_devices(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.
|
||||
// This can change during runtime, plugging/unplugging wmbus dongles.
|
||||
vector<shared_ptr<WMBus>> wmbus_devices_;
|
||||
RecursiveMutex wmbus_devices_mutex_("wmbus_devices_mutex");
|
||||
#define LOCK_WMBUS_DEVICES(where) WITH(wmbus_devices_mutex_, where)
|
||||
vector<shared_ptr<WMBus>> bus_devices_;
|
||||
RecursiveMutex bus_devices_mutex_("bus_devices_mutex");
|
||||
#define LOCK_BUS_DEVICES(where) WITH(bus_devices_mutex_, where)
|
||||
|
||||
// Remember devices that were not detected as wmbus devices.
|
||||
// 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)
|
||||
{
|
||||
LOCK_WMBUS_DEVICES(check_for_wmbus_devices);
|
||||
LOCK_BUS_DEVICES(check_for_bus_devices);
|
||||
|
||||
trace("[MAIN] checking for dead wmbus devices...\n");
|
||||
|
||||
vector<WMBus*> not_working;
|
||||
for (auto &w : wmbus_devices_)
|
||||
for (auto &w : bus_devices_)
|
||||
{
|
||||
if (!w->isWorking())
|
||||
{
|
||||
|
@ -252,20 +252,20 @@ void check_for_dead_wmbus_devices(Configuration *config)
|
|||
|
||||
for (auto w : not_working)
|
||||
{
|
||||
auto i = wmbus_devices_.begin();
|
||||
while (i != wmbus_devices_.end())
|
||||
auto i = bus_devices_.begin();
|
||||
while (i != bus_devices_.end())
|
||||
{
|
||||
if (w == (*i).get())
|
||||
{
|
||||
// The erased shared_ptr will delete the WMBus object.
|
||||
wmbus_devices_.erase(i);
|
||||
bus_devices_.erase(i);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (wmbus_devices_.size() == 0)
|
||||
if (bus_devices_.size() == 0)
|
||||
{
|
||||
if (config->single_device_override)
|
||||
{
|
||||
|
@ -349,6 +349,10 @@ shared_ptr<WMBus> create_wmbus_object(Detected *detected, Configuration *config,
|
|||
assert(0);
|
||||
error("Internal error DEVICE_AUTO should not be used here!\n");
|
||||
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:
|
||||
verbose("(im871a) on %s\n", detected->found_file.c_str());
|
||||
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;
|
||||
}
|
||||
|
||||
for (SpecifiedDevice &specified_device : config->supplied_wmbus_devices)
|
||||
for (SpecifiedDevice &specified_device : config->supplied_bus_devices)
|
||||
{
|
||||
specified_device.handled = false;
|
||||
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_);
|
||||
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 != "")
|
||||
{
|
||||
|
@ -615,7 +619,7 @@ void detect_and_configure_wmbus_devices(Configuration *config, DetectionType dt)
|
|||
// Only read stdin and files once!
|
||||
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;
|
||||
|
@ -631,13 +635,13 @@ void detect_and_configure_wmbus_devices(Configuration *config, DetectionType dt)
|
|||
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);
|
||||
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)
|
||||
{
|
||||
|
@ -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.
|
||||
// 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)
|
||||
{
|
||||
|
@ -670,7 +674,7 @@ SpecifiedDevice *find_specified_device_from_detected(Configuration *c, Detected
|
|||
|
||||
// Iterate over the supplied devices and look for a type match.
|
||||
// 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)
|
||||
{
|
||||
|
@ -786,7 +790,7 @@ void log_start_information(Configuration *config)
|
|||
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());
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -813,20 +817,10 @@ void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, Dete
|
|||
return;
|
||||
}
|
||||
|
||||
LOCK_WMBUS_DEVICES(open_wmbus_device);
|
||||
LOCK_BUS_DEVICES(open_bus_device);
|
||||
|
||||
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;
|
||||
if (lms.empty())
|
||||
{
|
||||
|
@ -853,14 +847,20 @@ void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, Dete
|
|||
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(),
|
||||
toLowerCaseString(detected->found_type),
|
||||
id.c_str(),
|
||||
file.c_str(),
|
||||
using_link_modes.c_str(),
|
||||
fq.c_str(),
|
||||
cmd.c_str());
|
||||
listening.c_str());
|
||||
|
||||
// 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)
|
||||
|
@ -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_);
|
||||
if (wmbus == NULL) return;
|
||||
wmbus_devices_.push_back(wmbus);
|
||||
bus_devices_.push_back(wmbus);
|
||||
|
||||
// By default, reset your dongle once every 23 hours,
|
||||
// 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",
|
||||
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;
|
||||
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)
|
||||
{
|
||||
// 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
|
||||
|
@ -1029,7 +1022,7 @@ void perform_auto_scan_of_swradio_devices(Configuration *config)
|
|||
if (config->use_auto_device_detect || found)
|
||||
{
|
||||
// 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())
|
||||
{
|
||||
|
@ -1156,9 +1149,12 @@ bool start(Configuration *config)
|
|||
// Configure where the logging information should end up.
|
||||
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.
|
||||
|
@ -1212,7 +1208,7 @@ bool start(Configuration *config)
|
|||
serial_manager_->startEventLoop();
|
||||
detect_and_configure_wmbus_devices(config, DetectionType::ALL);
|
||||
|
||||
if (wmbus_devices_.size() == 0)
|
||||
if (bus_devices_.size() == 0)
|
||||
{
|
||||
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.
|
||||
w->simulate();
|
||||
|
@ -1273,7 +1270,7 @@ bool start(Configuration *config)
|
|||
}
|
||||
|
||||
// Destroy any remaining allocated objects.
|
||||
wmbus_devices_.clear();
|
||||
bus_devices_.clear();
|
||||
meter_manager_->removeAllMeters();
|
||||
printer_.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+"\"";
|
||||
}
|
||||
|
||||
string currentYear() {
|
||||
string currentYear()
|
||||
{
|
||||
char datetime[40];
|
||||
memset(datetime, 0, sizeof(datetime));
|
||||
|
||||
|
@ -1411,7 +1412,7 @@ struct TimePeriod
|
|||
int day_in_week_from {}; // 0 = mon 6 = sun
|
||||
int day_in_week_to {}; // 0 = mon 6 = sun
|
||||
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)
|
||||
|
|
|
@ -4456,6 +4456,14 @@ Detected detectWMBusDeviceWithFile(SpecifiedDevice &specified_device,
|
|||
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.
|
||||
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 \
|
||||
X(UNKNOWN,unknown,false,false) \
|
||||
X(MBUS,mbus,true,false) \
|
||||
X(AUTO,auto,false,false) \
|
||||
X(AMB8465,amb8465,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<WMBus> openRawTTY(string device, int baudrate, shared_ptr<SerialCommunicationManager> manager,
|
||||
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<SerialDevice> serial_override);
|
||||
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 detectIM871A(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 detectRTL433(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;
|
||||
for (int i=0; i<3; ++i)
|
||||
{
|
||||
verbose("(cul) get version\n");
|
||||
// Try three times, it seems slow sometimes.
|
||||
vector<uchar> data;
|
||||
|
||||
|
@ -397,7 +396,11 @@ AccessCheck detectCUL(Detected *detected, shared_ptr<SerialCommunicationManager>
|
|||
msg[2] = 0x0d;
|
||||
|
||||
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.
|
||||
usleep(1000*200);
|
||||
|
@ -416,10 +419,13 @@ AccessCheck detectCUL(Detected *detected, shared_ptr<SerialCommunicationManager>
|
|||
|
||||
if (!found)
|
||||
{
|
||||
verbose("(cul) are you there? no\n");
|
||||
return AccessCheck::NotThere;
|
||||
}
|
||||
|
||||
detected->setAsFound("", WMBusDeviceType::DEVICE_CUL, 38400, false, false, detected->specified_device.linkmodes);
|
||||
|
||||
verbose("(cul) are you there? yes\n");
|
||||
|
||||
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.
|
||||
// If not 5, then this is not a rc1180 dongle.
|
||||
serial->close();
|
||||
verbose("(rc1180) are you there? no.\n");
|
||||
return AccessCheck::NotThere;
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue