kopia lustrzana https://github.com/weetmuts/wmbusmeters
Added device and rssi_dbm to json.
rodzic
db6b1b5c93
commit
c4226a8268
3
CHANGES
3
CHANGES
|
@ -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
|
||||
|
|
|
@ -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}
|
|
@ -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);
|
||||
|
|
|
@ -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 += ",";
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
17
src/wmbus.cc
17
src/wmbus.cc
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
17
src/wmbus.h
17
src/wmbus.h
|
@ -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;
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -208,7 +208,8 @@ void WMBusRTL433::processSerialData()
|
|||
payload[0] = payload.size()-1;
|
||||
}
|
||||
}
|
||||
handleTelegram(payload);
|
||||
AboutTelegram about("", 0);
|
||||
handleTelegram(about, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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 \
|
||||
|
|
Ładowanie…
Reference in New Issue