Now rtlwmbus seems to work.

pull/22/head
weetmuts 2019-02-25 22:03:20 +01:00
rodzic dfe8c8bee5
commit b69b27707c
16 zmienionych plików z 488 dodań i 26 usunięć

Wyświetl plik

@ -1,4 +1,9 @@
Version 0.9.0: 2019-02-24
Running wmbusmeters as daemon is now supported.
Updated README
Version 0.8.4: 2019-02-23
Add config files support and daemon mode.

Wyświetl plik

@ -20,7 +20,7 @@
# make DEBUG=true
# make DEBUG=true HOST=arm
VERSION=0.8.4
VERSION=0.9.0
ifeq "$(HOST)" "arm"
CXX=arm-linux-gnueabihf-g++
@ -73,6 +73,7 @@ METERS_OBJS:=\
$(BUILD)/wmbus.o \
$(BUILD)/wmbus_amb8465.o \
$(BUILD)/wmbus_im871a.o \
$(BUILD)/wmbus_rtlwmbus.o \
$(BUILD)/wmbus_simulator.o \
$(BUILD)/wmbus_utils.o

Wyświetl plik

@ -194,9 +194,15 @@ unique_ptr<Configuration> parseCommandLine(int argc, char **argv) {
error("Unknown option \"%s\"\n", argv[i]);
}
c->usb_device = argv[i];
char *extra = strchr(argv[i], ':');
if (extra) {
*extra = 0;
extra++;
c->device_extra = extra;
}
c->device = argv[i];
i++;
if (c->usb_device.length() == 0) error("You must supply the usb device to which the wmbus dongle is connected.\n");
if (c->device.length() == 0) error("You must supply the usb device to which the wmbus dongle is connected.\n");
if ((argc-i) % 4 != 0) {
error("For each meter you must supply a: name,type,id and key.\n");

Wyświetl plik

@ -94,7 +94,19 @@ void handleLoglevel(Configuration *c, string loglevel)
void handleDevice(Configuration *c, string device)
{
c->usb_device = device;
// device can be:
// /dev/ttyUSB00
// auto
// rtlwmbus:/usr/bin/rtl_sdr -f 868.9M -s 1600000 - 2>/dev/null | /usr/bin/rtl_wmbus
// simulation....txt (read telegrams from file)
size_t p = device.find (':');
if (p != string::npos)
{
c->device_extra = device.substr(p+1);
c->device = device.substr(0,p);
} else {
c->device = device;
}
}
void handleLogtelegrams(Configuration *c, string logtelegrams)

Wyświetl plik

@ -65,7 +65,9 @@ struct Configuration {
bool list_shell_envs {};
bool oneshot {};
int exitafter {}; // Seconds to exit.
string usb_device;
string device; // auto, /dev/ttyUSB0, simulation.txt, rtlwmbus
string device_extra; // The command line that will start rtlwmbus
string telegram_reader;
LinkMode link_mode {};
bool link_mode_set {};
bool no_init {};

Wyświetl plik

@ -111,7 +111,10 @@ void startUsingCommandline(Configuration *config)
if (config->meterfiles) {
verbose("(config) store meter files in: \"%s\"\n", config->meterfiles_dir.c_str());
}
verbose("(config) using usb device: %s\n", config->usb_device.c_str());
verbose("(config) using device: %s\n", config->device.c_str());
if (config->device_extra.length() > 0) {
verbose("(config) with: %s\n", config->device_extra.c_str());
}
verbose("(config) number of meters: %d\n", config->meters.size());
auto manager = createSerialCommunicationManager(config->exitafter);
@ -120,7 +123,7 @@ void startUsingCommandline(Configuration *config)
unique_ptr<WMBus> wmbus;
auto type_and_device = detectMBusDevice(config->usb_device, manager.get());
auto type_and_device = detectMBusDevice(config->device, manager.get());
switch (type_and_device.first) {
case DEVICE_IM871A:
@ -135,6 +138,16 @@ void startUsingCommandline(Configuration *config)
verbose("(simulator) found %s\n", type_and_device.second.c_str());
wmbus = openSimulator(type_and_device.second, manager.get());
break;
case DEVICE_RTLWMBUS:
{
verbose("(rtlwmbus) found %s\n", type_and_device.second.c_str());
string command = config->device_extra;
if (command == "") {
command = "/usr/bin/rtl_sdr -f 868.9M -s 16000000 | /usr/bin/rtl_wmbus";
}
wmbus = openRTLWMBUS(command, manager.get());
break;
}
case DEVICE_UNKNOWN:
warning("No wmbus device found! Exiting!\n");
if (config->daemon) {

Wyświetl plik

@ -17,6 +17,7 @@
#include"util.h"
#include"serial.h"
#include"shell.h"
#include <algorithm>
#include <fcntl.h>
@ -34,20 +35,24 @@
static int openSerialTTY(const char *tty, int baud_rate);
struct SerialDeviceImp;
struct SerialDeviceTTY;
struct SerialDeviceCommand;
struct SerialCommunicationManagerImp : public SerialCommunicationManager {
SerialCommunicationManagerImp(time_t exit_after_seconds);
~SerialCommunicationManagerImp() { }
unique_ptr<SerialDevice> createSerialDeviceTTY(string dev, int baud_rate);
unique_ptr<SerialDevice> createSerialDeviceCommand(string command, vector<string> args, vector<string> envs);
void listenTo(SerialDevice *sd, function<void()> cb);
void stop();
void waitForStop();
bool isRunning();
void opened(SerialDeviceTTY *sd);
void closed(SerialDeviceTTY *sd);
void opened(SerialDeviceImp *sd);
void closed(SerialDeviceImp *sd);
private:
void *eventLoop();
@ -62,8 +67,13 @@ private:
};
struct SerialDeviceImp : public SerialDevice {
private:
int fd() { return fd_; }
protected:
function<void()> on_data_;
int fd_;
friend struct SerialCommunicationManagerImp;
};
@ -76,14 +86,12 @@ struct SerialDeviceTTY : public SerialDeviceImp {
void close();
bool send(vector<uchar> &data);
int receive(vector<uchar> *data);
int fd() { return fd_; }
SerialCommunicationManager *manager() { return manager_; }
private:
string device_;
int baud_rate_ {};
int fd_ {};
pthread_mutex_t write_lock_ = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t read_lock_ = PTHREAD_MUTEX_INITIALIZER;
SerialCommunicationManagerImp *manager_;
@ -114,7 +122,7 @@ bool SerialDeviceTTY::open(bool fail_if_not_ok)
}
}
manager_->opened(this);
verbose("(serial) opened %s\n", device_.c_str());
verbose("(serialtty) opened %s\n", device_.c_str());
return true;
}
@ -124,7 +132,7 @@ void SerialDeviceTTY::close()
::close(fd_);
fd_ = -1;
manager_->closed(this);
verbose("(serial) closed %s\n", device_.c_str());
verbose("(serialtty) closed %s\n", device_.c_str());
}
bool SerialDeviceTTY::send(vector<uchar> &data)
@ -189,6 +197,125 @@ int SerialDeviceTTY::receive(vector<uchar> *data)
return num_read;
}
struct SerialDeviceCommand : public SerialDeviceImp {
SerialDeviceCommand(string command, vector<string> args, vector<string> envs, SerialCommunicationManagerImp *manager);
~SerialDeviceCommand();
bool open(bool fail_if_not_ok);
void close();
bool send(vector<uchar> &data);
int receive(vector<uchar> *data);
int fd() { return fd_; }
SerialCommunicationManager *manager() { return manager_; }
private:
string command_;
int fd_ {};
int pid_ {};
vector<string> args_;
vector<string> envs_;
pthread_mutex_t write_lock_ = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t read_lock_ = PTHREAD_MUTEX_INITIALIZER;
SerialCommunicationManagerImp *manager_;
};
SerialDeviceCommand::SerialDeviceCommand(string command,
vector<string> args,
vector<string> envs,
SerialCommunicationManagerImp *manager) {
command_ = command;
args_ = args;
envs_ = envs;
manager_ = manager;
}
SerialDeviceCommand::~SerialDeviceCommand()
{
close();
}
bool SerialDeviceCommand::open(bool fail_if_not_ok)
{
bool ok = invokeBackgroundShell("/bin/sh", args_, envs_, &fd_, 0, &pid_);
if (!ok) return false;
manager_->opened(this);
verbose("(serialcmd) opened %s\n", command_.c_str());
return true;
}
void SerialDeviceCommand::close()
{
::flock(fd_, LOCK_UN);
::close(fd_);
fd_ = -1;
manager_->closed(this);
verbose("(serialcmd) closed %s\n", command_.c_str());
}
bool SerialDeviceCommand::send(vector<uchar> &data)
{
if (data.size() == 0) return true;
pthread_mutex_lock(&write_lock_);
bool rc = true;
int n = data.size();
int written = 0;
while (true) {
int nw = write(fd_, &data[written], n-written);
if (nw > 0) written += nw;
if (nw < 0) {
if (errno==EINTR) continue;
rc = false;
goto end;
}
if (written == n) break;
}
if (isDebugEnabled()) {
string msg = bin2hex(data);
debug("(serial %s) sent \"%s\"\n", command_.c_str(), msg.c_str());
}
end:
pthread_mutex_unlock(&write_lock_);
return rc;
}
int SerialDeviceCommand::receive(vector<uchar> *data)
{
pthread_mutex_lock(&read_lock_);
data->clear();
int available = 0;
int num_read = 0;
ioctl(fd_, FIONREAD, &available);
if (!available) goto end;
data->resize(available);
while (true) {
int nr = read(fd_, &((*data)[num_read]), available-num_read);
if (nr > 0) num_read += nr;
if (nr < 0) {
if (errno==EINTR) continue;
goto end;
}
if (num_read == available) break;
}
if (isDebugEnabled()) {
string msg = bin2hex(*data);
debug("(serialcmd) received \"%s\"\n", msg.c_str());
}
end:
pthread_mutex_unlock(&read_lock_);
return num_read;
}
SerialCommunicationManagerImp::SerialCommunicationManagerImp(time_t exit_after_seconds)
{
running_ = true;
@ -208,6 +335,13 @@ unique_ptr<SerialDevice> SerialCommunicationManagerImp::createSerialDeviceTTY(st
return unique_ptr<SerialDevice>(new SerialDeviceTTY(device, baud_rate, this));
}
unique_ptr<SerialDevice> SerialCommunicationManagerImp::createSerialDeviceCommand(string command,
vector<string> args,
vector<string> envs)
{
return unique_ptr<SerialDevice>(new SerialDeviceCommand(command, args, envs, this));
}
void SerialCommunicationManagerImp::listenTo(SerialDevice *sd, function<void()> cb) {
SerialDeviceImp *si = dynamic_cast<SerialDeviceImp*>(sd);
if (!si) {
@ -236,13 +370,13 @@ bool SerialCommunicationManagerImp::isRunning()
return running_;
}
void SerialCommunicationManagerImp::opened(SerialDeviceTTY *sd) {
void SerialCommunicationManagerImp::opened(SerialDeviceImp *sd) {
max_fd_ = max(sd->fd(), max_fd_);
devices_.push_back(sd);
pthread_kill(thread_, SIGUSR1);
}
void SerialCommunicationManagerImp::closed(SerialDeviceTTY *sd) {
void SerialCommunicationManagerImp::closed(SerialDeviceImp *sd) {
auto p = find(devices_.begin(), devices_.end(), sd);
if (p != devices_.end()) {
devices_.erase(p);
@ -270,7 +404,7 @@ void *SerialCommunicationManagerImp::eventLoop() {
time_t curr = time(NULL);
time_t diff = curr-start_time_;
if (diff > exit_after_seconds_) {
verbose("(serial) exit after %ld seconds\n", diff);
verbose("(serialtty) exit after %ld seconds\n", diff);
stop();
break;
}
@ -280,7 +414,7 @@ void *SerialCommunicationManagerImp::eventLoop() {
if (!running_) break;
if (activity < 0 && errno!=EINTR) {
warning("(serial) internal error after select! errno=%s\n", strerror(errno));
warning("(serialtty) internal error after select! errno=%s\n", strerror(errno));
}
if (activity > 0) {
for (SerialDevice *d : devices_) {
@ -291,7 +425,7 @@ void *SerialCommunicationManagerImp::eventLoop() {
}
}
}
verbose("(serial) event loop stopped!\n");
verbose("(serialtty) event loop stopped!\n");
return NULL;
}

Wyświetl plik

@ -41,6 +41,7 @@ struct SerialDevice {
struct SerialCommunicationManager {
virtual unique_ptr<SerialDevice> createSerialDeviceTTY(string dev, int baud_rate) = 0;
virtual unique_ptr<SerialDevice> createSerialDeviceCommand(string command, vector<string> args, vector<string> envs) = 0;
virtual void listenTo(SerialDevice *sd, function<void()> cb) = 0;
virtual void stop() = 0;
virtual void waitForStop() = 0;

Wyświetl plik

@ -18,6 +18,7 @@
#include "shell.h"
#include "util.h"
#include <assert.h>
#include <memory.h>
#include <pthread.h>
#include <sys/types.h>
@ -86,3 +87,81 @@ void invokeShell(string program, vector<string> args, vector<string> envs)
}
delete[] p;
}
bool invokeBackgroundShell(string program, vector<string> args, vector<string> envs, int *out, int *err, int *pid)
{
int link[2];
vector<const char*> argv(args.size()+2);
char *p = new char[program.length()+1];
strcpy(p, program.c_str());
argv[0] = p;
int i = 1;
debug("exec background \"%s\"\n", program.c_str());
for (auto &a : args) {
argv[i] = a.c_str();
i++;
debug("arg \"%s\"\n", a.c_str());
}
argv[i] = NULL;
vector<const char*> env(envs.size()+1);
env[0] = p;
i = 0;
for (auto &e : envs) {
env[i] = e.c_str();
i++;
debug("env \"%s\"\n", e.c_str());
}
env[i] = NULL;
if (pipe(link) == -1) {
error("Could not create pipe!\n");
}
*pid = fork();
if (*pid == 0) {
// I am the child!
// Redirect stdout and stderr to pipe
dup2 (link[1], STDOUT_FILENO);
dup2 (link[1], STDERR_FILENO);
// Close return pipe, not duped.
close(link[0]);
// Close old forward fd pipe.
close(link[1]);
close(0); // Close stdin
delete[] p;
#if defined(__APPLE__) && defined(__MACH__)
execve(program.c_str(), (char*const*)&argv[0], (char*const*)&env[0]);
#else
execvpe(program.c_str(), (char*const*)&argv[0], (char*const*)&env[0]);
#endif
perror("Execvp failed:");
warning("Invoking shell %s failed!\n", program.c_str());
return false;
}
*out = link[0];
delete[] p;
return true;
}
void stopBackgroundShell(int pid)
{
assert(pid > 0);
kill(pid, SIGINT);
int status;
debug("waiting for child %d.\n", pid);
// Wait for the child to finish!
waitpid(pid, &status, 0);
if (WIFEXITED(status)) {
// Child exited properly.
int rc = WEXITSTATUS(status);
debug("bgshell: return code %d\n", rc);
if (rc != 0) {
warning("bgshell: exited with non-zero return code: %d\n", rc);
}
}
}

Wyświetl plik

@ -21,3 +21,5 @@
using namespace std;
void invokeShell(string program, vector<string> args, vector<string> envs);
bool invokeBackgroundShell(string program, vector<string> args, vector<string> envs, int *out, int *err, int *pid);
void stopBackgroundShell(int pid);

Wyświetl plik

@ -100,6 +100,20 @@ bool hex2bin(string &src, vector<uchar> *target)
return hex2bin(src.c_str(), target);
}
bool hex2bin(vector<uchar> &src, vector<uchar> *target)
{
if (src.size() % 2 == 1) return false;
for (size_t i=0; i<src.size(); i+=2) {
if (src[i] != ' ') {
int hi = char2int(src[i]);
int lo = char2int(src[i+1]);
if (hi<0 || lo<0) return false;
target->push_back(hi*16 + lo);
}
}
return true;
}
char const hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A','B','C','D','E','F'};
std::string bin2hex(vector<uchar> &target) {

Wyświetl plik

@ -33,6 +33,7 @@ typedef unsigned char uchar;
bool hex2bin(const char* src, std::vector<uchar> *target);
bool hex2bin(std::string &src, std::vector<uchar> *target);
bool hex2bin(std::vector<uchar> &src, std::vector<uchar> *target);
std::string bin2hex(std::vector<uchar> &target);
std::string bin2hex(std::vector<uchar>::iterator data, int len);
void strprintf(std::string &s, const char* fmt, ...);

Wyświetl plik

@ -183,6 +183,10 @@ pair<MBusDeviceType,string> detectMBusDevice(string device, SerialCommunicationM
// SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SYMLINK+="im871a",MODE="0660", GROUP="yourowngroup"
// SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="amb8465",MODE="0660", GROUP="yourowngroup"
if (device == "rtlwmbus")
{
return { DEVICE_RTLWMBUS, "" };
}
if (device == "auto")
{
if (detectIM871A("/dev/im871a", handler))
@ -1712,6 +1716,7 @@ string formatData(int dif, int vif, int vife, string data)
string linkModeName(LinkMode link_mode)
{
switch (link_mode) {
case LinkModeAny: return "ANY";
case LinkModeC1: return "C1";
case LinkModeT1: return "T1";
case UNKNOWN_LINKMODE: break;

Wyświetl plik

@ -24,7 +24,7 @@
#include<inttypes.h>
#define LIST_OF_LINK_MODES X(LinkModeC1)X(LinkModeT1)X(UNKNOWN_LINKMODE)
#define LIST_OF_LINK_MODES X(LinkModeAny)X(LinkModeC1)X(LinkModeT1)X(UNKNOWN_LINKMODE)
// In link mode T1, the meter transmits a telegram every few seconds or minutes.
// Suitable for drive-by/walk-by collection of meter values.
@ -106,7 +106,7 @@ struct WMBus {
virtual ~WMBus() = 0;
};
#define LIST_OF_MBUS_DEVICES X(DEVICE_IM871A)X(DEVICE_AMB8465)X(DEVICE_SIMULATOR)X(DEVICE_UNKNOWN)
#define LIST_OF_MBUS_DEVICES X(DEVICE_IM871A)X(DEVICE_AMB8465)X(DEVICE_SIMULATOR)X(DEVICE_RTLWMBUS)X(DEVICE_UNKNOWN)
enum MBusDeviceType {
#define X(name) name,
@ -121,6 +121,7 @@ pair<MBusDeviceType,string> detectMBusDevice(string device, SerialCommunicationM
unique_ptr<WMBus> openIM871A(string device, SerialCommunicationManager *manager);
unique_ptr<WMBus> openAMB8465(string device, SerialCommunicationManager *manager);
struct WMBusSimulator;
unique_ptr<WMBus> openRTLWMBUS(string device, SerialCommunicationManager *manager);
unique_ptr<WMBus> openSimulator(string file, SerialCommunicationManager *manager);
string manufacturer(int m_field);

Wyświetl plik

@ -0,0 +1,191 @@
/*
Copyright (C) 2019 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"serial.h"
#include<assert.h>
#include<fcntl.h>
#include<pthread.h>
#include<semaphore.h>
#include<string.h>
#include<sys/errno.h>
#include<sys/types.h>
#include<unistd.h>
using namespace std;
enum FrameStatus { PartialFrame, FullFrame, ErrorInFrame };
struct WMBusRTLWMBUS : public WMBus {
bool ping();
uint32_t getDeviceId();
LinkMode getLinkMode();
void setLinkMode(LinkMode lm);
void onTelegram(function<void(Telegram*)> cb);
void processSerialData();
SerialDevice *serial() { return NULL; }
void simulate();
WMBusRTLWMBUS(unique_ptr<SerialDevice> serial, SerialCommunicationManager *manager);
private:
unique_ptr<SerialDevice> serial_;
vector<uchar> read_buffer_;
vector<uchar> received_payload_;
vector<function<void(Telegram*)>> telegram_listeners_;
FrameStatus checkRTLWMBUSFrame(vector<uchar> &data,
size_t *hex_frame_length,
int *hex_payload_len_out,
int *hex_payload_offset);
void handleMessage(vector<uchar> &frame);
string setup_;
SerialCommunicationManager *manager_ {};
};
unique_ptr<WMBus> openRTLWMBUS(string command, SerialCommunicationManager *manager)
{
vector<string> args;
vector<string> envs;
args.push_back("-c");
args.push_back(command);
auto serial = manager->createSerialDeviceCommand("/bin/sh", args, envs);
WMBusRTLWMBUS *imp = new WMBusRTLWMBUS(std::move(serial), manager);
return unique_ptr<WMBus>(imp);
}
WMBusRTLWMBUS::WMBusRTLWMBUS(unique_ptr<SerialDevice> serial, SerialCommunicationManager *manager) :
serial_(std::move(serial)), manager_(manager)
{
manager_->listenTo(serial_.get(),call(this,processSerialData));
serial_->open(true);
}
bool WMBusRTLWMBUS::ping() {
return true;
}
uint32_t WMBusRTLWMBUS::getDeviceId() {
return 0x11111111;
}
LinkMode WMBusRTLWMBUS::getLinkMode() {
return LinkModeAny;
}
void WMBusRTLWMBUS::setLinkMode(LinkMode lm)
{
}
void WMBusRTLWMBUS::onTelegram(function<void(Telegram*)> cb) {
telegram_listeners_.push_back(cb);
}
void WMBusRTLWMBUS::simulate()
{
}
void WMBusRTLWMBUS::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 hex_payload_len, hex_payload_offset;
FrameStatus status = checkRTLWMBUSFrame(read_buffer_, &frame_length, &hex_payload_len, &hex_payload_offset);
if (status == ErrorInFrame) {
verbose("(rtl_wmbus) protocol error in message received!\n");
string msg = bin2hex(read_buffer_);
debug("(rtl_wmbus) protocol error \"%s\"\n", msg.c_str());
read_buffer_.clear();
} else
if (status == FullFrame) {
vector<uchar> payload;
if (hex_payload_len > 0) {
vector<uchar> hex;
hex.insert(hex.end(), read_buffer_.begin()+hex_payload_offset, read_buffer_.begin()+hex_payload_offset+hex_payload_len);
hex2bin(hex, &payload);
}
read_buffer_.erase(read_buffer_.begin(), read_buffer_.begin()+frame_length);
handleMessage(payload);
}
}
void WMBusRTLWMBUS::handleMessage(vector<uchar> &frame)
{
Telegram t;
t.parse(frame);
for (auto f : telegram_listeners_)
{
if (f) f(&t);
if (isVerboseEnabled() && !t.handled) {
verbose("(rtl_wmbus) telegram ignored by all configured meters!\n");
}
}
}
FrameStatus WMBusRTLWMBUS::checkRTLWMBUSFrame(vector<uchar> &data,
size_t *hex_frame_length,
int *hex_payload_len_out,
int *hex_payload_offset)
{
//C1;1;1;2019-02-09 07:14:18.000;117;102;94740459;0x49449344590474943508780dff5f3500827f0000f10007b06effff530100005f2c620100007f2118010000008000800080008000000000000000000e003f005500d4ff2f046d10086922
if (data.size() == 0) return PartialFrame;
int payload_len = 0;
size_t eolp = 0;
// Look for end of line.
for (; eolp < data.size(); ++eolp) {
if (data[eolp] == '\n') break;
}
if (eolp >= data.size()) return PartialFrame;
// We got a full line, but if it is too short, then
// there is something wrong. Discard the data.
if (data.size() < 72) return ErrorInFrame;
// Discard lines that are not T1 or C1 telegrams
if (data[0] != 'T' && data[0] != 'C') return ErrorInFrame;
// And the checksums should match.
if (strncmp((const char*)&data[1], "1;1;1", 5)) return ErrorInFrame;
// Look for start of telegram 0x
size_t i = 0;
for (; i+1 < data.size(); ++i) {
if (data[i] == '0' && data[i+1] == 'x') break;
}
if (i+1 >= data.size()) return ErrorInFrame; // No 0x found, then discard the frame.
i+=2; // Skip 0x
payload_len = eolp-i;
*hex_payload_len_out = payload_len;
*hex_payload_offset = i;
*hex_frame_length = eolp+1;
return FullFrame;
}

Wyświetl plik

@ -192,8 +192,3 @@ void WMBusSimulator::simulate()
}
manager_->stop();
}
bool detectSimulator(string device, SerialCommunicationManager *manager)
{
return true;
}