kopia lustrzana https://github.com/weetmuts/wmbusmeters
Added gwfwater. Require di.usesProcessContent() to setup for mftc specific decoding.
rodzic
ab9e4b3c1d
commit
e7d723f5c7
|
@ -35,6 +35,7 @@ namespace
|
|||
di.setMeterType(MeterType::WaterMeter);
|
||||
di.addLinkMode(LinkMode::T1);
|
||||
di.addDetection(0x8614/*APT?*/, 0x03, 0x03);
|
||||
di.usesProcessContent();
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
|
||||
});
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace
|
|||
di.addDetection(MANUFACTURER_APA, 0x06, 0x05);
|
||||
di.addDetection(MANUFACTURER_APA, 0x07, 0x05);
|
||||
di.addDetection(0x8614 /*APT?*/, 0x07, 0x05); // Older version of telegram that is not understood!
|
||||
di.usesProcessContent();
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
|
||||
});
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace
|
|||
di.setDefaultFields("name,id,total_m3,timestamp");
|
||||
di.setMeterType(MeterType::WaterMeter);
|
||||
di.addDetection(0x8614 /*APT?*/, 0x11, 0x04);
|
||||
di.usesProcessContent();
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
|
||||
});
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace
|
|||
di.setMeterType(MeterType::HeatCostAllocationMeter);
|
||||
di.addDetection(0x8614 /* APT? */, 0x08, 0x04);
|
||||
di.addDetection(0x8601 /* APA? */, 0x08, 0x04);
|
||||
di.usesProcessContent();
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
|
||||
});
|
||||
|
||||
|
|
|
@ -22,8 +22,6 @@ using namespace std;
|
|||
struct MeterAuto : public virtual MeterCommonImplementation
|
||||
{
|
||||
MeterAuto(MeterInfo &mi, DriverInfo &di);
|
||||
|
||||
void processContent(Telegram *t);
|
||||
};
|
||||
|
||||
bool ok = registerDriver([](DriverInfo&di)
|
||||
|
@ -44,7 +42,3 @@ shared_ptr<Meter> createAuto(MeterInfo &mi)
|
|||
di.setName("auto");
|
||||
return shared_ptr<Meter>(new MeterAuto(mi, di));
|
||||
}
|
||||
|
||||
void MeterAuto::processContent(Telegram *t)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace
|
|||
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.usesProcessContent();
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
|
||||
});
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace
|
|||
di.addDetection(MANUFACTURER_TCH, 0x43, 0x22);
|
||||
di.addDetection(MANUFACTURER_TCH, 0x43, 0x45);
|
||||
di.addDetection(MANUFACTURER_TCH, 0x43, 0x39);
|
||||
|
||||
di.usesProcessContent();
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
|
||||
});
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace
|
|||
di.addLinkMode(LinkMode::T1);
|
||||
di.addDetection(MANUFACTURER_TCH, 0x80, 0x69);
|
||||
di.addDetection(MANUFACTURER_TCH, 0x80, 0x94);
|
||||
|
||||
di.usesProcessContent();
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
Copyright (C) 2023 Fredrik Öhrström (gpl-3.0-or-later)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include"meters_common_implementation.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Driver : public virtual MeterCommonImplementation
|
||||
{
|
||||
Driver(MeterInfo &mi, DriverInfo &di);
|
||||
|
||||
void processContent(Telegram *t);
|
||||
};
|
||||
|
||||
static bool ok = registerDriver([](DriverInfo&di)
|
||||
{
|
||||
di.setName("gwfwater");
|
||||
di.setDefaultFields("name,id,total_m3,timestamp");
|
||||
di.setMeterType(MeterType::WaterMeter);
|
||||
di.addDetection(MANUFACTURER_GWF, 0x0e, 0x01);
|
||||
di.usesProcessContent();
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
|
||||
});
|
||||
|
||||
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
|
||||
{
|
||||
addOptionalCommonFields("actuality_duration_s");
|
||||
addOptionalFlowRelatedFields("total_m3,target_m3,target_date");
|
||||
|
||||
addStringField(
|
||||
"status",
|
||||
"Meter status.",
|
||||
PrintProperty::INCLUDE_TPL_STATUS | PrintProperty::STATUS);
|
||||
|
||||
addStringField(
|
||||
"mfct_status",
|
||||
"Mfct status bit.",
|
||||
PrintProperty::INJECT_INTO_STATUS | PrintProperty::HIDE);
|
||||
|
||||
addStringField(
|
||||
"power_mode",
|
||||
"Normal or saving.",
|
||||
DEFAULT_PRINT_PROPERTIES);
|
||||
|
||||
addNumericField(
|
||||
"battery",
|
||||
Quantity::Time,
|
||||
DEFAULT_PRINT_PROPERTIES,
|
||||
"Remaining battery life in years.",
|
||||
Unit::Year);
|
||||
}
|
||||
|
||||
void Driver::processContent(Telegram *t)
|
||||
{
|
||||
vector<uchar> bytes;
|
||||
t->extractMfctData(&bytes); // Extract raw frame data after the DIF 0x0F.
|
||||
|
||||
if (bytes.size() < 3) return;
|
||||
|
||||
uchar type = bytes[0];
|
||||
uchar a = bytes[1];
|
||||
uchar b = bytes[2];
|
||||
|
||||
if (type != 1)
|
||||
{
|
||||
setStringValue("mfct_status", tostrprintf("UKNOWN_MFCT_STATUS=%02x%02x%02x", type, a, b));
|
||||
return;
|
||||
}
|
||||
|
||||
string info;
|
||||
|
||||
if (a & 0x02) info += "CONTINUOUS_FLOW ";
|
||||
if (a & 0x08) info += "BROKEN_PIPE ";
|
||||
if (a & 0x20) info += "BATTERY_LOW ";
|
||||
if (a & 0x40) info += "BACKFLOW ";
|
||||
|
||||
if (info.size() > 0) info.pop_back();
|
||||
setStringValue("mfct_status", info);
|
||||
|
||||
setStringValue("power_mode", (b & 0x01) ? "SAVING" : "NORMAL");
|
||||
|
||||
double battery_semesters = (b >> 3); // Half years.
|
||||
setNumericValue("battery", Unit::Year, battery_semesters/2.0);
|
||||
}
|
||||
}
|
||||
|
||||
// Test: Wateroo gwfwater 20221031 NOKEY
|
||||
// telegram=|3144E61E31102220010E8C04F47ABE0420452F2F_037410000004133E0000004413FFFFFFFF426CFFFF0F0120012F2F2F2F2F|
|
||||
// {"actuality_duration_s": 16,"battery_y": 0,"id": "20221031","media": "bus/system component","meter": "gwfwater","name": "Wateroo","power_mode": "SAVING","status": "BATTERY_LOW POWER_LOW","target_datetime": "2128-03-31 00:00","target_m3": 4294967.295,"timestamp": "1111-11-11T11:11:11Z","total_m3": 0.062}
|
||||
// |Wateroo;20221031;0.062;1111-11-11 11:11.11
|
|
@ -34,7 +34,7 @@ namespace
|
|||
di.addLinkMode(LinkMode::T1);
|
||||
di.addDetection(MANUFACTURER_TCH, 0x62, 0x74);
|
||||
di.addDetection(MANUFACTURER_TCH, 0x72, 0x74);
|
||||
|
||||
di.usesProcessContent();
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
|
||||
});
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace
|
|||
di.addDetection(MANUFACTURER_TCH, 0x62, 0x70);
|
||||
di.addDetection(MANUFACTURER_TCH, 0x72, 0x95);
|
||||
di.addDetection(MANUFACTURER_TCH, 0x72, 0x70);
|
||||
|
||||
di.usesProcessContent();
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
|
||||
});
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace
|
|||
di.setMeterType(MeterType::WaterMeter);
|
||||
di.addLinkMode(LinkMode::T1);
|
||||
di.addDetection(MANUFACTURER_BMT, 0x07, 0x05);
|
||||
di.usesProcessContent();
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
|
||||
});
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace
|
|||
di.setMeterType(MeterType::SmokeDetector);
|
||||
di.addLinkMode(LinkMode::T1);
|
||||
di.addDetection(MANUFACTURER_TCH, 0xf0, 0x76);
|
||||
|
||||
di.usesProcessContent();
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
|
||||
});
|
||||
|
||||
|
|
|
@ -22,8 +22,6 @@ using namespace std;
|
|||
struct MeterUnknown : public virtual MeterCommonImplementation
|
||||
{
|
||||
MeterUnknown(MeterInfo &mi, DriverInfo &di);
|
||||
|
||||
void processContent(Telegram *t);
|
||||
};
|
||||
|
||||
static bool ok = registerDriver([](DriverInfo&di)
|
||||
|
@ -44,7 +42,3 @@ shared_ptr<Meter> createUnknown(MeterInfo &mi)
|
|||
di.setName("unknown");
|
||||
return shared_ptr<Meter>(new MeterUnknown(mi, di));
|
||||
}
|
||||
|
||||
void MeterUnknown::processContent(Telegram *t)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace
|
|||
di.addLinkMode(LinkMode::T1);
|
||||
di.addDetection(MANUFACTURER_TCH, 0x04, 0x27);
|
||||
di.addDetection(MANUFACTURER_TCH, 0xc3, 0x27);
|
||||
di.usesProcessContent();
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
|
||||
});
|
||||
|
||||
|
|
|
@ -162,11 +162,13 @@ bool lookupDriverInfo(const string& driver, DriverInfo *out_di)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
MeterCommonImplementation::MeterCommonImplementation(MeterInfo &mi,
|
||||
string driver) :
|
||||
driver_name_(driver), bus_(mi.bus), name_(mi.name), waiting_for_poll_response_sem_("waiting_for_poll_response")
|
||||
driver_name_(driver),
|
||||
bus_(mi.bus),
|
||||
name_(mi.name),
|
||||
waiting_for_poll_response_sem_("waiting_for_poll_response")
|
||||
{
|
||||
ids_ = mi.ids;
|
||||
idsc_ = toIdsCommaSeparated(ids_);
|
||||
|
@ -185,7 +187,7 @@ MeterCommonImplementation::MeterCommonImplementation(MeterInfo &mi,
|
|||
addExtraConstantField(j);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
MeterCommonImplementation::MeterCommonImplementation(MeterInfo &mi,
|
||||
DriverInfo &di) :
|
||||
type_(di.type()),
|
||||
|
@ -193,6 +195,7 @@ MeterCommonImplementation::MeterCommonImplementation(MeterInfo &mi,
|
|||
bus_(mi.bus),
|
||||
name_(mi.name),
|
||||
mfct_tpl_status_bits_(di.mfctTPLStatusBits()),
|
||||
has_process_content_(di.hasProcessContent()),
|
||||
waiting_for_poll_response_sem_("waiting_for_poll_response")
|
||||
{
|
||||
ids_ = mi.ids;
|
||||
|
@ -1082,8 +1085,11 @@ bool MeterCommonImplementation::handleTelegram(AboutTelegram &about, vector<ucha
|
|||
|
||||
// Invoke standardized field extractors!
|
||||
processFieldExtractors(&t);
|
||||
// Invoke tailor made meter specific parsing!
|
||||
processContent(&t);
|
||||
if (hasProcessContent())
|
||||
{
|
||||
// Invoke tailor made meter specific parsing!
|
||||
processContent(&t);
|
||||
}
|
||||
// Invoke any calculators working on the extracted fields.
|
||||
processFieldCalculators();
|
||||
// All done....
|
||||
|
@ -1225,6 +1231,11 @@ void MeterCommonImplementation::processContent(Telegram *t)
|
|||
{
|
||||
}
|
||||
|
||||
bool MeterCommonImplementation::hasProcessContent()
|
||||
{
|
||||
return has_process_content_;
|
||||
}
|
||||
|
||||
void MeterCommonImplementation::setNumericValue(FieldInfo *fi, DVEntry *dve, Unit u, double v)
|
||||
{
|
||||
if (fi->hasSetNumericValueOverride())
|
||||
|
@ -2676,6 +2687,36 @@ void MeterCommonImplementation::addOptionalFlowRelatedFields(string field_names)
|
|||
);
|
||||
}
|
||||
|
||||
if (checkIf(fields,"target_m3"))
|
||||
{
|
||||
addNumericFieldWithExtractor(
|
||||
"target",
|
||||
"The volume recorded by this meter at the target date.",
|
||||
DEFAULT_PRINT_PROPERTIES,
|
||||
Quantity::Volume,
|
||||
VifScaling::Auto,
|
||||
FieldMatcher::build()
|
||||
.set(MeasurementType::Instantaneous)
|
||||
.set(VIFRange::Volume)
|
||||
.set(StorageNr(1))
|
||||
);
|
||||
}
|
||||
|
||||
if (checkIf(fields,"target_date"))
|
||||
{
|
||||
addNumericFieldWithExtractor(
|
||||
"target",
|
||||
"The target date. Usually the end of the previous billing period.",
|
||||
DEFAULT_PRINT_PROPERTIES,
|
||||
Quantity::PointInTime,
|
||||
VifScaling::Auto,
|
||||
FieldMatcher::build()
|
||||
.set(MeasurementType::Instantaneous)
|
||||
.set(VIFRange::Date)
|
||||
.set(StorageNr(1))
|
||||
);
|
||||
}
|
||||
|
||||
if (checkIf(fields,"total_forward_m3"))
|
||||
{
|
||||
addNumericFieldWithExtractor(
|
||||
|
|
|
@ -215,7 +215,7 @@ public:
|
|||
bool isValidMedia(uchar type);
|
||||
bool isCloseEnoughMedia(uchar type);
|
||||
int forceMfctIndex() { return force_mfct_index_; }
|
||||
bool hasProcessContentCode() { return has_process_content_; }
|
||||
bool hasProcessContent() { return has_process_content_; }
|
||||
};
|
||||
|
||||
bool registerDriver(function<void(DriverInfo&di)> setup);
|
||||
|
|
|
@ -63,6 +63,7 @@ struct MeterCommonImplementation : public virtual Meter
|
|||
vector<string> &extraConstantFields();
|
||||
string name();
|
||||
DriverName driverName();
|
||||
bool hasProcessContent();
|
||||
|
||||
ELLSecurityMode expectedELLSecurityMode();
|
||||
TPLSecurityMode expectedTPLSecurityMode();
|
||||
|
@ -82,7 +83,7 @@ struct MeterCommonImplementation : public virtual Meter
|
|||
static bool isTelegramForMeter(Telegram *t, Meter *meter, MeterInfo *mi);
|
||||
MeterKeys *meterKeys();
|
||||
|
||||
MeterCommonImplementation(MeterInfo &mi, string driver);
|
||||
// MeterCommonImplementation(MeterInfo &mi, string driver);
|
||||
MeterCommonImplementation(MeterInfo &mi, DriverInfo &di);
|
||||
|
||||
~MeterCommonImplementation() = default;
|
||||
|
@ -134,9 +135,6 @@ protected:
|
|||
string help,
|
||||
Unit display_unit = Unit::Unknown); // If specified use this unit for the json field instead instead of the default unit.
|
||||
|
||||
#define SET_STRING_FUNC(varname) {[=](string s){varname = s;}}
|
||||
#define GET_STRING_FUNC(varname) {[=](){return varname; }}
|
||||
|
||||
void addStringFieldWithExtractor(
|
||||
string vname,
|
||||
string help,
|
||||
|
@ -228,6 +226,7 @@ private:
|
|||
time_t poll_interval_ {};
|
||||
Translate::Lookup mfct_tpl_status_bits_ = NoLookup;
|
||||
int force_mfct_index_ = -1;
|
||||
bool has_process_content_ = false;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue