Add ability for driver to force mfct specific data after a specific point in telegram.

pull/631/head
Fredrik Öhrström 2022-09-28 21:20:43 +02:00
rodzic 9c39e911c7
commit 504a5cf345
6 zmienionych plików z 52 dodań i 5 usunięć

Wyświetl plik

@ -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)
{

Wyświetl plik

@ -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) {

Wyświetl plik

@ -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)
{

Wyświetl plik

@ -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);

Wyświetl plik

@ -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_;

Wyświetl plik

@ -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.