kopia lustrzana https://github.com/weetmuts/wmbusmeters
Add partial support for RC1180.
rodzic
e4f9eb23db
commit
d443fd4ea2
1
Makefile
1
Makefile
|
@ -160,6 +160,7 @@ METER_OBJS:=\
|
|||
$(BUILD)/wmbus_rtl433.o \
|
||||
$(BUILD)/wmbus_simulator.o \
|
||||
$(BUILD)/wmbus_rawtty.o \
|
||||
$(BUILD)/wmbus_rc1180.o \
|
||||
$(BUILD)/wmbus_wmb13u.o \
|
||||
$(BUILD)/wmbus_utils.o
|
||||
|
||||
|
|
|
@ -29,12 +29,12 @@ Availability of **wmbusmeters** for other Linux distributions can be checked on
|
|||
|
||||
# Run as a daemon
|
||||
|
||||
Remove the wmbus dongle (im871a,amb8465,rfmrx2,cul,d1tc) or the generic rtlsdr dongle (RTL2838) from your computer.
|
||||
Remove the wmbus dongle (im871a,amb8465,cul,rc1180,rfmrx2,d1tc) or the generic rtlsdr dongle (RTL2838) from your computer.
|
||||
|
||||
`make; sudo make install` will install wmbusmeters as a daemon.
|
||||
|
||||
Check the contents of your `/etc/wmbusmeters.conf` file, assuming it
|
||||
has `device=auto` and you are using a im871a,amb8465 or cul device,
|
||||
has `device=auto` and you are using a im871a,amb8465,rc1180 or cul device,
|
||||
then you can now start the daemon with `sudo systemctl start wmbusmeters`.
|
||||
|
||||
When the daemon is running it will scan for wmbus devices every few seconds
|
||||
|
@ -166,7 +166,7 @@ As <options> you can use:
|
|||
--meterfilestimestamp=(never|day|hour|minute|micros) the meter file is suffixed with a
|
||||
timestamp (localtime) with the given resolution.
|
||||
--oneshot wait for an update from each meter, then quit
|
||||
--resetafter=<time> reset the wmbus dongle regularly, default is 24h
|
||||
--resetafter=<time> reset the wmbus dongle regularly, default is 23h
|
||||
--selectfields=id,timestamp,total_m3 select fields to be printed
|
||||
--separator=<c> change field separator to c
|
||||
--shell=<cmdline> invokes cmdline with env variables containing the latest reading
|
||||
|
@ -223,10 +223,11 @@ As meter quadruples you specify:
|
|||
Supported wmbus dongles:
|
||||
IMST 871a (im871a)
|
||||
Amber 8465 (amb8465)
|
||||
BMeters RFM-RX2 (rfmrx2)
|
||||
CUL family (cul)
|
||||
Radiocraft (RC1180) work in progress
|
||||
rtl_wmbus (rtlwmbus)
|
||||
rtl_433 (rtl433)
|
||||
BMeters RFM-RX2 (rfmrx2)
|
||||
|
||||
Supported water meters:
|
||||
Apator at-wmbus-08 (apator08) (non-standard protocol)
|
||||
|
|
|
@ -54,7 +54,8 @@ LIST_OF_MAIN_MENU
|
|||
#define LIST_OF_WMBUS_RECEIVERS \
|
||||
X(AMB8465, "amb8465") \
|
||||
X(CUL, "cul") \
|
||||
X(IM871A, "im871a")
|
||||
X(IM871A, "im871a") \
|
||||
X(RC1180, "rc1180") \
|
||||
|
||||
enum class ReceiversType {
|
||||
#define X(name,description) name,
|
||||
|
@ -238,6 +239,9 @@ void detectWMBUSReceiver()
|
|||
case ReceiversType::IM871A:
|
||||
probeFor("im871a", detectIM871A);
|
||||
break;
|
||||
case ReceiversType::RC1180:
|
||||
probeFor("rc1180", detectRC1180);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,6 +283,9 @@ void resetWMBUSReceiver()
|
|||
case ReceiversType::IM871A:
|
||||
notImplementedYet("Resetting im871a");
|
||||
break;
|
||||
case ReceiversType::RC1180:
|
||||
notImplementedYet("Resetting RC1180");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
26
src/main.cc
26
src/main.cc
|
@ -190,7 +190,7 @@ shared_ptr<WMBus> createWMBusDeviceFrom(Detected *detected, Configuration *confi
|
|||
|
||||
if (detected->override_tty)
|
||||
{
|
||||
serial_override = manager->createSerialDeviceFile(detected->device.file);
|
||||
serial_override = manager->createSerialDeviceFile(detected->device.file, string("override ")+detected->device.file.c_str());
|
||||
verbose("(serial) override with devicefile: %s\n", detected->device.file.c_str());
|
||||
link_modes_matter = false;
|
||||
}
|
||||
|
@ -307,6 +307,12 @@ shared_ptr<WMBus> createWMBusDeviceFrom(Detected *detected, Configuration *confi
|
|||
wmbus = openD1TC(detected->device.file, manager, serial_override);
|
||||
break;
|
||||
}
|
||||
case DEVICE_RC1180:
|
||||
{
|
||||
verbose("(rc1180) on %s\n", detected->device.file.c_str());
|
||||
wmbus = openRC1180(detected->device.file, manager, serial_override);
|
||||
break;
|
||||
}
|
||||
case DEVICE_WMB13U:
|
||||
{
|
||||
verbose("(wmb13u) on %s\n", detected->device.file.c_str());
|
||||
|
@ -556,7 +562,14 @@ void open_wmbus_device(Configuration *config, string how, string device, Detecte
|
|||
}
|
||||
else
|
||||
{
|
||||
verbose("(main) started %s on %s (%s)\n", toString(detected->type), device.c_str(), how.c_str());
|
||||
if (detected->type != DEVICE_SIMULATOR)
|
||||
{
|
||||
notice("Started %s on %s (%s)\n", toString(detected->type), device.c_str(), how.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
verbose("Started %s on %s (%s)\n", toString(detected->type), device.c_str(), how.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<WMBus> w = createWMBusDeviceFrom(detected, config, serial_manager_);
|
||||
|
@ -564,11 +577,12 @@ void open_wmbus_device(Configuration *config, string how, string device, Detecte
|
|||
WMBus *wmbus = wmbus_devices_.back().get();
|
||||
wmbus->setLinkModes(config->listen_to_link_modes);
|
||||
|
||||
// By default, reset your dongle once every day.
|
||||
int regular_reset = 24*3600;
|
||||
// By default, reset your dongle once every 23 hours,
|
||||
// so that the reset is not at the exact same time every day.
|
||||
int regular_reset = 23*3600;
|
||||
if (config->resetafter != 0) regular_reset = config->resetafter;
|
||||
wmbus->setResetInterval(regular_reset);
|
||||
verbose("(main) regular reset %d\n", regular_reset);
|
||||
verbose("(main) regular reset of %s %s will happen every %d seconds\n", toString(detected->type), device.c_str(), regular_reset);
|
||||
|
||||
string using_link_modes = wmbus->getLinkModes().hr();
|
||||
verbose("(config) listen to link modes: %s\n", using_link_modes.c_str());
|
||||
|
@ -604,7 +618,7 @@ void perform_auto_scan_of_serial_devices(Configuration *config)
|
|||
{
|
||||
debug("(main) device %s not currently used, detect contents...\n", device.c_str());
|
||||
// This serial device is not in use.
|
||||
Detected detected = detectImstAmberCul(device, "", "", serial_manager_, true, false, false);
|
||||
Detected detected = detectImstAmberCulRC(device, "", "", serial_manager_, true, false, false);
|
||||
if (detected.type != DEVICE_UNKNOWN)
|
||||
{
|
||||
open_wmbus_device(config, "auto", device, &detected);
|
||||
|
|
121
src/serial.cc
121
src/serial.cc
|
@ -70,10 +70,10 @@ struct SerialCommunicationManagerImp : public SerialCommunicationManager
|
|||
SerialCommunicationManagerImp(time_t exit_after_seconds, bool start_event_loop);
|
||||
~SerialCommunicationManagerImp();
|
||||
|
||||
shared_ptr<SerialDevice> createSerialDeviceTTY(string dev, int baud_rate);
|
||||
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,
|
||||
function<void()> on_exit);
|
||||
shared_ptr<SerialDevice> createSerialDeviceFile(string file);
|
||||
function<void()> on_exit, string purpose);
|
||||
shared_ptr<SerialDevice> createSerialDeviceFile(string file, string purpose);
|
||||
shared_ptr<SerialDevice> createSerialDeviceSimulator();
|
||||
|
||||
void listenTo(SerialDevice *sd, function<void()> cb);
|
||||
|
@ -86,6 +86,7 @@ struct SerialCommunicationManagerImp : public SerialCommunicationManager
|
|||
bool isRunning();
|
||||
|
||||
shared_ptr<SerialDevice> addSerialDeviceForManagement(SerialDevice *sd);
|
||||
void tickleEventLoop();
|
||||
void removeNonWorkingSerialDevices();
|
||||
void closeAllDoNotRemove();
|
||||
|
||||
|
@ -106,7 +107,6 @@ private:
|
|||
|
||||
bool running_ {};
|
||||
bool expect_devices_to_work_ {}; // false during detection phase, true when running.
|
||||
int max_fd_ {};
|
||||
time_t start_time_ {};
|
||||
time_t exit_after_seconds_ {};
|
||||
|
||||
|
@ -144,6 +144,7 @@ struct SerialDeviceImp : public SerialDevice
|
|||
int receive(vector<uchar> *data);
|
||||
bool working() { return resetting_ || fd_ != -1; }
|
||||
bool opened() { return resetting_ || fd_ != -2; }
|
||||
bool isClosed() { return fd_ == -1 && !resetting_; }
|
||||
bool readonly() { return is_stdin_ || is_file_; }
|
||||
|
||||
void expectAscii() { expecting_ascii_ = true; }
|
||||
|
@ -163,9 +164,10 @@ struct SerialDeviceImp : public SerialDevice
|
|||
return available > 0;
|
||||
}
|
||||
|
||||
SerialDeviceImp(SerialCommunicationManagerImp *manager)
|
||||
SerialDeviceImp(SerialCommunicationManagerImp *manager, string purpose)
|
||||
{
|
||||
manager_ = manager;
|
||||
purpose_ = purpose;
|
||||
}
|
||||
~SerialDeviceImp() = default;
|
||||
|
||||
|
@ -186,6 +188,7 @@ protected:
|
|||
bool no_callbacks_ = false;
|
||||
SerialCommunicationManagerImp *manager_;
|
||||
bool resetting_ {}; // Set to true while resetting.
|
||||
string purpose_; // Can be set to identify a serial device purose.
|
||||
|
||||
friend struct SerialCommunicationManagerImp;
|
||||
};
|
||||
|
@ -252,7 +255,7 @@ int SerialDeviceImp::receive(vector<uchar> *data)
|
|||
|
||||
struct SerialDeviceTTY : public SerialDeviceImp
|
||||
{
|
||||
SerialDeviceTTY(string device, int baud_rate, SerialCommunicationManagerImp * manager);
|
||||
SerialDeviceTTY(string device, int baud_rate, SerialCommunicationManagerImp * manager, string purpose);
|
||||
~SerialDeviceTTY();
|
||||
|
||||
AccessCheck open(bool fail_if_not_ok);
|
||||
|
@ -268,8 +271,9 @@ struct SerialDeviceTTY : public SerialDeviceImp
|
|||
};
|
||||
|
||||
SerialDeviceTTY::SerialDeviceTTY(string device, int baud_rate,
|
||||
SerialCommunicationManagerImp *manager)
|
||||
: SerialDeviceImp(manager)
|
||||
SerialCommunicationManagerImp *manager,
|
||||
string purpose)
|
||||
: SerialDeviceImp(manager, purpose)
|
||||
{
|
||||
device_ = device;
|
||||
baud_rate_ = baud_rate;
|
||||
|
@ -310,7 +314,7 @@ AccessCheck SerialDeviceTTY::open(bool fail_if_not_ok)
|
|||
}
|
||||
}
|
||||
}
|
||||
verbose("(serialtty) opened %s\n", device_.c_str());
|
||||
verbose("(serialtty) opened %s %d (%s)\n", device_.c_str(), fd_, purpose_.c_str());
|
||||
return AccessCheck::AccessOK;
|
||||
}
|
||||
|
||||
|
@ -325,7 +329,9 @@ void SerialDeviceTTY::close()
|
|||
on_disappear_();
|
||||
on_disappear_ = NULL;
|
||||
}
|
||||
verbose("(serialtty) closed %s\n", device_.c_str());
|
||||
manager_->tickleEventLoop();
|
||||
|
||||
verbose("(serialtty) closed %s (%s)\n", device_.c_str(), purpose_.c_str());
|
||||
}
|
||||
|
||||
bool SerialDeviceTTY::send(vector<uchar> &data)
|
||||
|
@ -376,7 +382,8 @@ struct SerialDeviceCommand : public SerialDeviceImp
|
|||
{
|
||||
SerialDeviceCommand(string device, string command, vector<string> args, vector<string> envs,
|
||||
SerialCommunicationManagerImp *manager,
|
||||
function<void()> on_exit);
|
||||
function<void()> on_exit,
|
||||
string purpose);
|
||||
~SerialDeviceCommand();
|
||||
|
||||
AccessCheck open(bool fail_if_not_ok);
|
||||
|
@ -405,8 +412,9 @@ SerialDeviceCommand::SerialDeviceCommand(string device,
|
|||
vector<string> args,
|
||||
vector<string> envs,
|
||||
SerialCommunicationManagerImp *manager,
|
||||
function<void()> on_exit)
|
||||
: SerialDeviceImp(manager)
|
||||
function<void()> on_exit,
|
||||
string purpose)
|
||||
: SerialDeviceImp(manager, purpose)
|
||||
{
|
||||
assert(device != "");
|
||||
device_ = device;
|
||||
|
@ -428,7 +436,7 @@ AccessCheck SerialDeviceCommand::open(bool fail_if_not_ok)
|
|||
assert(fd_ >= 0);
|
||||
if (!ok) return AccessCheck::NotThere;
|
||||
setIsStdin();
|
||||
verbose("(serialcmd) opened %s pid %d fd %d\n", command_.c_str(), pid_, fd_);
|
||||
verbose("(serialcmd) opened %s pid %d fd %d (%s)\n", command_.c_str(), pid_, fd_, purpose_.c_str());
|
||||
return AccessCheck::AccessOK;
|
||||
}
|
||||
|
||||
|
@ -449,7 +457,10 @@ void SerialDeviceCommand::close()
|
|||
::flock(fd_, LOCK_UN);
|
||||
::close(fd_);
|
||||
fd_ = -1;
|
||||
verbose("(serialcmd) closed %s pid=%d fd=%d\n", command_.c_str(), p, f);
|
||||
|
||||
manager_->tickleEventLoop();
|
||||
|
||||
verbose("(serialcmd) closed %s pid=%d fd=%d (%s)\n", command_.c_str(), p, f, purpose_.c_str());
|
||||
}
|
||||
|
||||
bool SerialDeviceCommand::working()
|
||||
|
@ -502,7 +513,7 @@ bool SerialDeviceCommand::send(vector<uchar> &data)
|
|||
|
||||
struct SerialDeviceFile : public SerialDeviceImp
|
||||
{
|
||||
SerialDeviceFile(string file, SerialCommunicationManagerImp *manager);
|
||||
SerialDeviceFile(string file, SerialCommunicationManagerImp *manager, string purpose);
|
||||
~SerialDeviceFile();
|
||||
|
||||
AccessCheck open(bool fail_if_not_ok);
|
||||
|
@ -518,8 +529,9 @@ struct SerialDeviceFile : public SerialDeviceImp
|
|||
};
|
||||
|
||||
SerialDeviceFile::SerialDeviceFile(string file,
|
||||
SerialCommunicationManagerImp *manager)
|
||||
: SerialDeviceImp(manager)
|
||||
SerialCommunicationManagerImp *manager,
|
||||
string purpose)
|
||||
: SerialDeviceImp(manager, purpose)
|
||||
{
|
||||
file_ = file;
|
||||
}
|
||||
|
@ -538,7 +550,7 @@ AccessCheck SerialDeviceFile::open(bool fail_if_not_ok)
|
|||
flags |= O_NONBLOCK;
|
||||
fcntl(0, F_SETFL, flags);
|
||||
setIsStdin();
|
||||
verbose("(serialfile) reading from stdin\n");
|
||||
verbose("(serialfile) reading from stdin (%s)\n", purpose_.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -557,13 +569,9 @@ AccessCheck SerialDeviceFile::open(bool fail_if_not_ok)
|
|||
}
|
||||
}
|
||||
setIsFile();
|
||||
verbose("(serialfile) reading from file %s\n", file_.c_str());
|
||||
}
|
||||
if (signalsInstalled())
|
||||
{
|
||||
// Tickle the event loop to use the new file descriptor in the select.
|
||||
if (getEventLoopThread()) pthread_kill(getEventLoopThread(), SIGUSR1);
|
||||
verbose("(serialfile) reading from file %s (%s)\n", file_.c_str(), purpose_.c_str());
|
||||
}
|
||||
manager_->tickleEventLoop();
|
||||
|
||||
return AccessCheck::AccessOK;
|
||||
}
|
||||
|
@ -574,7 +582,10 @@ void SerialDeviceFile::close()
|
|||
::flock(fd_, LOCK_UN);
|
||||
::close(fd_);
|
||||
fd_ = -1;
|
||||
verbose("(serialfile) closed %s %d\n", file_.c_str(), fd_);
|
||||
|
||||
manager_->tickleEventLoop();
|
||||
|
||||
verbose("(serialfile) closed %s %d (%s)\n", file_.c_str(), fd_, purpose_.c_str());
|
||||
}
|
||||
|
||||
bool SerialDeviceFile::working()
|
||||
|
@ -601,10 +612,10 @@ bool SerialDeviceFile::send(vector<uchar> &data)
|
|||
|
||||
struct SerialDeviceSimulator : public SerialDeviceImp
|
||||
{
|
||||
SerialDeviceSimulator(SerialCommunicationManagerImp *m) :
|
||||
SerialDeviceImp(m)
|
||||
SerialDeviceSimulator(SerialCommunicationManagerImp *m, string purpose) :
|
||||
SerialDeviceImp(m, purpose)
|
||||
{
|
||||
verbose("(serialsimulator) opened\n");
|
||||
verbose("(serialsimulator) opened (%s)\n", purpose_.c_str());
|
||||
};
|
||||
~SerialDeviceSimulator() { };
|
||||
|
||||
|
@ -633,7 +644,6 @@ SerialCommunicationManagerImp::SerialCommunicationManagerImp(time_t exit_after_s
|
|||
bool start_event_loop)
|
||||
{
|
||||
running_ = true;
|
||||
max_fd_ = 0;
|
||||
// Block the event loop until everything is configured.
|
||||
if (start_event_loop)
|
||||
{
|
||||
|
@ -647,28 +657,30 @@ SerialCommunicationManagerImp::SerialCommunicationManagerImp(time_t exit_after_s
|
|||
}
|
||||
|
||||
shared_ptr<SerialDevice> SerialCommunicationManagerImp::createSerialDeviceTTY(string device,
|
||||
int baud_rate)
|
||||
int baud_rate,
|
||||
string purpose)
|
||||
{
|
||||
return addSerialDeviceForManagement(new SerialDeviceTTY(device, baud_rate, this));
|
||||
return addSerialDeviceForManagement(new SerialDeviceTTY(device, baud_rate, this, purpose));
|
||||
}
|
||||
|
||||
shared_ptr<SerialDevice> SerialCommunicationManagerImp::createSerialDeviceCommand(string device,
|
||||
string command,
|
||||
vector<string> args,
|
||||
vector<string> envs,
|
||||
function<void()> on_exit)
|
||||
function<void()> on_exit,
|
||||
string purpose)
|
||||
{
|
||||
return addSerialDeviceForManagement(new SerialDeviceCommand(device, command, args, envs, this, on_exit));
|
||||
return addSerialDeviceForManagement(new SerialDeviceCommand(device, command, args, envs, this, on_exit, purpose));
|
||||
}
|
||||
|
||||
shared_ptr<SerialDevice> SerialCommunicationManagerImp::createSerialDeviceFile(string file)
|
||||
shared_ptr<SerialDevice> SerialCommunicationManagerImp::createSerialDeviceFile(string file, string purpose)
|
||||
{
|
||||
return addSerialDeviceForManagement(new SerialDeviceFile(file, this));
|
||||
return addSerialDeviceForManagement(new SerialDeviceFile(file, this, purpose));
|
||||
}
|
||||
|
||||
shared_ptr<SerialDevice> SerialCommunicationManagerImp::createSerialDeviceSimulator()
|
||||
{
|
||||
return addSerialDeviceForManagement(new SerialDeviceSimulator(this));
|
||||
return addSerialDeviceForManagement(new SerialDeviceSimulator(this, ""));
|
||||
}
|
||||
|
||||
void SerialCommunicationManagerImp::listenTo(SerialDevice *sd, function<void()> cb)
|
||||
|
@ -764,12 +776,24 @@ shared_ptr<SerialDevice> SerialCommunicationManagerImp::addSerialDeviceForManage
|
|||
{
|
||||
LOCK_SERIAL_DEVICES(opened);
|
||||
|
||||
max_fd_ = max(sd->fd(), max_fd_);
|
||||
shared_ptr<SerialDevice> ptr = shared_ptr<SerialDevice>(sd);
|
||||
serial_devices_.push_back(ptr);
|
||||
|
||||
tickleEventLoop();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void SerialCommunicationManagerImp::tickleEventLoop()
|
||||
{
|
||||
LOCK_SERIAL_DEVICES(tickle);
|
||||
|
||||
if (signalsInstalled())
|
||||
{
|
||||
// Tickle the event loop to use the new file descriptor in the select.
|
||||
if (getEventLoopThread()) pthread_kill(getEventLoopThread(), SIGUSR1);
|
||||
}
|
||||
}
|
||||
|
||||
void SerialCommunicationManagerImp::removeNonWorkingSerialDevices()
|
||||
{
|
||||
LOCK_SERIAL_DEVICES(remove_non_working_serial_devices);
|
||||
|
@ -786,14 +810,6 @@ void SerialCommunicationManagerImp::removeNonWorkingSerialDevices()
|
|||
}
|
||||
}
|
||||
|
||||
max_fd_ = 0;
|
||||
for (shared_ptr<SerialDevice> &sp : serial_devices_)
|
||||
{
|
||||
if (sp->fd() > max_fd_)
|
||||
{
|
||||
max_fd_ = sp->fd();
|
||||
}
|
||||
}
|
||||
if (serial_devices_.size() == 0 && expect_devices_to_work_)
|
||||
{
|
||||
debug("(serial) no devices working emergency exit!\n");
|
||||
|
@ -938,7 +954,16 @@ void *SerialCommunicationManagerImp::eventLoop()
|
|||
break;
|
||||
}
|
||||
|
||||
int activity = select(max_fd_+1 , &readfds, NULL , NULL, &timeout);
|
||||
int max_fd = 0;
|
||||
for (shared_ptr<SerialDevice> &sp : serial_devices_)
|
||||
{
|
||||
if (sp->fd() > max_fd)
|
||||
{
|
||||
max_fd = sp->fd();
|
||||
}
|
||||
}
|
||||
|
||||
int activity = select(max_fd+1 , &readfds, NULL , NULL, &timeout);
|
||||
|
||||
if (activity == -1 && errno == EINTR)
|
||||
{
|
||||
|
@ -983,7 +1008,7 @@ void *SerialCommunicationManagerImp::eventLoop()
|
|||
|
||||
for (shared_ptr<SerialDevice> &sd : serial_devices_)
|
||||
{
|
||||
if (sd->opened() && !sd->working()) non_working.push_back(sd);
|
||||
if (sd->opened() && !sd->working() && !sd->isClosed()) non_working.push_back(sd);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ struct SerialDevice
|
|||
// If fail_if_not_ok then forcefully exit the program if cannot be opened.
|
||||
virtual AccessCheck open(bool fail_if_not_ok) = 0;
|
||||
virtual void close() = 0;
|
||||
// Explicitly closed fd == -1
|
||||
virtual bool isClosed() = 0;
|
||||
// Send will return true only if sending on a tty.
|
||||
virtual bool send(std::vector<uchar> &data) = 0;
|
||||
// Receive returns the number of bytes received.
|
||||
|
@ -67,15 +69,16 @@ struct SerialDevice
|
|||
struct SerialCommunicationManager
|
||||
{
|
||||
// Read from a /dev/ttyUSB0 or /dev/ttyACM0 device with baud settings.
|
||||
virtual shared_ptr<SerialDevice> createSerialDeviceTTY(string dev, int baud_rate) = 0;
|
||||
virtual shared_ptr<SerialDevice> createSerialDeviceTTY(string dev, int baud_rate, string purpose) = 0;
|
||||
// Read from a sub shell.
|
||||
virtual shared_ptr<SerialDevice> createSerialDeviceCommand(string device,
|
||||
string command,
|
||||
vector<string> args,
|
||||
vector<string> envs,
|
||||
function<void()> on_exit) = 0;
|
||||
function<void()> on_exit,
|
||||
string purpose) = 0;
|
||||
// Read from stdin (file="stdin") or a specific file.
|
||||
virtual shared_ptr<SerialDevice> createSerialDeviceFile(string file) = 0;
|
||||
virtual shared_ptr<SerialDevice> createSerialDeviceFile(string file, string purpose) = 0;
|
||||
// A serial device simulator used for internal testing.
|
||||
virtual shared_ptr<SerialDevice> createSerialDeviceSimulator() = 0;
|
||||
|
||||
|
|
15
src/wmbus.cc
15
src/wmbus.cc
|
@ -471,7 +471,7 @@ string mediaTypeJSON(int a_field_device_type)
|
|||
return "Unknown";
|
||||
}
|
||||
|
||||
Detected detectImstAmberCul(string file,
|
||||
Detected detectImstAmberCulRC(string file,
|
||||
string suffix,
|
||||
string linkmodes,
|
||||
shared_ptr<SerialCommunicationManager> handler,
|
||||
|
@ -489,18 +489,28 @@ Detected detectImstAmberCul(string file,
|
|||
// Anyway by testing for the amb8465 first, we can immediately continue
|
||||
// with the test for the im871a, without the need for a 1s delay.
|
||||
|
||||
|
||||
// Talk amb8465 with it...
|
||||
// assumes this device is configured for 9600 bps, which seems to be the default.
|
||||
if (detectAMB8465(file, &detected, handler) == AccessCheck::AccessOK)
|
||||
{
|
||||
return detected;
|
||||
}
|
||||
|
||||
// Talk RC1180 with it...
|
||||
// assumes this device is configured for 19200 bps, which seems to be the default.
|
||||
if (detectRC1180(file, &detected, handler) == AccessCheck::AccessOK)
|
||||
{
|
||||
return detected;
|
||||
}
|
||||
|
||||
// Talk im871a with it...
|
||||
// assumes this device is configured for 57600 bps, which seems to be the default.
|
||||
if (detectIM871A(file, &detected, handler) == AccessCheck::AccessOK)
|
||||
{
|
||||
return detected;
|
||||
}
|
||||
|
||||
// Talk CUL with it...
|
||||
// assumes this device is configured for 38400 bps, which seems to be the default.
|
||||
if (detectCUL(file, &detected, handler) == AccessCheck::AccessOK)
|
||||
|
@ -580,6 +590,7 @@ Detected detectWMBusDeviceSetting(string file,
|
|||
|
||||
if (suffix == "amb8465") return { { file, suffix }, DEVICE_AMB8465, 0, override_tty, is_tty, is_stdin, is_file };
|
||||
if (suffix == "im871a") return { { file, suffix }, DEVICE_IM871A, 0, override_tty, is_tty, is_stdin, is_file };
|
||||
if (suffix == "rc1180") return { { file, suffix }, DEVICE_RC1180, 0, override_tty, is_tty, is_stdin, is_file };
|
||||
if (suffix == "rfmrx2") return { { file, suffix }, DEVICE_RFMRX2, 0, override_tty, is_tty, is_stdin, is_file };
|
||||
if (suffix == "rtlwmbus") return { { file, suffix }, DEVICE_RTLWMBUS, 0, override_tty, is_tty, is_stdin, is_file };
|
||||
if (suffix == "rtl433") return { { file, suffix}, DEVICE_RTL433, 0, override_tty, is_tty, is_stdin, is_file };
|
||||
|
@ -602,7 +613,7 @@ Detected detectWMBusDeviceSetting(string file,
|
|||
// Ok, we are left with a single /dev/ttyUSB0 lets talk to it
|
||||
// to figure out what is connected to it. We currently only
|
||||
// know how to detect Imst, Amber or CUL dongles.
|
||||
return detectImstAmberCul(file, suffix, linkmodes, handler, is_tty, is_stdin, is_file);
|
||||
return detectImstAmberCulRC(file, suffix, linkmodes, handler, is_tty, is_stdin, is_file);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -75,6 +75,7 @@ struct Device
|
|||
X(DEVICE_AMB8465)\
|
||||
X(DEVICE_RFMRX2)\
|
||||
X(DEVICE_SIMULATOR)\
|
||||
X(DEVICE_RC1180)\
|
||||
X(DEVICE_RTLWMBUS)\
|
||||
X(DEVICE_RTL433)\
|
||||
X(DEVICE_RAWTTY)\
|
||||
|
@ -515,6 +516,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> 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<SerialDevice> serial_override);
|
||||
shared_ptr<WMBus> openRTL433(string device, string command, shared_ptr<SerialCommunicationManager> manager, std::function<void()> on_exit,
|
||||
|
@ -577,6 +580,7 @@ FrameStatus checkWMBusFrame(vector<uchar> &data,
|
|||
AccessCheck detectIM871A(string file, Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||
AccessCheck detectAMB8465(string file, Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||
AccessCheck detectRawTTY(string file, int baud, Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||
AccessCheck detectRC1180(string file, Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||
AccessCheck detectRTLSDR(string file, Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||
AccessCheck detectCUL(string file, Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||
AccessCheck detectWMB13U(string file, Detected *detected, shared_ptr<SerialCommunicationManager> handler);
|
||||
|
@ -585,7 +589,7 @@ AccessCheck detectWMB13U(string file, Detected *detected, shared_ptr<SerialCommu
|
|||
// restore to factory settings.
|
||||
AccessCheck factoryResetAMB8465(string device, shared_ptr<SerialCommunicationManager> handler, int *was_baud);
|
||||
|
||||
Detected detectImstAmberCul(string file,
|
||||
Detected detectImstAmberCulRC(string file,
|
||||
string suffix,
|
||||
string linkmodes,
|
||||
shared_ptr<SerialCommunicationManager> handler,
|
||||
|
|
|
@ -102,7 +102,7 @@ shared_ptr<WMBus> openAMB8465(string device, shared_ptr<SerialCommunicationManag
|
|||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 9600);
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 9600, "amb8465");
|
||||
WMBusAmber *imp = new WMBusAmber(serial, manager);
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
@ -508,7 +508,7 @@ void WMBusAmber::handleMessage(int msgid, vector<uchar> &frame)
|
|||
AccessCheck detectAMB8465(string device, Detected *detected, shared_ptr<SerialCommunicationManager> manager)
|
||||
{
|
||||
// Talk to the device and expect a very specific answer.
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 9600);
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 9600, "detect amb8465");
|
||||
serial->doNotUseCallbacks();
|
||||
AccessCheck rc = serial->open(false);
|
||||
if (rc != AccessCheck::AccessOK) return AccessCheck::NotThere;
|
||||
|
@ -562,7 +562,7 @@ AccessCheck detectAMB8465(string device, Detected *detected, shared_ptr<SerialCo
|
|||
static AccessCheck tryFactoryResetAMB8465(string device, shared_ptr<SerialCommunicationManager> manager, int baud)
|
||||
{
|
||||
// Talk to the device and expect a very specific answer.
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), baud);
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), baud, "reset amb8465");
|
||||
AccessCheck rc = serial->open(false);
|
||||
if (rc != AccessCheck::AccessOK) {
|
||||
verbose("(amb8465) could not open device %s using baud %d\n", device.c_str(), baud);
|
||||
|
|
|
@ -87,7 +87,7 @@ shared_ptr<WMBus> openCUL(string device, shared_ptr<SerialCommunicationManager>
|
|||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 38400);
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 38400, "cul");
|
||||
WMBusCUL *imp = new WMBusCUL(serial, manager);
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
@ -340,7 +340,7 @@ FrameStatus WMBusCUL::checkCULFrame(vector<uchar> &data,
|
|||
AccessCheck detectCUL(string device, Detected *detected, shared_ptr<SerialCommunicationManager> manager)
|
||||
{
|
||||
// Talk to the device and expect a very specific answer.
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 38400);
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 38400, "detect cul");
|
||||
serial->doNotUseCallbacks();
|
||||
AccessCheck rc = serial->open(false);
|
||||
if (rc != AccessCheck::AccessOK) return AccessCheck::NotThere;
|
||||
|
|
|
@ -63,7 +63,7 @@ shared_ptr<WMBus> openD1TC(string device, shared_ptr<SerialCommunicationManager>
|
|||
WMBusD1TC *imp = new WMBusD1TC(serial_override, manager);
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 115200);
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 115200, "d1tc");
|
||||
WMBusD1TC *imp = new WMBusD1TC(serial, manager);
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ AccessCheck detectD1TC(string device, int baud, shared_ptr<SerialCommunicationMa
|
|||
{
|
||||
// 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(device.c_str(), baud);
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), baud, "detect d1tc");
|
||||
AccessCheck rc = serial->open(false);
|
||||
if (rc != AccessCheck::AccessOK) return AccessCheck::NotThere;
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ shared_ptr<WMBus> openIM871A(string device, shared_ptr<SerialCommunicationManage
|
|||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 57600);
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 57600, "im871a");
|
||||
WMBusIM871A *imp = new WMBusIM871A(serial, manager);
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
@ -640,7 +640,7 @@ void WMBusIM871A::handleHWTest(int msgid, vector<uchar> &payload)
|
|||
AccessCheck detectIM871A(string file, Detected *detected, shared_ptr<SerialCommunicationManager> manager)
|
||||
{
|
||||
// Talk to the device and expect a very specific answer.
|
||||
auto serial = manager->createSerialDeviceTTY(file.c_str(), 57600);
|
||||
auto serial = manager->createSerialDeviceTTY(file.c_str(), 57600, "detect im871a");
|
||||
serial->doNotUseCallbacks();
|
||||
AccessCheck rc = serial->open(false);
|
||||
if (rc != AccessCheck::AccessOK) return AccessCheck::NotThere;
|
||||
|
|
|
@ -58,7 +58,7 @@ shared_ptr<WMBus> openRawTTY(string device, int baudrate, shared_ptr<SerialCommu
|
|||
WMBusRawTTY *imp = new WMBusRawTTY(serial_override, manager);
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), baudrate);
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), baudrate, "rawtty");
|
||||
WMBusRawTTY *imp = new WMBusRawTTY(serial, manager);
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ AccessCheck detectRawTTY(string device, int baud, Detected *detected, shared_ptr
|
|||
{
|
||||
// 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(device.c_str(), baud);
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), baud, "detect rawtty");
|
||||
AccessCheck rc = serial->open(false);
|
||||
if (rc != AccessCheck::AccessOK) return AccessCheck::NotThere;
|
||||
|
||||
|
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
Copyright (C) 2020 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_utils.h"
|
||||
#include"wmbus_cul.h"
|
||||
#include"serial.h"
|
||||
|
||||
#include<assert.h>
|
||||
#include<fcntl.h>
|
||||
#include<grp.h>
|
||||
#include<pthread.h>
|
||||
#include<semaphore.h>
|
||||
#include<string.h>
|
||||
#include<errno.h>
|
||||
#include<sys/stat.h>
|
||||
#include<sys/types.h>
|
||||
#include<unistd.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define SET_LINK_MODE 1
|
||||
#define SET_X01_MODE 2
|
||||
|
||||
struct WMBusRC1180 : public virtual WMBusCommonImplementation
|
||||
{
|
||||
bool ping();
|
||||
uint32_t getDeviceId();
|
||||
LinkModeSet getLinkModes();
|
||||
void deviceReset();
|
||||
void deviceSetLinkModes(LinkModeSet lms);
|
||||
LinkModeSet supportedLinkModes() {
|
||||
return
|
||||
C1_bit |
|
||||
S1_bit |
|
||||
T1_bit;
|
||||
}
|
||||
int numConcurrentLinkModes() { return 1; }
|
||||
bool canSetLinkModes(LinkModeSet lms)
|
||||
{
|
||||
if (0 == countSetBits(lms.bits())) return false;
|
||||
if (!supportedLinkModes().supports(lms)) return false;
|
||||
// Ok, the supplied link modes are compatible,
|
||||
// but im871a can only listen to one at a time.
|
||||
return 1 == countSetBits(lms.bits());
|
||||
}
|
||||
void processSerialData();
|
||||
void simulate();
|
||||
|
||||
WMBusRC1180(shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager);
|
||||
~WMBusRC1180() { }
|
||||
|
||||
private:
|
||||
|
||||
LinkModeSet link_modes_ {};
|
||||
vector<uchar> read_buffer_;
|
||||
vector<uchar> received_payload_;
|
||||
string sent_command_;
|
||||
string received_response_;
|
||||
|
||||
FrameStatus checkRC1180Frame(vector<uchar> &data,
|
||||
size_t *hex_frame_length,
|
||||
vector<uchar> &payload);
|
||||
|
||||
string setup_;
|
||||
};
|
||||
|
||||
shared_ptr<WMBus> openRC1180(string device, shared_ptr<SerialCommunicationManager> manager, shared_ptr<SerialDevice> serial_override)
|
||||
{
|
||||
if (serial_override)
|
||||
{
|
||||
WMBusRC1180 *imp = new WMBusRC1180(serial_override, manager);
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 38400, "rc1180");
|
||||
WMBusRC1180 *imp = new WMBusRC1180(serial, manager);
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
||||
WMBusRC1180::WMBusRC1180(shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager) :
|
||||
WMBusCommonImplementation(DEVICE_RC1180, manager, serial)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
bool WMBusRC1180::ping()
|
||||
{
|
||||
verbose("(rc1180) ping\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t WMBusRC1180::getDeviceId()
|
||||
{
|
||||
verbose("(rc1180) getDeviceId\n");
|
||||
return 0x11111111;
|
||||
}
|
||||
|
||||
LinkModeSet WMBusRC1180::getLinkModes()
|
||||
{
|
||||
return link_modes_;
|
||||
}
|
||||
|
||||
void WMBusRC1180::deviceReset()
|
||||
{
|
||||
// No device specific settings needed right now.
|
||||
// The common code in wmbus.cc reset()
|
||||
// will open the serial device and potentially
|
||||
// set the link modes properly.
|
||||
}
|
||||
|
||||
void WMBusRC1180::deviceSetLinkModes(LinkModeSet lms)
|
||||
{
|
||||
if (serial()->readonly()) return; // Feeding from stdin or file.
|
||||
|
||||
return;
|
||||
|
||||
if (!canSetLinkModes(lms))
|
||||
{
|
||||
string modes = lms.hr();
|
||||
error("(rc1180) setting link mode(s) %s is not supported\n", modes.c_str());
|
||||
}
|
||||
// 'brc' command: b - wmbus, r - receive, c - c mode (with t)
|
||||
vector<uchar> msg(5);
|
||||
msg[0] = 'b';
|
||||
msg[1] = 'r';
|
||||
if (lms.has(LinkMode::C1)) {
|
||||
msg[2] = 'c';
|
||||
} else if (lms.has(LinkMode::S1)) {
|
||||
msg[2] = 's';
|
||||
} else if (lms.has(LinkMode::T1)) {
|
||||
msg[2] = 't';
|
||||
}
|
||||
msg[3] = 0xa;
|
||||
msg[4] = 0xd;
|
||||
|
||||
verbose("(rc1180) set link mode %c\n", msg[2]);
|
||||
sent_command_ = string(&msg[0], &msg[3]);
|
||||
received_response_ = "";
|
||||
bool sent = serial()->send(msg);
|
||||
|
||||
if (sent) waitForResponse();
|
||||
|
||||
sent_command_ = "";
|
||||
debug("(rc1180) received \"%s\"", received_response_.c_str());
|
||||
|
||||
bool ok = true;
|
||||
if (lms.has(LinkMode::C1)) {
|
||||
if (received_response_ != "CMODE") ok = false;
|
||||
} else if (lms.has(LinkMode::S1)) {
|
||||
if (received_response_ != "SMODE") ok = false;
|
||||
} else if (lms.has(LinkMode::T1)) {
|
||||
if (received_response_ != "TMODE") ok = false;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
string modes = lms.hr();
|
||||
error("(rc1180) setting link mode(s) %s is not supported for this cul device!\n", modes.c_str());
|
||||
}
|
||||
|
||||
// X01 - start the receiver
|
||||
msg[0] = 'X';
|
||||
msg[1] = '0';
|
||||
msg[2] = '1';
|
||||
msg[3] = 0xa;
|
||||
msg[4] = 0xd;
|
||||
|
||||
sent = serial()->send(msg);
|
||||
|
||||
// Any response here, or does it silently move into listening mode?
|
||||
}
|
||||
|
||||
void WMBusRC1180::simulate()
|
||||
{
|
||||
}
|
||||
|
||||
void WMBusRC1180::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);
|
||||
handleTelegram(payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AccessCheck detectRC1180(string device, Detected *detected, shared_ptr<SerialCommunicationManager> manager)
|
||||
{
|
||||
// Talk to the device and expect a very specific answer.
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 19200, "detect rc1180");
|
||||
serial->doNotUseCallbacks();
|
||||
AccessCheck rc = serial->open(false);
|
||||
if (rc != AccessCheck::AccessOK) return AccessCheck::NotThere;
|
||||
|
||||
verbose("(rc1180) are you there?\n");
|
||||
|
||||
vector<uchar> data;
|
||||
vector<uchar> msg(1);
|
||||
|
||||
// Send a single 0x00 byte. This will trigger the device to enter command mode
|
||||
// the device then responds with '>'
|
||||
msg[0] = 0;
|
||||
|
||||
serial->send(msg);
|
||||
usleep(200*1000);
|
||||
serial->receive(&data);
|
||||
|
||||
if (data[0] != '>') {
|
||||
// no RC1180 device detected
|
||||
serial->close();
|
||||
return AccessCheck::NotThere;
|
||||
}
|
||||
|
||||
data.clear();
|
||||
|
||||
// send '0' to get get the version string: "V 1.67 nanoRC1180868" or similar
|
||||
msg[0] = '0';
|
||||
|
||||
serial->send(msg);
|
||||
// Wait for 200ms so that the USB stick have time to prepare a response.
|
||||
usleep(1000*200);
|
||||
|
||||
serial->receive(&data);
|
||||
string hex = bin2hex(data);
|
||||
|
||||
msg[0] = 'X';
|
||||
serial->send(msg);
|
||||
|
||||
serial->close();
|
||||
|
||||
detected->set(WMBusDeviceType::DEVICE_RC1180, 19200, false);
|
||||
|
||||
return AccessCheck::AccessOK;
|
||||
}
|
|
@ -84,7 +84,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);
|
||||
auto serial = manager->createSerialDeviceCommand(device, "/bin/sh", args, envs, on_exit, "rtl433");
|
||||
WMBusRTL433 *imp = new WMBusRTL433(serial, manager);
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ shared_ptr<WMBus> openRTLWMBUS(string device, string command, shared_ptr<SerialC
|
|||
WMBusRTLWMBUS *imp = new WMBusRTLWMBUS(serial_override, manager);
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
auto serial = manager->createSerialDeviceCommand(device, "/bin/sh", args, envs, on_exit);
|
||||
auto serial = manager->createSerialDeviceCommand(device, "/bin/sh", args, envs, on_exit, "rtlwmbus");
|
||||
WMBusRTLWMBUS *imp = new WMBusRTLWMBUS(serial, manager);
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ shared_ptr<WMBus> openWMB13U(string device, shared_ptr<SerialCommunicationManage
|
|||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 19200);
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 19200, "wmb13u");
|
||||
WMBusWMB13U *imp = new WMBusWMB13U(serial, manager);
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ bool WMBusWMB13U::getConfiguration()
|
|||
AccessCheck detectWMB13U(string device, shared_ptr<SerialCommunicationManager> manager)
|
||||
{
|
||||
// Talk to the device and expect a very specific answer.
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 19200);
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), 19200, "detect wmb13u");
|
||||
AccessCheck rc = serial->open(false);
|
||||
if (rc != AccessCheck::AccessOK) return AccessCheck::NotThere;
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ then
|
|||
fi
|
||||
|
||||
cat <<EOF > $TEST/test_expected.txt
|
||||
Started DEVICE_RTLWMBUS on stdin:rtlwmbus (config)
|
||||
(wmbus) decrypted content failed check, did you use the correct decryption key? Ignoring telegram.
|
||||
(wmbus) decrypted payload crc failed check, did you use the correct decryption key? Ignoring telegram.
|
||||
(wmbus) decrypted content failed check, did you use the correct decryption key? Ignoring telegram.
|
||||
|
|
Ładowanie…
Reference in New Issue