kopia lustrzana https://github.com/weetmuts/wmbusmeters
Add ability for driver to force mfct specific data after a specific point in telegram.
rodzic
9c39e911c7
commit
504a5cf345
|
@ -38,7 +38,7 @@ namespace
|
|||
di.addLinkMode(LinkMode::T1);
|
||||
di.setMeterType(MeterType::HeatCostAllocationMeter);
|
||||
di.addDetection(MANUFACTURER_BFW,0x08, 0x02);
|
||||
|
||||
di.forceMfctIndex(2); // First two bytes are 2f2f after that its completely mfct specific.
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
|
||||
});
|
||||
|
||||
|
@ -116,10 +116,24 @@ namespace
|
|||
|
||||
if (content.size() < 40) return;
|
||||
|
||||
current_hca_ = content[6]*256 + content[7];
|
||||
|
||||
string msg = tostrprintf("*** %02X%02X \"current_hca\":%g", content[6], content[7], current_hca_);
|
||||
t->addSpecialExplanation(6+t->header_size, 2, KindOfData::CONTENT, Understanding::FULL, msg.c_str());
|
||||
|
||||
prev_hca_ = content[4]*256 + content[5];
|
||||
|
||||
msg = tostrprintf("*** %02X%02X \"prev_hca\":%g", content[4], content[5], prev_hca_);
|
||||
t->addSpecialExplanation(4+t->header_size, 2, KindOfData::CONTENT, Understanding::FULL, msg.c_str());
|
||||
|
||||
device_date_ = tostrprintf("20%02x-%02x-%02x", content[39], content[39-1], content[39-2]);
|
||||
|
||||
current_hca_ = content[6]*256 + content[7];
|
||||
prev_hca_ = content[4]*256 + content[5];
|
||||
msg = tostrprintf("*** %02X%02X%02X \"device_date\":\"%s\"", content[39-2], content[39-1], content[39],
|
||||
device_date_.c_str());
|
||||
t->addSpecialExplanation(39-2+t->header_size, 3, KindOfData::CONTENT, Understanding::FULL, msg.c_str());
|
||||
|
||||
|
||||
|
||||
|
||||
for (int i=0; i<18; ++i)
|
||||
{
|
||||
|
|
|
@ -149,6 +149,7 @@ bool parseDV(Telegram *t,
|
|||
vector<uchar>::iterator format_end;
|
||||
bool data_has_difvifs = true;
|
||||
bool variable_length = false;
|
||||
int force_mfct_index = t->force_mfct_index;
|
||||
|
||||
if (format == NULL) {
|
||||
// No format string was supplied, we therefore assume
|
||||
|
@ -198,12 +199,29 @@ bool parseDV(Telegram *t,
|
|||
id_bytes.clear();
|
||||
DEBUG_PARSER("(dvparser debug) Remaining format data %ju\n", std::distance(*format,format_end));
|
||||
if (*format == format_end) break;
|
||||
|
||||
if (force_mfct_index != -1)
|
||||
{
|
||||
// This is an old meter without a proper 0f or other hear start manufacturer data marker.
|
||||
int index = std::distance(data_start, data);
|
||||
|
||||
if (index >= force_mfct_index)
|
||||
{
|
||||
DEBUG_PARSER("(dvparser) manufacturer specific data, parsing is done.\n", dif);
|
||||
size_t datalen = std::distance(data, data_end);
|
||||
string value = bin2hex(data, data_end, datalen);
|
||||
t->addExplanationAndIncrementPos(data, datalen, KindOfData::CONTENT, Understanding::NONE, "manufacturer specific data %s", value.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uchar dif = **format;
|
||||
|
||||
MeasurementType mt = difMeasurementType(dif);
|
||||
int datalen = difLenBytes(dif);
|
||||
DEBUG_PARSER("(dvparser debug) dif=%02x datalen=%d \"%s\" type=%s\n", dif, datalen, difType(dif).c_str(),
|
||||
measurementTypeName(mt).c_str());
|
||||
|
||||
if (datalen == -2)
|
||||
{
|
||||
if (dif == 0x0f)
|
||||
|
@ -213,7 +231,7 @@ bool parseDV(Telegram *t,
|
|||
string value = bin2hex(data+1, data_end, datalen-1);
|
||||
t->mfct_0f_index = 1+std::distance(data_start, data);
|
||||
assert(t->mfct_0f_index >= 0);
|
||||
t->addExplanationAndIncrementPos(data, datalen, KindOfData::PROTOCOL, Understanding::NONE, "%02X manufacturer specific data %s", dif, value.c_str());
|
||||
t->addExplanationAndIncrementPos(data, datalen, KindOfData::CONTENT, Understanding::NONE, "%02X manufacturer specific data %s", dif, value.c_str());
|
||||
break;
|
||||
}
|
||||
DEBUG_PARSER("(dvparser) reached unknown dif %02x treating remaining data as manufacturer specific, parsing is done.\n", dif);
|
||||
|
@ -221,7 +239,7 @@ bool parseDV(Telegram *t,
|
|||
string value = bin2hex(data+1, data_end, datalen-1);
|
||||
t->mfct_0f_index = 1+std::distance(data_start, data);
|
||||
assert(t->mfct_0f_index >= 0);
|
||||
t->addExplanationAndIncrementPos(data, datalen, KindOfData::PROTOCOL, Understanding::NONE, "%02X unknown dif treating remaining data as mfct specific %s", dif, value.c_str());
|
||||
t->addExplanationAndIncrementPos(data, datalen, KindOfData::CONTENT, Understanding::NONE, "%02X unknown dif treating remaining data as mfct specific %s", dif, value.c_str());
|
||||
break;
|
||||
}
|
||||
if (dif == 0x2f) {
|
||||
|
|
|
@ -770,6 +770,7 @@ MeterCommonImplementation::MeterCommonImplementation(MeterInfo &mi,
|
|||
}
|
||||
|
||||
link_modes_.unionLinkModeSet(di.linkModes());
|
||||
force_mfct_index_ = di.forceMfctIndex();
|
||||
}
|
||||
|
||||
void MeterCommonImplementation::addConversions(std::vector<Unit> cs)
|
||||
|
@ -1735,6 +1736,12 @@ bool MeterCommonImplementation::handleTelegram(AboutTelegram &about, vector<ucha
|
|||
debug("(meter) %s %s \"%s\"\n", name().c_str(), t.ids.back().c_str(), msg.c_str());
|
||||
}
|
||||
|
||||
// For older meters with manufacturer specific data without a nice 0f dif marker.
|
||||
if (force_mfct_index_ != -1)
|
||||
{
|
||||
t.force_mfct_index = force_mfct_index_;
|
||||
}
|
||||
|
||||
ok = t.parse(input_frame, &meter_keys_, true);
|
||||
if (!ok)
|
||||
{
|
||||
|
|
|
@ -236,6 +236,7 @@ private:
|
|||
function<shared_ptr<Meter>(MeterInfo&,DriverInfo&di)> constructor_; // Invoke this to create an instance of the driver.
|
||||
vector<DriverDetect> detect_;
|
||||
vector<string> default_fields_;
|
||||
int force_mfct_index_ = -1; // Used for meters not declaring mfct specific data using the dif 0f.
|
||||
|
||||
public:
|
||||
DriverInfo() {};
|
||||
|
@ -245,6 +246,7 @@ public:
|
|||
void setMeterType(MeterType t) { type_ = t; }
|
||||
void setDefaultFields(string f) { default_fields_ = splitString(f, ','); }
|
||||
void addLinkMode(LinkMode lm) { linkmodes_.addLinkMode(lm); }
|
||||
void forceMfctIndex(int i) { force_mfct_index_ = i; }
|
||||
void addMfctTPLStatusBits(Translate::Lookup lookup) { mfct_tpl_status_bits_ = lookup; }
|
||||
void setConstructor(function<shared_ptr<Meter>(MeterInfo&,DriverInfo&)> c) { constructor_ = c; }
|
||||
void addDetection(uint16_t mfct, uchar type, uchar ver) { detect_.push_back({ mfct, type, ver }); }
|
||||
|
@ -261,6 +263,7 @@ public:
|
|||
bool detect(uint16_t mfct, uchar type, uchar version);
|
||||
bool isValidMedia(uchar type);
|
||||
bool isCloseEnoughMedia(uchar type);
|
||||
int forceMfctIndex() { return force_mfct_index_; }
|
||||
};
|
||||
|
||||
bool registerDriver(function<void(DriverInfo&di)> setup);
|
||||
|
|
|
@ -245,6 +245,8 @@ protected:
|
|||
vector<string> &selectedFields() { return selected_fields_; }
|
||||
void setSelectedFields(vector<string> &f) { selected_fields_ = f; }
|
||||
|
||||
void forceMfctIndex(int i) { force_mfct_index_ = i; }
|
||||
|
||||
private:
|
||||
|
||||
int index_ {};
|
||||
|
@ -266,8 +268,10 @@ private:
|
|||
vector<string> extra_constant_fields_;
|
||||
time_t poll_interval_ {};
|
||||
Translate::Lookup mfct_tpl_status_bits_ = NoLookup;
|
||||
int force_mfct_index_ = -1;
|
||||
|
||||
protected:
|
||||
|
||||
vector<Unit> conversions_;
|
||||
vector<FieldInfo> field_infos_;
|
||||
vector<string> field_names_;
|
||||
|
|
|
@ -515,6 +515,7 @@ public:
|
|||
int header_size {}; // Size of headers before the APL content.
|
||||
int suffix_size {}; // Size of suffix after the APL content. Usually empty, but can be MACs!
|
||||
int mfct_0f_index = -1; // -1 if not found, else index of the 0f byte, if found, inside the difvif data after the header.
|
||||
int force_mfct_index = -1; // Force all data after this offset to be mfct specific. Used for meters not using 0f.
|
||||
void extractFrame(vector<uchar> *fr); // Extract to full frame.
|
||||
void extractPayload(vector<uchar> *pl); // Extract frame data containing the measurements, after the header and not the suffix.
|
||||
void extractMfctData(vector<uchar> *pl); // Extract frame data after the DIF 0x0F.
|
||||
|
|
Ładowanie…
Reference in New Issue