kopia lustrzana https://github.com/weetmuts/wmbusmeters
Now properly handles different dll id and tpl id.
rodzic
b152fefc96
commit
d50f13b240
|
@ -144,19 +144,19 @@ telegram=|2E4409077272727210077AD7102005CC2FF08D057E306D8C3078AE44AD6E3D37F8515B
|
|||
|
||||
# Test electricity meter with eBZ wMB E01.
|
||||
telegram=|5B445A149922992202378C20F6900F002C25BC9E0000BF48954821BC508D72992299225A140102F6003007102F2F040330F92A0004A9FF01FF24000004A9FF026A29000004A9FF03460600000DFD11063132333435362F2F2F2F2F2F|
|
||||
{"media":"radio converter (meter side)","meter":"ebzwmbe","name":"Elen1","id":"22992299","total_energy_consumption_kwh":2816.304,"current_power_consumption_kw":0.21679,"current_power_consumption_phase1_kw":0.09471,"current_power_consumption_phase2_kw":0.10602,"current_power_consumption_phase3_kw":0.01606,"customer":"123456","timestamp":"1111-11-11T11:11:11Z"}
|
||||
{"media":"electricity","meter":"ebzwmbe","name":"Elen1","id":"22992299","total_energy_consumption_kwh":2816.304,"current_power_consumption_kw":0.21679,"current_power_consumption_phase1_kw":0.09471,"current_power_consumption_phase2_kw":0.10602,"current_power_consumption_phase3_kw":0.01606,"customer":"123456","timestamp":"1111-11-11T11:11:11Z"}
|
||||
|Elen1;22992299;2816.304000;0.216790;0.094710;0.106020;0.016060;1111-11-11 11:11.11
|
||||
|
||||
# Test electricity meter with ESYS-WM20
|
||||
|
||||
# static telegram
|
||||
telegram=|7B4479169977997730378C208B900F002C25E4EF0A002EA98E7D58B3ADC57290779977991611028B005087102F2F|0DFD090F34302e3030562030303030303030300D790E31323334353637383839595345310DFD100AAAAAAAAAAAAAAAAAAAAA0D780E31323334353637383930594553312F2F2F2F2F2F2F2F2F2F2F|
|
||||
{"media":"radio converter (meter side)","meter":"esyswm","name":"Elen2","id":"77997799","total_energy_consumption_kwh":0,"current_power_consumption_kw":0,"total_energy_production_kwh":0,"total_energy_consumption_tariff1_kwh":0,"total_energy_consumption_tariff2_kwh":0,"current_power_consumption_phase1_kw":0,"current_power_consumption_phase2_kw":0,"current_power_consumption_phase3_kw":0,"enhanced_id":"1ESY9887654321","version":"40.00V 00000000","location_hex":"AAAAAAAAAAAAAAAAAAAA","fabrication_no":"1SEY0987654321","timestamp":"1111-11-11T11:11:11Z"}
|
||||
telegram=|7B4479169977997730378C208B900F002C25E4EF0A002EA98E7D58B3ADC57299779977991611028B005087102F2F|0DFD090F34302e3030562030303030303030300D790E31323334353637383839595345310DFD100AAAAAAAAAAAAAAAAAAAAA0D780E31323334353637383930594553312F2F2F2F2F2F2F2F2F2F2F|
|
||||
{"media":"electricity","meter":"esyswm","name":"Elen2","id":"77997799","total_energy_consumption_kwh":0,"current_power_consumption_kw":0,"total_energy_production_kwh":0,"total_energy_consumption_tariff1_kwh":0,"total_energy_consumption_tariff2_kwh":0,"current_power_consumption_phase1_kw":0,"current_power_consumption_phase2_kw":0,"current_power_consumption_phase3_kw":0,"enhanced_id":"1ESY9887654321","version":"40.00V 00000000","location_hex":"AAAAAAAAAAAAAAAAAAAA","fabrication_no":"1SEY0987654321","timestamp":"1111-11-11T11:11:11Z"}
|
||||
|Elen2;77997799;0.000000;0.000000;0.000000;0.000000;0.000000;0.000000;0.000000;0.000000;1ESY9887654321;1111-11-11 11:11.11
|
||||
|
||||
# dynamic telegram
|
||||
telegram=|7B4479169977997730378C20F0900F002C2549EE0A0077C19D3D1A08ABCD729977997779161102F0005007102F2F|0702F5C3FA000000000007823C5407000000000000841004E081020084200415000000042938AB000004A9FF01FA0A000004A9FF02050A000004A9FF03389600002F2F2F2F2F2F2F2F2F2F2F2F2F|
|
||||
{"media":"radio converter (meter side)","meter":"esyswm","name":"Elen2","id":"77997799","total_energy_consumption_kwh":1643.4165,"current_power_consumption_kw":0.43832,"total_energy_production_kwh":0.1876,"total_energy_consumption_tariff1_kwh":1643.2,"total_energy_consumption_tariff2_kwh":0.21,"current_power_consumption_phase1_kw":0.0281,"current_power_consumption_phase2_kw":0.02565,"current_power_consumption_phase3_kw":0.38456,"enhanced_id":"1ESY9887654321","version":"40.00V 00000000","location_hex":"AAAAAAAAAAAAAAAAAAAA","fabrication_no":"1SEY0987654321","timestamp":"1111-11-11T11:11:11Z"}
|
||||
{"media":"electricity","meter":"esyswm","name":"Elen2","id":"77997799","total_energy_consumption_kwh":1643.4165,"current_power_consumption_kw":0.43832,"total_energy_production_kwh":0.1876,"total_energy_consumption_tariff1_kwh":1643.2,"total_energy_consumption_tariff2_kwh":0.21,"current_power_consumption_phase1_kw":0.0281,"current_power_consumption_phase2_kw":0.02565,"current_power_consumption_phase3_kw":0.38456,"enhanced_id":"1ESY9887654321","version":"40.00V 00000000","location_hex":"AAAAAAAAAAAAAAAAAAAA","fabrication_no":"1SEY0987654321","timestamp":"1111-11-11T11:11:11Z"}
|
||||
|Elen2;77997799;1643.416500;0.438320;0.187600;1643.200000;0.210000;0.028100;0.025650;0.384560;1ESY9887654321;1111-11-11 11:11.11
|
||||
|
||||
# Test electricity meter eHZ-P
|
||||
|
|
|
@ -1247,8 +1247,7 @@ bool start(Configuration *config)
|
|||
Telegram t;
|
||||
t.about = about;
|
||||
MeterKeys mk;
|
||||
t.parserNoWarnings(); // Try a best effort parse, do not print any warnings.
|
||||
t.parse(frame, &mk);
|
||||
t.parse(frame, &mk, false); // Try a best effort parse, do not print any warnings.
|
||||
t.print();
|
||||
t.explainParse("(wmbus)",0);
|
||||
logTelegram(t.frame, 0, 0);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include<algorithm>
|
||||
#include<memory.h>
|
||||
#include<numeric>
|
||||
#include<time.h>
|
||||
#include<cmath>
|
||||
|
||||
|
@ -79,15 +80,15 @@ struct MeterManagerImplementation : public virtual MeterManager
|
|||
|
||||
bool handled = false;
|
||||
|
||||
string id;
|
||||
string ids;
|
||||
for (auto &m : meters_)
|
||||
{
|
||||
bool h = m->handleTelegram(about, data, simulated, &id);
|
||||
bool h = m->handleTelegram(about, data, simulated, &ids);
|
||||
if (h) handled = true;
|
||||
}
|
||||
if (isVerboseEnabled() && !handled)
|
||||
{
|
||||
verbose("(wmbus) telegram from %s ignored by all configured meters!\n", id.c_str());
|
||||
verbose("(wmbus) telegram from %s ignored by all configured meters!\n", ids.c_str());
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
@ -266,10 +267,10 @@ LIST_OF_METERS
|
|||
|
||||
bool MeterCommonImplementation::isTelegramForMe(Telegram *t)
|
||||
{
|
||||
debug("(meter) %s: for me? %s\n", name_.c_str(), t->id.c_str());
|
||||
debug("(meter) %s: for me? %s\n", name_.c_str(), t->idsc.c_str());
|
||||
|
||||
bool used_wildcard = false;
|
||||
bool id_match = doesIdMatchExpressions(t->id, ids_, &used_wildcard);
|
||||
bool id_match = doesIdsMatchExpressions(t->ids, ids_, &used_wildcard);
|
||||
|
||||
if (!id_match) {
|
||||
// The id must match.
|
||||
|
@ -278,6 +279,10 @@ bool MeterCommonImplementation::isTelegramForMe(Telegram *t)
|
|||
}
|
||||
|
||||
bool valid_driver = isMeterDriverValid(type_, t->dll_mfct, t->dll_type, t->dll_version);
|
||||
if (!valid_driver && t->tpl_id_found)
|
||||
{
|
||||
valid_driver = isMeterDriverValid(type_, t->tpl_mfct, t->tpl_type, t->tpl_version);
|
||||
}
|
||||
|
||||
if (!valid_driver)
|
||||
{
|
||||
|
@ -291,7 +296,7 @@ bool MeterCommonImplementation::isTelegramForMe(Telegram *t)
|
|||
// to many meters and some received matched meter telegrams are not from the right meter type,
|
||||
// ie their driver does not match. Lets just ignore telegrams that probably cannot be decoded properly.
|
||||
verbose("(meter) ignoring telegram from %s since it matched a wildcard id rule but driver does not match.\n",
|
||||
t->id.c_str());
|
||||
t->idsc.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -363,7 +368,14 @@ string concatAllFields(Meter *m, Telegram *t, char c, vector<Print> &prints, vec
|
|||
string s;
|
||||
s = "";
|
||||
s += m->name() + c;
|
||||
s += t->id + c;
|
||||
if (t->ids.size() > 0)
|
||||
{
|
||||
s += t->ids.back() + c;
|
||||
}
|
||||
else
|
||||
{
|
||||
s += c;
|
||||
}
|
||||
for (Print p : prints)
|
||||
{
|
||||
if (p.field)
|
||||
|
@ -409,7 +421,7 @@ string concatFields(Meter *m, Telegram *t, char c, vector<Print> &prints, vector
|
|||
}
|
||||
if (field == "id")
|
||||
{
|
||||
s += t->id + c;
|
||||
s += t->ids.back() + c;
|
||||
continue;
|
||||
}
|
||||
if (field == "timestamp")
|
||||
|
@ -473,7 +485,7 @@ string concatFields(Meter *m, Telegram *t, char c, vector<Print> &prints, vector
|
|||
return s;
|
||||
}
|
||||
|
||||
bool MeterCommonImplementation::handleTelegram(AboutTelegram &about, vector<uchar> input_frame, bool simulated, string *id)
|
||||
bool MeterCommonImplementation::handleTelegram(AboutTelegram &about, vector<uchar> input_frame, bool simulated, string *ids)
|
||||
{
|
||||
Telegram t;
|
||||
t.about = about;
|
||||
|
@ -481,7 +493,7 @@ bool MeterCommonImplementation::handleTelegram(AboutTelegram &about, vector<ucha
|
|||
|
||||
if (simulated) t.markAsSimulated();
|
||||
|
||||
*id = t.id;
|
||||
*ids = t.idsc;
|
||||
|
||||
if (!ok || !isTelegramForMe(&t))
|
||||
{
|
||||
|
@ -489,15 +501,15 @@ bool MeterCommonImplementation::handleTelegram(AboutTelegram &about, vector<ucha
|
|||
return false;
|
||||
}
|
||||
|
||||
verbose("(meter) %s %s handling telegram from %s\n", name().c_str(), meterName().c_str(), t.id.c_str());
|
||||
verbose("(meter) %s %s handling telegram from %s\n", name().c_str(), meterName().c_str(), t.ids.back().c_str());
|
||||
|
||||
if (isDebugEnabled())
|
||||
{
|
||||
string msg = bin2hex(input_frame);
|
||||
debug("(meter) %s %s \"%s\"\n", name().c_str(), t.id.c_str(), msg.c_str());
|
||||
debug("(meter) %s %s \"%s\"\n", name().c_str(), t.ids.back().c_str(), msg.c_str());
|
||||
}
|
||||
|
||||
ok = t.parse(input_frame, &meter_keys_);
|
||||
ok = t.parse(input_frame, &meter_keys_, true);
|
||||
if (!ok)
|
||||
{
|
||||
// Ignoring telegram since it could not be parsed.
|
||||
|
@ -533,12 +545,33 @@ void MeterCommonImplementation::printMeter(Telegram *t,
|
|||
*human_readable = concatFields(this, t, '\t', prints_, conversions_, true, selected_fields);
|
||||
*fields = concatFields(this, t, separator, prints_, conversions_, false, selected_fields);
|
||||
|
||||
string mfct;
|
||||
if (t->tpl_id_found)
|
||||
{
|
||||
mfct = mediaTypeJSON(t->tpl_type, t->tpl_mfct);
|
||||
}
|
||||
else if (t->ell_id_found)
|
||||
{
|
||||
mfct = mediaTypeJSON(t->ell_type, t->ell_mfct);
|
||||
}
|
||||
else
|
||||
{
|
||||
mfct = mediaTypeJSON(t->dll_type, t->dll_mfct);
|
||||
}
|
||||
|
||||
string s;
|
||||
s += "{";
|
||||
s += "\"media\":\""+mediaTypeJSON(t->dll_type, t->dll_mfct)+"\",";
|
||||
s += "\"media\":\""+mfct+"\",";
|
||||
s += "\"meter\":\""+meterName()+"\",";
|
||||
s += "\"name\":\""+name()+"\",";
|
||||
s += "\"id\":\""+t->id+"\",";
|
||||
if (t->ids.size() > 0)
|
||||
{
|
||||
s += "\"id\":\""+t->ids.back()+"\",";
|
||||
}
|
||||
else
|
||||
{
|
||||
s += "\"id\":\"\",";
|
||||
}
|
||||
for (Print p : prints_)
|
||||
{
|
||||
if (p.json)
|
||||
|
@ -583,7 +616,14 @@ void MeterCommonImplementation::printMeter(Telegram *t,
|
|||
envs->push_back(string("METER_JSON=")+*json);
|
||||
envs->push_back(string("METER_TYPE=")+meterName());
|
||||
envs->push_back(string("METER_NAME=")+name());
|
||||
envs->push_back(string("METER_ID=")+t->id);
|
||||
if (t->ids.size() > 0)
|
||||
{
|
||||
envs->push_back(string("METER_ID=")+t->ids.back());
|
||||
}
|
||||
else
|
||||
{
|
||||
envs->push_back(string("METER_ID="));
|
||||
}
|
||||
|
||||
for (Print p : prints_)
|
||||
{
|
||||
|
@ -683,7 +723,6 @@ ELLSecurityMode MeterCommonImplementation::expectedELLSecurityMode()
|
|||
|
||||
void detectMeterDriver(int manufacturer, int media, int version, vector<string> *drivers)
|
||||
{
|
||||
drivers->clear();
|
||||
#define X(TY,MA,ME,VE) { if (manufacturer == MA && (media == ME || ME == -1) && (version == VE || VE == -1)) { drivers->push_back(toMeterName(MeterType::TY)); }}
|
||||
METER_DETECTION
|
||||
#undef X
|
||||
|
|
|
@ -91,10 +91,10 @@ void Printer::printFiles(Meter *meter, Telegram *t, string &human_readable, stri
|
|||
snprintf(filename, 127, "%s/%s", meterfiles_dir_.c_str(), meter->name().c_str());
|
||||
break;
|
||||
case MeterFileNaming::Id:
|
||||
snprintf(filename, 127, "%s/%s", meterfiles_dir_.c_str(), t->id.c_str());
|
||||
snprintf(filename, 127, "%s/%s", meterfiles_dir_.c_str(), t->ids.back().c_str());
|
||||
break;
|
||||
case MeterFileNaming::NameId:
|
||||
snprintf(filename, 127, "%s/%s-%s", meterfiles_dir_.c_str(), meter->name().c_str(), t->id.c_str());
|
||||
snprintf(filename, 127, "%s/%s-%s", meterfiles_dir_.c_str(), meter->name().c_str(), t->ids.back().c_str());
|
||||
break;
|
||||
}
|
||||
string stamp;
|
||||
|
|
17
src/util.cc
17
src/util.cc
|
@ -622,7 +622,22 @@ bool hasWildCard(string &mes)
|
|||
return mes.find('*') != string::npos;
|
||||
}
|
||||
|
||||
bool doesIdMatchExpressions(string& id, vector<string>& mes, bool *used_wildcard)
|
||||
bool doesIdsMatchExpressions(vector<string> &ids, vector<string>& mes, bool *used_wildcard)
|
||||
{
|
||||
bool match = false;
|
||||
for (string &id : ids)
|
||||
{
|
||||
if (doesIdMatchExpressions(id, mes, used_wildcard))
|
||||
{
|
||||
match = true;
|
||||
}
|
||||
// Go through all ids even though there is an early match.
|
||||
// This way we can see if theres an exact match later.
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
bool doesIdMatchExpressions(string id, vector<string>& mes, bool *used_wildcard)
|
||||
{
|
||||
bool found_match = false;
|
||||
bool found_negative_match = false;
|
||||
|
|
|
@ -104,8 +104,9 @@ void setAlarmShells(std::vector<std::string> &alarm_shells);
|
|||
|
||||
bool isValidMatchExpression(std::string id, bool non_compliant);
|
||||
bool isValidMatchExpressions(std::string ids, bool non_compliant);
|
||||
bool doesIdMatchExpression(std::string id, std::string match);
|
||||
bool doesIdMatchExpressions(std::string& id, std::vector<std::string>& ids, bool *used_wildcard);
|
||||
bool doesIdMatchExpression(std::string id, std::string match_rule);
|
||||
bool doesIdMatchExpressions(std::string id, std::vector<std::string>& match_rules, bool *used_wildcard);
|
||||
bool doesIdsMatchExpressions(std::vector<std::string> &ids, std::vector<std::string>& match_rules, bool *used_wildcard);
|
||||
bool isValidId(std::string id, bool accept_non_compliant);
|
||||
|
||||
bool isValidKey(std::string& key, MeterType mt);
|
||||
|
|
74
src/wmbus.cc
74
src/wmbus.cc
|
@ -238,6 +238,18 @@ void Telegram::print()
|
|||
|
||||
notice(" ver: 0x%02x\n", dll_version);
|
||||
|
||||
if (tpl_id_found)
|
||||
{
|
||||
notice(" Concerning meter: %02x%02x%02x%02x\n", tpl_id_b[3],tpl_id_b[2],tpl_id_b[1],tpl_id_b[0]);
|
||||
notice(" manufacturer: (%s) %s (0x%02x)\n",
|
||||
manufacturerFlag(tpl_mfct).c_str(),
|
||||
manufacturer(tpl_mfct).c_str(),
|
||||
tpl_mfct);
|
||||
notice(" type: %s (0x%02x)\n", mediaType(tpl_type, dll_mfct).c_str(), tpl_type);
|
||||
|
||||
notice(" ver: 0x%02x\n", tpl_version);
|
||||
|
||||
}
|
||||
if (about.device != "")
|
||||
{
|
||||
notice(" device: %s\n", about.device.c_str());
|
||||
|
@ -804,9 +816,12 @@ bool Telegram::parseDLL(vector<uchar>::iterator &pos)
|
|||
dll_id[i] = *(pos+3-i);
|
||||
}
|
||||
}
|
||||
strprintf(id, "%02x%02x%02x%02x", *(pos+3), *(pos+2), *(pos+1), *(pos+0));
|
||||
// Add dll_id to ids.
|
||||
string id = tostrprintf("%02x%02x%02x%02x", *(pos+3), *(pos+2), *(pos+1), *(pos+0));
|
||||
ids.push_back(id);
|
||||
idsc = id;
|
||||
addExplanationAndIncrementPos(pos, 4, "%02x%02x%02x%02x dll-id (%s)",
|
||||
*(pos+0), *(pos+1), *(pos+2), *(pos+3), id.c_str());
|
||||
*(pos+0), *(pos+1), *(pos+2), *(pos+3), ids.back().c_str());
|
||||
|
||||
dll_version = *(pos+0);
|
||||
dll_type = *(pos+1);
|
||||
|
@ -893,6 +908,10 @@ bool Telegram::parseELL(vector<uchar>::iterator &pos)
|
|||
ell_id_b[2] = *(pos+2);
|
||||
ell_id_b[3] = *(pos+3);
|
||||
|
||||
// Add ell_id to ids.
|
||||
string id = tostrprintf("%02x%02x%02x%02x", *(pos+3), *(pos+2), *(pos+1), *(pos+0));
|
||||
ids.push_back(id);
|
||||
idsc = idsc+","+id;
|
||||
addExplanationAndIncrementPos(pos, 4, "%02x%02x%02x%02x ell-id",
|
||||
ell_id_b[0], ell_id_b[1], ell_id_b[2], ell_id_b[3]);
|
||||
|
||||
|
@ -922,12 +941,10 @@ bool Telegram::parseELL(vector<uchar>::iterator &pos)
|
|||
|
||||
if (ell_sec_mode == ELLSecurityMode::AES_CTR)
|
||||
{
|
||||
bool decrypt_ok = decrypt_ELL_AES_CTR(this, frame, pos, meter_keys->confidentiality_key);
|
||||
// Actually this ctr decryption always succeeds, if wrong key, it will decrypt to garbage.
|
||||
if (!decrypt_ok)
|
||||
if (meter_keys)
|
||||
{
|
||||
decryption_failed = true;
|
||||
return true;
|
||||
decrypt_ELL_AES_CTR(this, frame, pos, meter_keys->confidentiality_key);
|
||||
// Actually this ctr decryption always succeeds, if wrong key, it will decrypt to garbage.
|
||||
}
|
||||
// Now the frame from pos and onwards has been decrypted, perhaps.
|
||||
}
|
||||
|
@ -1199,7 +1216,7 @@ bool Telegram::parseTPLConfig(std::vector<uchar>::iterator &pos)
|
|||
|
||||
debugPayload("(wmbus) input to kdf for enc", input);
|
||||
|
||||
if (meter_keys->confidentiality_key.size() != 16)
|
||||
if (meter_keys == NULL || meter_keys->confidentiality_key.size() != 16)
|
||||
{
|
||||
if (isSimulated())
|
||||
{
|
||||
|
@ -1256,6 +1273,10 @@ bool Telegram::parseLongTPL(std::vector<uchar>::iterator &pos)
|
|||
tpl_id_b[2] = *(pos+2);
|
||||
tpl_id_b[3] = *(pos+3);
|
||||
|
||||
// Add the tpl_id to ids.
|
||||
string id = tostrprintf("%02x%02x%02x%02x", *(pos+3), *(pos+2), *(pos+1), *(pos+0));
|
||||
ids.push_back(id);
|
||||
idsc = idsc+","+id;
|
||||
addExplanationAndIncrementPos(pos, 4, "%02x%02x%02x%02x tpl-id (%02x%02x%02x%02x)", tpl_id_b[0], tpl_id_b[1], tpl_id_b[2], tpl_id_b[3],
|
||||
tpl_id_b[3], tpl_id_b[2], tpl_id_b[1], tpl_id_b[0]);
|
||||
|
||||
|
@ -1322,6 +1343,7 @@ bool Telegram::potentiallyDecrypt(vector<uchar>::iterator &pos)
|
|||
{
|
||||
if (tpl_sec_mode == TPLSecurityMode::AES_CBC_IV)
|
||||
{
|
||||
if (!meter_keys) return false;
|
||||
bool ok = decrypt_TPL_AES_CBC_IV(this, frame, pos, meter_keys->confidentiality_key);
|
||||
if (!ok) return false;
|
||||
// Now the frame from pos and onwards has been decrypted.
|
||||
|
@ -1350,7 +1372,7 @@ bool Telegram::potentiallyDecrypt(vector<uchar>::iterator &pos)
|
|||
}
|
||||
else if (tpl_sec_mode == TPLSecurityMode::AES_CBC_NO_IV)
|
||||
{
|
||||
if (!meter_keys->hasConfidentialityKey() && isSimulated())
|
||||
if (meter_keys == NULL || (!meter_keys->hasConfidentialityKey() && isSimulated()))
|
||||
{
|
||||
CHECK(2);
|
||||
addExplanationAndIncrementPos(pos, 2, "%02x%02x (already) decrypted check bytes", *(pos+0), *(pos+1));
|
||||
|
@ -1564,26 +1586,42 @@ bool Telegram::parseTPL(vector<uchar>::iterator &pos)
|
|||
bool Telegram::parseHeader(vector<uchar> &input_frame)
|
||||
{
|
||||
bool ok;
|
||||
// Parsing the header is used to extract the ids, so that we can
|
||||
// match the telegram towards any known ids and thus keys.
|
||||
// No need to warn.
|
||||
parser_warns_ = false;
|
||||
decryption_failed = false;
|
||||
explanations.clear();
|
||||
frame = input_frame;
|
||||
vector<uchar>::iterator pos = frame.begin();
|
||||
// Parsed accumulates parsed bytes.
|
||||
parsed.clear();
|
||||
|
||||
// ┌──────────────────────────────────────────────┐
|
||||
// │ │
|
||||
// │ Parse DLL Data Link Layer for Wireless MBUS. │
|
||||
// │ │
|
||||
// └──────────────────────────────────────────────┘
|
||||
|
||||
ok = parseDLL(pos);
|
||||
if (!ok) return false;
|
||||
|
||||
// At the worst, only the DLL is parsed. That is fine.
|
||||
ok = parseELL(pos);
|
||||
if (!ok) return true;
|
||||
// Could not decrypt stop here.
|
||||
if (decryption_failed) return true;
|
||||
|
||||
ok = parseNWL(pos);
|
||||
if (!ok) return true;
|
||||
|
||||
ok = parseAFL(pos);
|
||||
if (!ok) return true;
|
||||
|
||||
ok = parseTPL(pos);
|
||||
if (!ok) return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Telegram::parse(vector<uchar> &input_frame, MeterKeys *mk)
|
||||
bool Telegram::parse(vector<uchar> &input_frame, MeterKeys *mk, bool warn)
|
||||
{
|
||||
parser_warns_ = warn;
|
||||
decryption_failed = false;
|
||||
explanations.clear();
|
||||
meter_keys = mk;
|
||||
assert(meter_keys != NULL);
|
||||
|
@ -1663,6 +1701,10 @@ string Telegram::autoDetectPossibleDrivers()
|
|||
{
|
||||
vector<string> drivers;
|
||||
detectMeterDriver(dll_mfct, dll_type, dll_version, &drivers);
|
||||
if (tpl_id_found)
|
||||
{
|
||||
detectMeterDriver(tpl_mfct, tpl_type, tpl_version, &drivers);
|
||||
}
|
||||
string possibles;
|
||||
for (string d : drivers) possibles = possibles+d+" ";
|
||||
if (possibles != "") possibles.pop_back();
|
||||
|
|
10
src/wmbus.h
10
src/wmbus.h
|
@ -345,8 +345,11 @@ struct Telegram
|
|||
// If a warning is printed mark this.
|
||||
bool triggered_warning {};
|
||||
|
||||
// The meter address as a string usually printed on the meter.
|
||||
string id;
|
||||
// The different ids found, the first is th dll_id, ell_id, nwl_id, and the last is the tpl_id.
|
||||
vector<string> ids;
|
||||
// Ids separated by commas
|
||||
string idsc;
|
||||
|
||||
// If decryption failed, set this to true, to prevent further processing.
|
||||
bool decryption_failed {};
|
||||
|
||||
|
@ -443,8 +446,7 @@ struct Telegram
|
|||
bool handled {}; // Set to true, when a meter has accepted the telegram.
|
||||
|
||||
bool parseHeader(vector<uchar> &input_frame);
|
||||
bool parse(vector<uchar> &input_frame, MeterKeys *mk);
|
||||
void parserNoWarnings() { parser_warns_ = false; }
|
||||
bool parse(vector<uchar> &input_frame, MeterKeys *mk, bool warn);
|
||||
void print();
|
||||
|
||||
// A vector of indentations and explanations, to be printed
|
||||
|
|
5
test.sh
5
test.sh
|
@ -96,6 +96,11 @@ if [ "$?" != "0" ]; then RC="1"; fi
|
|||
tests/test_ignore_duplicates.sh $PROG
|
||||
if [ "$?" != "0" ]; then RC="1"; fi
|
||||
|
||||
./tests/test_match_dll_and_tpl_id.sh $PROG
|
||||
if [ "$?" != "0" ]; then RC="1"; fi
|
||||
|
||||
echo Slower tests...
|
||||
|
||||
tests/test_pipe.sh $PROG
|
||||
if [ "$?" != "0" ]; then RC="1"; fi
|
||||
|
||||
|
|
|
@ -15,8 +15,7 @@ cat simulations/simulation_aes.msg | grep '^[CT]' | tr -d '#' > $TEST/test_input
|
|||
cat $TEST/test_input.txt | $PROG --format=json "stdin:rtlwmbus" \
|
||||
ApWater apator162 88888888 00000000000000000000000000000000 \
|
||||
Vatten multical21 76348799 28F64A24988064A079AA2C807D6102AE \
|
||||
Wasser supercom587 77777777 5065747220486F6C79737A6577736B69 \
|
||||
> $TEST/test_output.txt 2> $TEST/test_stderr.txt
|
||||
Wasser supercom587 77777777 5065747220486F6C79737A6577736B69 > $TEST/test_output.txt 2> $TEST/test_stderr.txt
|
||||
|
||||
cat $TEST/test_output.txt | sed 's/"timestamp":"....-..-..T..:..:..Z"/"timestamp":"1111-11-11T11:11:11Z"/' > $TEST/test_response.txt
|
||||
diff $TEST/test_expected.txt $TEST/test_response.txt
|
||||
|
|
|
@ -79,7 +79,11 @@ Received telegram from: 88018801
|
|||
manufacturer: (INE) INNOTAS Elektronik, Germany (0x25c5)
|
||||
type: Heat Cost Allocator (0x08)
|
||||
ver: 0x55
|
||||
driver: eurisii
|
||||
Concerning meter: 88018801
|
||||
manufacturer: (INE) INNOTAS Elektronik, Germany (0x25c5)
|
||||
type: Heat Cost Allocator (0x08)
|
||||
ver: 0x55
|
||||
driver: eurisii eurisii
|
||||
Received telegram from: 00010204
|
||||
manufacturer: (LAS) Lansen Systems, Sweden (0x3033)
|
||||
type: Smoke detector (0x1a)
|
||||
|
@ -154,16 +158,28 @@ Received telegram from: 22992299
|
|||
manufacturer: (EBZ) eBZ, Germany (0x145a)
|
||||
type: Radio converter (meter side) (0x37)
|
||||
ver: 0x02
|
||||
Concerning meter: 22992299
|
||||
manufacturer: (EBZ) eBZ, Germany (0x145a)
|
||||
type: Electricity meter (0x02)
|
||||
ver: 0x01
|
||||
driver: ebzwmbe
|
||||
Received telegram from: 77997799
|
||||
manufacturer: (ESY) EasyMeter (0x1679)
|
||||
type: Radio converter (meter side) (0x37)
|
||||
ver: 0x30
|
||||
Concerning meter: 77997799
|
||||
manufacturer: (ETY) Unknown (0x1699)
|
||||
type: Electricity meter (0x02)
|
||||
ver: 0x11
|
||||
driver: esyswm
|
||||
Received telegram from: 77997799
|
||||
manufacturer: (ESY) EasyMeter (0x1679)
|
||||
type: Radio converter (meter side) (0x37)
|
||||
ver: 0x30
|
||||
Concerning meter: 77997799
|
||||
manufacturer: (ESY) EasyMeter (0x1679)
|
||||
type: Electricity meter (0x02)
|
||||
ver: 0x11
|
||||
driver: esyswm
|
||||
Received telegram from: 55995599
|
||||
manufacturer: (EMH) EMH metering formerly EMH Elektrizitatszahler (0x15a8)
|
||||
|
|
Ładowanie…
Reference in New Issue