Added device and rssi_dbm to json.

pull/156/head
Fredrik Öhrström 2020-10-14 20:59:14 +02:00
rodzic db6b1b5c93
commit c4226a8268
21 zmienionych plików z 171 dodań i 81 usunięć

Wyświetl plik

@ -31,6 +31,9 @@ To list the fields avilable for a meter do --listfields=multical21
To list all meters do --listmeters
To search for a meter do --listmeters=water or --listmeters=multi
The wmbus device used to received the telegram and the rssi level
is part of the json, eg: "device":"rtlwmbus[1234]","rssi_dbm":-47
Version 0.9.36: 2020-09-08
Added support for detection of the proper driver

Wyświetl plik

@ -1,6 +1,6 @@
T1;1;1;2019-04-03 19:00:42.000;97;148;88888888;0x6e4401068888888805077a85006085bc2630713819512eb4cd87fba554fb43f67cf9654a68ee8e194088160df752e716238292e8af1ac20986202ee561d743602466915e42f1105d9c6782a54504e4f099e65a7656b930c73a30775122d2fdf074b5035cfaa7e0050bf32faae03a77
{"media":"water","meter":"apator162","name":"ApWater","id":"88888888","total_m3":4.848,"timestamp":"1111-11-11T11:11:11Z"}
{"media":"water","meter":"apator162","name":"ApWater","id":"88888888","total_m3":4.848,"timestamp":"1111-11-11T11:11:11Z","device":"rtlwmbus[]","rssi_dbm":97}
C1;1;1;2020-01-23 10:25:13.000;97;148;76348799;0x2A442D2C998734761B168D2091D37CAC21E1D68CDAFFCD3DC452BD802913FF7B1706CA9E355D6C2701CC24
{"media":"cold water","meter":"multical21","name":"Vatten","id":"76348799","total_m3":6.408,"target_m3":6.408,"max_flow_m3h":0,"flow_temperature_c":127,"external_temperature_c":19,"current_status":"DRY","time_dry":"22-31 days","time_reversed":"","time_leaking":"","time_bursting":"","timestamp":"1111-11-11T11:11:11Z"}
{"media":"cold water","meter":"multical21","name":"Vatten","id":"76348799","total_m3":6.408,"target_m3":6.408,"max_flow_m3h":0,"flow_temperature_c":127,"external_temperature_c":19,"current_status":"DRY","time_dry":"22-31 days","time_reversed":"","time_leaking":"","time_bursting":"","timestamp":"1111-11-11T11:11:11Z","device":"rtlwmbus[]","rssi_dbm":97}
T1;1;1;2019-04-03 19:00:42.000;97;148;77777777;0xAE44EE4D777777773C077A4400A025E78F4A01F9DCA029EDA03BA452686E8FA917507B29E5358B52D77C111EA4C41140290523F3F6B9F9261705E041C0CA41305004605F42D6C9464E5A04EEE227510BD0DC0983C665C3A5E4739C2082975476AC637BCDD39766AEF030502B6A7697BE9E1C49AF535C15470FCF8ADA36CAB9D0B2A1A8690F8DDCF70859F18B3414D8315B311A0AFA57325531587CB7E9CC110E807F24C190D7E635BEDAF4CAE8A161
{"media":"water","meter":"supercom587","name":"Wasser","id":"77777777","total_m3":0,"timestamp":"1111-11-11T11:11:11Z"}
{"media":"water","meter":"supercom587","name":"Wasser","id":"77777777","total_m3":0,"timestamp":"1111-11-11T11:11:11Z","device":"rtlwmbus[]","rssi_dbm":97}

Wyświetl plik

@ -834,7 +834,7 @@ void open_wmbus_device_and_set_linkmodes(Configuration *config, string how, Dete
debug("(main) added %s to files\n", detected->found_file.c_str());
simulation_files_.insert(detected->specified_device.file);
}
wmbus->onTelegram([&, simulated](vector<uchar> data){return meter_manager_->handleTelegram(data, simulated);});
wmbus->onTelegram([&, simulated](AboutTelegram &about,vector<uchar> data){return meter_manager_->handleTelegram(about, data, simulated);});
wmbus->setTimeout(config->alarm_timeout, config->alarm_expected_activity);
}
@ -1122,8 +1122,9 @@ bool start(Configuration *config)
{
notice("No meters configured. Printing id:s of all telegrams heard!\n");
meter_manager_->onTelegram([](vector<uchar> frame) {
meter_manager_->onTelegram([](AboutTelegram &about, vector<uchar> frame) {
Telegram t;
t.about = about;
MeterKeys mk;
t.parserNoWarnings(); // Try a best effort parse, do not print any warnings.
t.parse(frame, &mk);

Wyświetl plik

@ -66,13 +66,13 @@ struct MeterManagerImplementation : public virtual MeterManager
return meters_.size() != 0;
}
bool handleTelegram(vector<uchar> data, bool simulated)
bool handleTelegram(AboutTelegram &about, vector<uchar> data, bool simulated)
{
if (!hasMeters())
{
if (on_telegram_)
{
on_telegram_(data);
on_telegram_(about, data);
}
return true;
}
@ -82,7 +82,7 @@ struct MeterManagerImplementation : public virtual MeterManager
string id;
for (auto &m : meters_)
{
bool h = m->handleTelegram(data, simulated, &id);
bool h = m->handleTelegram(about, data, simulated, &id);
if (h) handled = true;
}
if (isVerboseEnabled() && !handled)
@ -92,7 +92,7 @@ struct MeterManagerImplementation : public virtual MeterManager
return handled;
}
void onTelegram(function<void(vector<uchar>)> cb)
void onTelegram(function<void(AboutTelegram &about, vector<uchar>)> cb)
{
on_telegram_ = cb;
}
@ -101,7 +101,7 @@ struct MeterManagerImplementation : public virtual MeterManager
private:
vector<shared_ptr<Meter>> meters_;
function<void(vector<uchar>)> on_telegram_;
function<void(AboutTelegram&,vector<uchar>)> on_telegram_;
};
shared_ptr<MeterManager> createMeterManager()
@ -428,9 +428,10 @@ string concatFields(Meter *m, Telegram *t, char c, vector<Print> &prints, vector
return s;
}
bool MeterCommonImplementation::handleTelegram(vector<uchar> input_frame, bool simulated, string *id)
bool MeterCommonImplementation::handleTelegram(AboutTelegram &about, vector<uchar> input_frame, bool simulated, string *id)
{
Telegram t;
t.about = about;
bool ok = t.parseHeader(input_frame);
if (simulated) t.markAsSimulated();
@ -515,6 +516,12 @@ void MeterCommonImplementation::printMeter(Telegram *t,
}
}
s += "\"timestamp\":\""+datetimeOfUpdateRobot()+"\"";
if (t->about.device != "")
{
s += ",";
s += "\"device\":\""+t->about.device+"\",";
s += "\"rssi_dbm\":"+to_string(t->about.rssi_dbm);
}
for (string add_json : additionalJsons())
{
s += ",";

Wyświetl plik

@ -225,7 +225,7 @@ struct Meter
// The handleTelegram expects an input_frame where the DLL crcs have been removed.
// Returns true of this meter handled this telegram!
virtual bool handleTelegram(vector<uchar> input_frame, bool simulated, string *id) = 0;
virtual bool handleTelegram(AboutTelegram &about, vector<uchar> input_frame, bool simulated, string *id) = 0;
virtual bool isTelegramForMe(Telegram *t) = 0;
virtual MeterKeys *meterKeys() = 0;
@ -247,10 +247,10 @@ struct MeterManager
virtual Meter*lastAddedMeter() = 0;
virtual void removeAllMeters() = 0;
virtual void forEachMeter(std::function<void(Meter*)> cb) = 0;
virtual bool handleTelegram(vector<uchar> data, bool simulated) = 0;
virtual bool handleTelegram(AboutTelegram &about, vector<uchar> data, bool simulated) = 0;
virtual bool hasAllMetersReceivedATelegram() = 0;
virtual bool hasMeters() = 0;
virtual void onTelegram(function<void(vector<uchar>)> cb) = 0;
virtual void onTelegram(function<void(AboutTelegram&,vector<uchar>)> cb) = 0;
virtual ~MeterManager() = default;
};

Wyświetl plik

@ -74,7 +74,7 @@ protected:
// Print the dimensionless Text quantity, no unit is needed.
void addPrint(string vname, Quantity vquantity,
function<std::string()> getValueFunc, string help, bool field, bool json);
bool handleTelegram(vector<uchar> frame, bool simulated, string *id);
bool handleTelegram(AboutTelegram &about, vector<uchar> frame, bool simulated, string *id);
void printMeter(Telegram *t,
string *human_readable,
string *fields, char separator,

Wyświetl plik

@ -232,6 +232,11 @@ void Telegram::print()
notice(" ver: 0x%02x\n", dll_version);
if (about.device != "")
{
notice(" device: %s\n", about.device.c_str());
notice(" rssi: %d dBm\n", about.rssi_dbm);
}
string possible_drivers = autoDetectPossibleDrivers();
notice(" driver: %s\n", possible_drivers.c_str());
}
@ -241,7 +246,7 @@ void Telegram::printDLL()
string possible_drivers = autoDetectPossibleDrivers();
string man = manufacturerFlag(dll_mfct);
verbose("(telegram) DLL L=%02x C=%02x (%s) M=%04x (%s) A=%02x%02x%02x%02x VER=%02x TYPE=%02x (%s) (driver %s)\n",
verbose("(telegram) DLL L=%02x C=%02x (%s) M=%04x (%s) A=%02x%02x%02x%02x VER=%02x TYPE=%02x (%s) (driver %s) DEV=%s RSSI=%d\n",
dll_len,
dll_c, cType(dll_c).c_str(),
dll_mfct,
@ -250,7 +255,9 @@ void Telegram::printDLL()
dll_version,
dll_type,
mediaType(dll_type).c_str(),
possible_drivers.c_str());
possible_drivers.c_str(),
about.device.c_str(),
about.rssi_dbm);
}
void Telegram::printELL()
@ -3177,12 +3184,12 @@ WMBusDeviceType WMBusCommonImplementation::type()
return type_;
}
void WMBusCommonImplementation::onTelegram(function<bool(vector<uchar>)> cb)
void WMBusCommonImplementation::onTelegram(function<bool(AboutTelegram&,vector<uchar>)> cb)
{
telegram_listeners_.push_back(cb);
}
bool WMBusCommonImplementation::handleTelegram(vector<uchar> frame)
bool WMBusCommonImplementation::handleTelegram(AboutTelegram &about, vector<uchar> frame)
{
bool handled = false;
last_received_ = time(NULL);
@ -3191,7 +3198,7 @@ bool WMBusCommonImplementation::handleTelegram(vector<uchar> frame)
{
if (f)
{
bool h = f(frame);
bool h = f(about, frame);
if (h) handled = true;
}
}

Wyświetl plik

@ -320,8 +320,23 @@ struct MeterKeys
bool hasAuthenticationKey() { return authentication_key.size() > 0; }
};
struct AboutTelegram
{
// wmbus device used to receive this telegram.
string device;
// The device's opinion of the rssi, best effort conversion into the dbm scale.
// -100 dbm = 0.1 pico Watt to -20 dbm = 10 micro W
// Measurements smaller than -100 and larger than -10 are unlikely.
int rssi_dbm {};
AboutTelegram(string dv, int rs) : device(dv), rssi_dbm(rs) {}
AboutTelegram() {}
};
struct Telegram
{
AboutTelegram about;
// The meter address as a string usually printed on the meter.
string id;
// If decryption failed, set this to true, to prevent further processing.
@ -491,7 +506,7 @@ struct WMBus
virtual int numConcurrentLinkModes() = 0;
virtual bool canSetLinkModes(LinkModeSet lms) = 0;
virtual void setLinkModes(LinkModeSet lms) = 0;
virtual void onTelegram(function<bool(vector<uchar>)> cb) = 0;
virtual void onTelegram(function<bool(AboutTelegram&,vector<uchar>)> cb) = 0;
virtual SerialDevice *serial() = 0;
// Return true of the serial has been overridden, usually with stdin or a file.
virtual bool serialOverride() = 0;

Wyświetl plik

@ -86,8 +86,8 @@ private:
int *msgid_out,
int *payload_len_out,
int *payload_offset,
uchar *rssi);
void handleMessage(int msgid, vector<uchar> &frame);
int *rssi_dbm);
void handleMessage(int msgid, vector<uchar> &frame, int rssi_dbm);
};
shared_ptr<WMBus> openAMB8465(string device, shared_ptr<SerialCommunicationManager> manager, shared_ptr<SerialDevice> serial_override)
@ -279,7 +279,7 @@ FrameStatus WMBusAmber::checkAMB8465Frame(vector<uchar> &data,
int *msgid_out,
int *payload_len_out,
int *payload_offset,
uchar *rssi)
int *rssi_dbm)
{
if (data.size() < 2) return PartialFrame;
debugPayload("(amb8465) checkAMB8465Frame", data);
@ -317,9 +317,9 @@ FrameStatus WMBusAmber::checkAMB8465Frame(vector<uchar> &data,
if (rssi_len)
{
*rssi = data[*frame_length-2];
signed int dbm = (*rssi >= 128) ? (*rssi - 256) / 2 - 74 : *rssi / 2 - 74;
verbose("(amb8465) rssi %d (%d dBm)\n", *rssi, dbm);
int rssi = (int)data[*frame_length-2];
*rssi_dbm = (rssi >= 128) ? (rssi - 256) / 2 - 74 : rssi / 2 - 74;
verbose("(amb8465) rssi %d (%d dBm)\n", rssi, *rssi_dbm);
}
return FullFrame;
@ -362,9 +362,9 @@ FrameStatus WMBusAmber::checkAMB8465Frame(vector<uchar> &data,
if (rssi_expected_)
{
*rssi = data[*frame_length-1];
signed int dbm = (*rssi >= 128) ? (*rssi - 256) / 2 - 74 : *rssi / 2 - 74;
verbose("(amb8465) rssi %d (%d dBm)\n", *rssi, dbm);
int rssi = data[*frame_length-1];
*rssi_dbm = (rssi >= 128) ? (rssi - 256) / 2 - 74 : rssi / 2 - 74;
verbose("(amb8465) rssi %d (%d dBm)\n", rssi, *rssi_dbm);
}
return FullFrame;
@ -403,11 +403,11 @@ void WMBusAmber::processSerialData()
size_t frame_length;
int msgid;
int payload_len, payload_offset;
uchar rssi;
int rssi_dbm;
for (;;)
{
FrameStatus status = checkAMB8465Frame(read_buffer_, &frame_length, &msgid, &payload_len, &payload_offset, &rssi);
FrameStatus status = checkAMB8465Frame(read_buffer_, &frame_length, &msgid, &payload_len, &payload_offset, &rssi_dbm);
if (status == PartialFrame)
{
@ -443,17 +443,18 @@ void WMBusAmber::processSerialData()
read_buffer_.erase(read_buffer_.begin(), read_buffer_.begin()+frame_length);
handleMessage(msgid, payload);
handleMessage(msgid, payload, rssi_dbm);
}
}
}
void WMBusAmber::handleMessage(int msgid, vector<uchar> &frame)
void WMBusAmber::handleMessage(int msgid, vector<uchar> &frame, int rssi_dbm)
{
switch (msgid) {
case (0):
{
handleTelegram(frame);
AboutTelegram about("amb8465["+cached_device_id_+"]", rssi_dbm);
handleTelegram(about, frame);
break;
}
case (0x80|CMD_SET_MODE_REQ):

Wyświetl plik

@ -241,7 +241,8 @@ void WMBusCUL::processSerialData()
{
read_buffer_.erase(read_buffer_.begin(), read_buffer_.begin()+frame_length);
handleTelegram(payload);
AboutTelegram about("", 0);
handleTelegram(about, payload);
}
}
}

Wyświetl plik

@ -204,7 +204,8 @@ void WMBusD1TC::processSerialData()
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);
AboutTelegram about("", 0);
handleTelegram(about, payload);
}
}
}

Wyświetl plik

@ -107,7 +107,7 @@ struct Config
s += "link_mode="+toString(LinkModeIM871A(link_mode));
string ids;
strprintf(ids, " id=%08x media=%02x version=%02x c_field=%02x", id, media, version, c_field);
strprintf(ids, " id=%08x media=%02x version=%02x c_field=%02x auto_rssi=%02x", id, media, version, c_field, auto_rssi);
return s+ids;
}
@ -189,7 +189,8 @@ struct WMBusIM871A : public virtual WMBusCommonImplementation
static FrameStatus checkIM871AFrame(vector<uchar> &data,
size_t *frame_length, int *endpoint_out, int *msgid_out,
int *payload_len_out, int *payload_offset);
int *payload_len_out, int *payload_offset,
int *rssi_dbm);
private:
@ -205,11 +206,26 @@ private:
friend AccessCheck detectIM871A(Detected *detected, shared_ptr<SerialCommunicationManager> manager);
void handleDevMgmt(int msgid, vector<uchar> &payload);
void handleRadioLink(int msgid, vector<uchar> &payload);
void handleRadioLink(int msgid, vector<uchar> &payload, int rssi_dbm);
void handleRadioLinkTest(int msgid, vector<uchar> &payload);
void handleHWTest(int msgid, vector<uchar> &payload);
};
int toDBM(int rssi)
{
// Very course approximation of this graph:
// Figure 7-3: RSSI vs. Input Power (Silicon Labs Si1002 datasheet [3])
// Stronger rssi:s than 0 dbm will be reported as 0 dbm.
// rssi = >230 -> 0 dbm
// rssi = 205 -> -20 dbm
// rssi = 45 -> -100 dbm
#define SLOPE (80.0/(205.0-45.0))
if (rssi >= 230) return 0;
int dbm = -100+SLOPE*(rssi-45);
return dbm;
}
shared_ptr<WMBus> openIM871A(string device, shared_ptr<SerialCommunicationManager> manager, shared_ptr<SerialDevice> serial_override)
{
assert(device != "");
@ -493,9 +509,9 @@ void WMBusIM871A::deviceSetLinkModes(LinkModeSet lms)
request_[6] = (int)LinkModeIM871A::C1a; // Defaults to C1a
}
request_[7] = 16+32; // iff2 bits: Set rssi+timestamp
request_[7] = 0x10 | 0x20; // iff2 bits: Set rssi 0x10, timestamp 0x20
request_[8] = 1; // Enable rssi
request_[9] = 1; // Enable timestamp
request_[9] = 0; // Disable timestamp
verbose("(im871a) set config to set link mode %02x\n", request_[6]);
bool sent = serial()->send(request_);
@ -512,7 +528,8 @@ void WMBusIM871A::deviceSetLinkModes(LinkModeSet lms)
FrameStatus WMBusIM871A::checkIM871AFrame(vector<uchar> &data,
size_t *frame_length, int *endpoint_out, int *msgid_out,
int *payload_len_out, int *payload_offset)
int *payload_len_out, int *payload_offset,
int *rssi_dbm)
{
if (data.size() == 0) return PartialFrame;
@ -613,8 +630,9 @@ FrameStatus WMBusIM871A::checkIM871AFrame(vector<uchar> &data,
i += 4;
}
if (has_rssi) {
uint32_t rssi = data[i];
verbose("(im871a) rssi %02x\n", rssi);
int rssi = data[i];
*rssi_dbm = toDBM(rssi);
debug("(im871a) rssi %d (%d dBm)\n", rssi, *rssi_dbm);
i++;
}
if (has_crc16) {
@ -647,10 +665,11 @@ void WMBusIM871A::processSerialData()
int endpoint;
int msgid;
int payload_len, payload_offset;
int rssi_dbm = 0;
for (;;)
{
FrameStatus status = checkIM871AFrame(read_buffer_, &frame_length, &endpoint, &msgid, &payload_len, &payload_offset);
FrameStatus status = checkIM871AFrame(read_buffer_, &frame_length, &endpoint, &msgid, &payload_len, &payload_offset, &rssi_dbm);
if (status == PartialFrame)
{
@ -688,7 +707,7 @@ void WMBusIM871A::processSerialData()
// It can be wmbus receiver-dongle messages or wmbus remote meter messages received over the radio.
switch (endpoint) {
case DEVMGMT_ID: handleDevMgmt(msgid, payload); break;
case RADIOLINK_ID: handleRadioLink(msgid, payload); break;
case RADIOLINK_ID: handleRadioLink(msgid, payload, rssi_dbm); break;
case RADIOLINKTEST_ID: handleRadioLinkTest(msgid, payload); break;
case HWTEST_ID: handleHWTest(msgid, payload); break;
}
@ -726,13 +745,16 @@ void WMBusIM871A::handleDevMgmt(int msgid, vector<uchar> &payload)
}
}
void WMBusIM871A::handleRadioLink(int msgid, vector<uchar> &frame)
void WMBusIM871A::handleRadioLink(int msgid, vector<uchar> &frame, int rssi_dbm)
{
switch (msgid) {
case RADIOLINK_MSG_WMBUSMSG_IND: // 0x03
{
// Invoke common telegram reception code in WMBusCommonImplementation.
handleTelegram(frame);
break;
AboutTelegram about("im871a["+cached_device_id_+"]", rssi_dbm);
handleTelegram(about, frame);
}
break;
default:
verbose("(im871a) Unhandled radio link message %d\n", msgid);
}
@ -757,10 +779,10 @@ void WMBusIM871A::handleHWTest(int msgid, vector<uchar> &payload)
bool extract_response(vector<uchar> &data, vector<uchar> &response, int expected_endpoint, int expected_msgid)
{
size_t frame_length;
int endpoint, msgid, payload_len, payload_offset;
int endpoint, msgid, payload_len, payload_offset, rssi_dbm;
FrameStatus status = WMBusIM871A::checkIM871AFrame(data,
&frame_length, &endpoint, &msgid,
&payload_len, &payload_offset);
&payload_len, &payload_offset, &rssi_dbm);
if (status != FullFrame ||
endpoint != expected_endpoint ||
msgid != expected_msgid)
@ -845,10 +867,10 @@ AccessCheck detectIM871A(Detected *detected, shared_ptr<SerialCommunicationManag
serial->receive(&response);
size_t frame_length;
int endpoint, msgid, payload_len, payload_offset;
int endpoint, msgid, payload_len, payload_offset, rssi_dbm;
FrameStatus status = WMBusIM871A::checkIM871AFrame(response,
&frame_length, &endpoint, &msgid,
&payload_len, &payload_offset);
&payload_len, &payload_offset, &rssi_dbm);
if (status != FullFrame ||
endpoint != 1 ||
msgid != DEVMGMT_MSG_GET_CONFIG_RSP)

Wyświetl plik

@ -132,7 +132,8 @@ void WMBusRawTTY::processSerialData()
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);
AboutTelegram about("", 0);
handleTelegram(about, payload);
}
}
}

Wyświetl plik

@ -230,7 +230,8 @@ void WMBusRC1180::processSerialData()
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);
AboutTelegram about("", 0);
handleTelegram(about, payload);
}
}
}

Wyświetl plik

@ -208,7 +208,8 @@ void WMBusRTL433::processSerialData()
payload[0] = payload.size()-1;
}
}
handleTelegram(payload);
AboutTelegram about("", 0);
handleTelegram(about, payload);
}
}
}

Wyświetl plik

@ -55,11 +55,12 @@ struct WMBusRTLWMBUS : public virtual WMBusCommonImplementation
void processSerialData();
void simulate();
WMBusRTLWMBUS(shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager);
WMBusRTLWMBUS(string serialnr, shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager);
~WMBusRTLWMBUS() { }
private:
string serialnr_;
vector<uchar> read_buffer_;
vector<uchar> received_payload_;
bool warning_dll_len_printed_ {};
@ -67,33 +68,35 @@ private:
FrameStatus checkRTLWMBUSFrame(vector<uchar> &data,
size_t *hex_frame_length,
int *hex_payload_len_out,
int *hex_payload_offset);
int *hex_payload_offset,
double *rssi);
void handleMessage(vector<uchar> &frame);
string setup_;
};
shared_ptr<WMBus> openRTLWMBUS(string identifier, string command, shared_ptr<SerialCommunicationManager> manager,
shared_ptr<WMBus> openRTLWMBUS(string serialnr, string command, shared_ptr<SerialCommunicationManager> manager,
function<void()> on_exit, shared_ptr<SerialDevice> serial_override)
{
debug("(rtlwmbus) opening %s\n", identifier.c_str());
debug("(rtlwmbus) opening %s\n", serialnr.c_str());
vector<string> args;
vector<string> envs;
args.push_back("-c");
args.push_back(command);
if (serial_override)
{
WMBusRTLWMBUS *imp = new WMBusRTLWMBUS(serial_override, manager);
WMBusRTLWMBUS *imp = new WMBusRTLWMBUS(serialnr, serial_override, manager);
imp->markSerialAsOverriden();
return shared_ptr<WMBus>(imp);
}
auto serial = manager->createSerialDeviceCommand(identifier, "/bin/sh", args, envs, on_exit, "rtlwmbus");
WMBusRTLWMBUS *imp = new WMBusRTLWMBUS(serial, manager);
auto serial = manager->createSerialDeviceCommand(serialnr, "/bin/sh", args, envs, on_exit, "rtlwmbus");
WMBusRTLWMBUS *imp = new WMBusRTLWMBUS(serialnr, serial, manager);
return shared_ptr<WMBus>(imp);
}
WMBusRTLWMBUS::WMBusRTLWMBUS(shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager) :
WMBusCommonImplementation(DEVICE_RTLWMBUS, manager, serial)
WMBusRTLWMBUS::WMBusRTLWMBUS(string serialnr, shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager) :
WMBusCommonImplementation(DEVICE_RTLWMBUS, manager, serial), serialnr_(serialnr)
{
reset();
}
@ -105,7 +108,7 @@ bool WMBusRTLWMBUS::ping()
string WMBusRTLWMBUS::getDeviceId()
{
return "";
return serialnr_;
}
LinkModeSet WMBusRTLWMBUS::getLinkModes()
@ -139,7 +142,8 @@ void WMBusRTLWMBUS::processSerialData()
for (;;)
{
FrameStatus status = checkRTLWMBUSFrame(read_buffer_, &frame_length, &hex_payload_len, &hex_payload_offset);
double rssi = 0;
FrameStatus status = checkRTLWMBUSFrame(read_buffer_, &frame_length, &hex_payload_len, &hex_payload_offset, &rssi);
if (status == PartialFrame)
{
@ -194,7 +198,10 @@ void WMBusRTLWMBUS::processSerialData()
payload[0] = payload.size()-1;
}
}
handleTelegram(payload);
string id = string("rtlwmbus[")+getDeviceId()+"]";
AboutTelegram about(id, rssi);
handleTelegram(about, payload);
}
}
}
@ -202,7 +209,8 @@ void WMBusRTLWMBUS::processSerialData()
FrameStatus WMBusRTLWMBUS::checkRTLWMBUSFrame(vector<uchar> &data,
size_t *hex_frame_length,
int *hex_payload_len_out,
int *hex_payload_offset)
int *hex_payload_offset,
double *rssi)
{
// C1;1;1;2019-02-09 07:14:18.000;117;102;94740459;0x49449344590474943508780dff5f3500827f0000f10007b06effff530100005f2c620100007f2118010000008000800080008000000000000000000e003f005500d4ff2f046d10086922
// There might be a second telegram on the same line ;0x4944.......
@ -259,8 +267,27 @@ FrameStatus WMBusRTLWMBUS::checkRTLWMBUSFrame(vector<uchar> &data,
return ErrorInFrame;
}
}
// Look for start of telegram 0x
size_t i = 0;
int count = 0;
// Look for packet rssi
for (; i+1 < data.size(); ++i) {
if (data[i] == ';') count++;
if (count == 4) break;
}
if (count == 4)
{
size_t from = i+1;
for (i++; i<data.size(); ++i) {
if (data[i] == ';') break;
}
if ((i-from)<5)
{
string rssis = string(data.begin()+from,data.begin()+i);
*rssi = atof(rssis.c_str());
}
}
// Look for start of telegram 0x
for (; i+1 < data.size(); ++i) {
if (data[i] == '0' && data[i+1] == 'x') break;
}

Wyświetl plik

@ -157,7 +157,8 @@ void WMBusSimulator::simulate()
{
error("Not a valid string of hex bytes! \"%s\"\n", l.c_str());
}
handleTelegram(payload);
AboutTelegram about("", 0);
handleTelegram(about, payload);
}
manager_->stop();
}

Wyświetl plik

@ -33,8 +33,8 @@ struct WMBusCommonImplementation : public virtual WMBus
~WMBusCommonImplementation();
WMBusDeviceType type();
void onTelegram(function<bool(vector<uchar>)> cb);
bool handleTelegram(vector<uchar> frame);
void onTelegram(function<bool(AboutTelegram&,vector<uchar>)> cb);
bool handleTelegram(AboutTelegram &about, vector<uchar> frame);
void checkStatus();
bool isWorking();
string dongleId();
@ -73,7 +73,7 @@ struct WMBusCommonImplementation : public virtual WMBus
private:
bool is_working_ {};
vector<function<bool(vector<uchar>)>> telegram_listeners_;
vector<function<bool(AboutTelegram&,vector<uchar>)>> telegram_listeners_;
WMBusDeviceType type_ {};
int protocol_error_count_ {};
time_t timeout_ {}; // If longer silence than timeout, then reset dongle! It might have hanged!

Wyświetl plik

@ -239,7 +239,8 @@ void WMBusWMB13U::processSerialData()
payload.insert(payload.end(), read_buffer_.begin()+payload_offset, read_buffer_.begin()+payload_offset+payload_len-3);
}
read_buffer_.erase(read_buffer_.begin(), read_buffer_.begin()+frame_length);
handleTelegram(payload);
AboutTelegram about("", 0);
handleTelegram(about, payload);
}
}
}

Wyświetl plik

@ -1,3 +1,3 @@
#!/bin/sh
echo "T1;1;1;2019-04-03 19:00:42.000;97;148;88888888;0x6e4401068888888805077a85006085bc2630713819512eb4cd87fba554fb43f67cf9654a68ee8e194088160df752e716238292e8af1ac20986202ee561d743602466915e42f1105d9c6782a54504e4f099e65a7656b930c73a30775122d2fdf074b5035cfaa7e0050bf32faae03a77"
#{"media":"water","meter":"apator162","name":"ApWater","id":"88888888","total_m3":4.848,"timestamp":"1111-11-11T11:11:11Z"}
#{"media":"water","meter":"apator162","name":"ApWater","id":"88888888","total_m3":4.848,"timestamp":"1111-11-11T11:11:11Z","device":"rtlwmbus[cmd_0]","rssi_dbm":97}

Wyświetl plik

@ -69,8 +69,8 @@ TESTNAME="Reading rtlwmbus formatted telegrams from stdin"
TESTRESULT="ERROR"
cat > $TEST/test_expected.txt <<EOF
{"media":"room sensor","meter":"lansenth","name":"Rummet1","id":"00010203","current_temperature_c":21.8,"current_relative_humidity_rh":43,"average_temperature_1h_c":21.79,"average_relative_humidity_1h_rh":43,"average_temperature_24h_c":21.97,"average_relative_humidity_24h_rh":42.5,"timestamp":"1111-11-11T11:11:11Z"}
{"media":"room sensor","meter":"rfmamb","name":"Rummet2","id":"11772288","current_temperature_c":22.08,"average_temperature_1h_c":21.91,"average_temperature_24h_c":22.07,"maximum_temperature_1h_c":22.08,"minimum_temperature_1h_c":21.85,"maximum_temperature_24h_c":23.47,"minimum_temperature_24h_c":21.29,"current_relative_humidity_rh":44.2,"average_relative_humidity_1h_rh":43.2,"average_relative_humidity_24h_rh":44.5,"minimum_relative_humidity_1h_rh":42.2,"maximum_relative_humidity_1h_rh":50.1,"maximum_relative_humidity_24h_rh":0,"minimum_relative_humidity_24h_rh":0,"device_date_time":"2019-10-11 19:59","timestamp":"1111-11-11T11:11:11Z"}
{"media":"room sensor","meter":"lansenth","name":"Rummet1","id":"00010203","current_temperature_c":21.8,"current_relative_humidity_rh":43,"average_temperature_1h_c":21.79,"average_relative_humidity_1h_rh":43,"average_temperature_24h_c":21.97,"average_relative_humidity_24h_rh":42.5,"timestamp":"1111-11-11T11:11:11Z","device":"rtlwmbus[]","rssi_dbm":97}
{"media":"room sensor","meter":"rfmamb","name":"Rummet2","id":"11772288","current_temperature_c":22.08,"average_temperature_1h_c":21.91,"average_temperature_24h_c":22.07,"maximum_temperature_1h_c":22.08,"minimum_temperature_1h_c":21.85,"maximum_temperature_24h_c":23.47,"minimum_temperature_24h_c":21.29,"current_relative_humidity_rh":44.2,"average_relative_humidity_1h_rh":43.2,"average_relative_humidity_24h_rh":44.5,"minimum_relative_humidity_1h_rh":42.2,"maximum_relative_humidity_1h_rh":50.1,"maximum_relative_humidity_24h_rh":0,"minimum_relative_humidity_24h_rh":0,"device_date_time":"2019-10-11 19:59","timestamp":"1111-11-11T11:11:11Z","device":"rtlwmbus[]","rssi_dbm":97}
EOF
cat simulations/serial_rtlwmbus_ok.msg | \
@ -97,8 +97,8 @@ TESTNAME="Reading rtlwmbus formatted telegrams from file"
TESTRESULT="ERROR"
cat > $TEST/test_expected.txt <<EOF
{"media":"room sensor","meter":"lansenth","name":"Rummet1","id":"00010203","current_temperature_c":21.8,"current_relative_humidity_rh":43,"average_temperature_1h_c":21.79,"average_relative_humidity_1h_rh":43,"average_temperature_24h_c":21.97,"average_relative_humidity_24h_rh":42.5,"timestamp":"1111-11-11T11:11:11Z"}
{"media":"room sensor","meter":"rfmamb","name":"Rummet2","id":"11772288","current_temperature_c":22.08,"average_temperature_1h_c":21.91,"average_temperature_24h_c":22.07,"maximum_temperature_1h_c":22.08,"minimum_temperature_1h_c":21.85,"maximum_temperature_24h_c":23.47,"minimum_temperature_24h_c":21.29,"current_relative_humidity_rh":44.2,"average_relative_humidity_1h_rh":43.2,"average_relative_humidity_24h_rh":44.5,"minimum_relative_humidity_1h_rh":42.2,"maximum_relative_humidity_1h_rh":50.1,"maximum_relative_humidity_24h_rh":0,"minimum_relative_humidity_24h_rh":0,"device_date_time":"2019-10-11 19:59","timestamp":"1111-11-11T11:11:11Z"}
{"media":"room sensor","meter":"lansenth","name":"Rummet1","id":"00010203","current_temperature_c":21.8,"current_relative_humidity_rh":43,"average_temperature_1h_c":21.79,"average_relative_humidity_1h_rh":43,"average_temperature_24h_c":21.97,"average_relative_humidity_24h_rh":42.5,"timestamp":"1111-11-11T11:11:11Z","device":"rtlwmbus[]","rssi_dbm":97}
{"media":"room sensor","meter":"rfmamb","name":"Rummet2","id":"11772288","current_temperature_c":22.08,"average_temperature_1h_c":21.91,"average_temperature_24h_c":22.07,"maximum_temperature_1h_c":22.08,"minimum_temperature_1h_c":21.85,"maximum_temperature_24h_c":23.47,"minimum_temperature_24h_c":21.29,"current_relative_humidity_rh":44.2,"average_relative_humidity_1h_rh":43.2,"average_relative_humidity_24h_rh":44.5,"minimum_relative_humidity_1h_rh":42.2,"maximum_relative_humidity_1h_rh":50.1,"maximum_relative_humidity_24h_rh":0,"minimum_relative_humidity_24h_rh":0,"device_date_time":"2019-10-11 19:59","timestamp":"1111-11-11T11:11:11Z","device":"rtlwmbus[]","rssi_dbm":97}
EOF
$PROG --format=json --listento=any simulations/serial_rtlwmbus_ok.msg:rtlwmbus \