kopia lustrzana https://github.com/weetmuts/wmbusmeters
Converted water meters to unit scaling.
rodzic
49f7410519
commit
2a47115cb9
|
@ -36,15 +36,15 @@ struct MeterApator162 : public virtual WaterMeter, public virtual MeterCommonImp
|
||||||
MeterApator162(WMBus *bus, string& name, string& id, string& key);
|
MeterApator162(WMBus *bus, string& name, string& id, string& key);
|
||||||
|
|
||||||
// Total water counted through the meter
|
// Total water counted through the meter
|
||||||
double totalWaterConsumption();
|
double totalWaterConsumption(Unit u);
|
||||||
bool hasTotalWaterConsumption();
|
bool hasTotalWaterConsumption();
|
||||||
double targetWaterConsumption();
|
double targetWaterConsumption(Unit u);
|
||||||
bool hasTargetWaterConsumption();
|
bool hasTargetWaterConsumption();
|
||||||
double maxFlow();
|
double maxFlow(Unit u);
|
||||||
bool hasMaxFlow();
|
bool hasMaxFlow();
|
||||||
double flowTemperature();
|
double flowTemperature(Unit u);
|
||||||
bool hasFlowTemperature();
|
bool hasFlowTemperature();
|
||||||
double externalTemperature();
|
double externalTemperature(Unit u);
|
||||||
bool hasExternalTemperature();
|
bool hasExternalTemperature();
|
||||||
|
|
||||||
string statusHumanReadable();
|
string statusHumanReadable();
|
||||||
|
@ -77,7 +77,7 @@ MeterApator162::MeterApator162(WMBus *bus, string& name, string& id, string& key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double MeterApator162::totalWaterConsumption()
|
double MeterApator162::totalWaterConsumption(Unit u)
|
||||||
{
|
{
|
||||||
return total_water_consumption_;
|
return total_water_consumption_;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ void MeterApator162::printMeter(Telegram *t,
|
||||||
"%s",
|
"%s",
|
||||||
name().c_str(),
|
name().c_str(),
|
||||||
t->id.c_str(),
|
t->id.c_str(),
|
||||||
totalWaterConsumption(),
|
totalWaterConsumption(Unit::M3),
|
||||||
datetimeOfUpdateHumanReadable().c_str());
|
datetimeOfUpdateHumanReadable().c_str());
|
||||||
|
|
||||||
*human_readable = buf;
|
*human_readable = buf;
|
||||||
|
@ -178,7 +178,7 @@ void MeterApator162::printMeter(Telegram *t,
|
||||||
"%s",
|
"%s",
|
||||||
name().c_str(), separator,
|
name().c_str(), separator,
|
||||||
t->id.c_str(), separator,
|
t->id.c_str(), separator,
|
||||||
totalWaterConsumption(), separator,
|
totalWaterConsumption(Unit::M3), separator,
|
||||||
datetimeOfUpdateRobot().c_str());
|
datetimeOfUpdateRobot().c_str());
|
||||||
|
|
||||||
*fields = buf;
|
*fields = buf;
|
||||||
|
@ -198,7 +198,7 @@ void MeterApator162::printMeter(Telegram *t,
|
||||||
mediaTypeJSON(t->a_field_device_type).c_str(),
|
mediaTypeJSON(t->a_field_device_type).c_str(),
|
||||||
name().c_str(),
|
name().c_str(),
|
||||||
t->id.c_str(),
|
t->id.c_str(),
|
||||||
totalWaterConsumption(),
|
totalWaterConsumption(Unit::M3),
|
||||||
datetimeOfUpdateRobot().c_str());
|
datetimeOfUpdateRobot().c_str());
|
||||||
|
|
||||||
*json = buf;
|
*json = buf;
|
||||||
|
@ -206,7 +206,7 @@ void MeterApator162::printMeter(Telegram *t,
|
||||||
envs->push_back(string("METER_JSON=")+*json);
|
envs->push_back(string("METER_JSON=")+*json);
|
||||||
envs->push_back(string("METER_TYPE=apator162"));
|
envs->push_back(string("METER_TYPE=apator162"));
|
||||||
envs->push_back(string("METER_ID=")+t->id);
|
envs->push_back(string("METER_ID=")+t->id);
|
||||||
envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption()));
|
envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption(Unit::M3)));
|
||||||
envs->push_back(string("METER_TIMESTAMP=")+datetimeOfUpdateRobot());
|
envs->push_back(string("METER_TIMESTAMP=")+datetimeOfUpdateRobot());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ bool MeterApator162::hasTotalWaterConsumption()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterApator162::targetWaterConsumption()
|
double MeterApator162::targetWaterConsumption(Unit u)
|
||||||
{
|
{
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
@ -225,7 +225,7 @@ bool MeterApator162::hasTargetWaterConsumption()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterApator162::maxFlow()
|
double MeterApator162::maxFlow(Unit u)
|
||||||
{
|
{
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,7 @@ bool MeterApator162::hasMaxFlow()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterApator162::flowTemperature()
|
double MeterApator162::flowTemperature(Unit u)
|
||||||
{
|
{
|
||||||
return 127;
|
return 127;
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,7 @@ bool MeterApator162::hasFlowTemperature()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterApator162::externalTemperature()
|
double MeterApator162::externalTemperature(Unit u)
|
||||||
{
|
{
|
||||||
return 127;
|
return 127;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,15 +37,15 @@ struct MeterIperl : public virtual WaterMeter, public virtual MeterCommonImpleme
|
||||||
MeterIperl(WMBus *bus, string& name, string& id, string& key);
|
MeterIperl(WMBus *bus, string& name, string& id, string& key);
|
||||||
|
|
||||||
// Total water counted through the meter
|
// Total water counted through the meter
|
||||||
double totalWaterConsumption();
|
double totalWaterConsumption(Unit u);
|
||||||
bool hasTotalWaterConsumption();
|
bool hasTotalWaterConsumption();
|
||||||
double targetWaterConsumption();
|
double targetWaterConsumption(Unit u);
|
||||||
bool hasTargetWaterConsumption();
|
bool hasTargetWaterConsumption();
|
||||||
double maxFlow();
|
double maxFlow(Unit u);
|
||||||
bool hasMaxFlow();
|
bool hasMaxFlow();
|
||||||
double flowTemperature();
|
double flowTemperature(Unit u);
|
||||||
bool hasFlowTemperature();
|
bool hasFlowTemperature();
|
||||||
double externalTemperature();
|
double externalTemperature(Unit u);
|
||||||
bool hasExternalTemperature();
|
bool hasExternalTemperature();
|
||||||
|
|
||||||
string statusHumanReadable();
|
string statusHumanReadable();
|
||||||
|
@ -79,7 +79,7 @@ MeterIperl::MeterIperl(WMBus *bus, string& name, string& id, string& key) :
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double MeterIperl::totalWaterConsumption()
|
double MeterIperl::totalWaterConsumption(Unit u)
|
||||||
{
|
{
|
||||||
return total_water_consumption_;
|
return total_water_consumption_;
|
||||||
}
|
}
|
||||||
|
@ -160,8 +160,8 @@ void MeterIperl::printMeter(Telegram *t,
|
||||||
"%s",
|
"%s",
|
||||||
name().c_str(),
|
name().c_str(),
|
||||||
t->id.c_str(),
|
t->id.c_str(),
|
||||||
totalWaterConsumption(),
|
totalWaterConsumption(Unit::M3),
|
||||||
maxFlow(),
|
maxFlow(Unit::M3H),
|
||||||
datetimeOfUpdateHumanReadable().c_str());
|
datetimeOfUpdateHumanReadable().c_str());
|
||||||
|
|
||||||
*human_readable = buf;
|
*human_readable = buf;
|
||||||
|
@ -174,8 +174,8 @@ void MeterIperl::printMeter(Telegram *t,
|
||||||
"%s",
|
"%s",
|
||||||
name().c_str(), separator,
|
name().c_str(), separator,
|
||||||
t->id.c_str(), separator,
|
t->id.c_str(), separator,
|
||||||
totalWaterConsumption(), separator,
|
totalWaterConsumption(Unit::M3), separator,
|
||||||
maxFlow(), separator,
|
maxFlow(Unit::M3H), separator,
|
||||||
datetimeOfUpdateRobot().c_str());
|
datetimeOfUpdateRobot().c_str());
|
||||||
|
|
||||||
*fields = buf;
|
*fields = buf;
|
||||||
|
@ -196,8 +196,8 @@ void MeterIperl::printMeter(Telegram *t,
|
||||||
mediaTypeJSON(t->a_field_device_type).c_str(),
|
mediaTypeJSON(t->a_field_device_type).c_str(),
|
||||||
name().c_str(),
|
name().c_str(),
|
||||||
t->id.c_str(),
|
t->id.c_str(),
|
||||||
totalWaterConsumption(),
|
totalWaterConsumption(Unit::M3),
|
||||||
maxFlow(),
|
maxFlow(Unit::M3H),
|
||||||
datetimeOfUpdateRobot().c_str());
|
datetimeOfUpdateRobot().c_str());
|
||||||
|
|
||||||
*json = buf;
|
*json = buf;
|
||||||
|
@ -205,8 +205,8 @@ void MeterIperl::printMeter(Telegram *t,
|
||||||
envs->push_back(string("METER_JSON=")+*json);
|
envs->push_back(string("METER_JSON=")+*json);
|
||||||
envs->push_back(string("METER_TYPE=iperl"));
|
envs->push_back(string("METER_TYPE=iperl"));
|
||||||
envs->push_back(string("METER_ID=")+t->id);
|
envs->push_back(string("METER_ID=")+t->id);
|
||||||
envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption()));
|
envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption(Unit::M3)));
|
||||||
envs->push_back(string("METER_MAX_FLOW_M3H=")+to_string(maxFlow()));
|
envs->push_back(string("METER_MAX_FLOW_M3H=")+to_string(maxFlow(Unit::M3H)));
|
||||||
envs->push_back(string("METER_TIMESTAMP=")+datetimeOfUpdateRobot());
|
envs->push_back(string("METER_TIMESTAMP=")+datetimeOfUpdateRobot());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ bool MeterIperl::hasTotalWaterConsumption()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterIperl::targetWaterConsumption()
|
double MeterIperl::targetWaterConsumption(Unit u)
|
||||||
{
|
{
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
@ -225,7 +225,7 @@ bool MeterIperl::hasTargetWaterConsumption()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterIperl::maxFlow()
|
double MeterIperl::maxFlow(Unit u)
|
||||||
{
|
{
|
||||||
return max_flow_;
|
return max_flow_;
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,7 @@ bool MeterIperl::hasMaxFlow()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterIperl::flowTemperature()
|
double MeterIperl::flowTemperature(Unit u)
|
||||||
{
|
{
|
||||||
return 127;
|
return 127;
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,7 @@ bool MeterIperl::hasFlowTemperature()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterIperl::externalTemperature()
|
double MeterIperl::externalTemperature(Unit u)
|
||||||
{
|
{
|
||||||
return 127;
|
return 127;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,41 +32,20 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
struct MKRadio3 : public virtual WaterMeter, public virtual MeterCommonImplementation {
|
struct MKRadio3 : public virtual WaterMeter, public virtual MeterCommonImplementation
|
||||||
|
{
|
||||||
MKRadio3(WMBus *bus, string& name, string& id, string& key);
|
MKRadio3(WMBus *bus, string& name, string& id, string& key);
|
||||||
|
|
||||||
// Total water counted through the meter
|
double totalWaterConsumption(Unit u);
|
||||||
double totalWaterConsumption();
|
|
||||||
bool hasTotalWaterConsumption();
|
bool hasTotalWaterConsumption();
|
||||||
double targetWaterConsumption();
|
double targetWaterConsumption(Unit u);
|
||||||
bool hasTargetWaterConsumption();
|
bool hasTargetWaterConsumption();
|
||||||
double maxFlow();
|
|
||||||
bool hasMaxFlow();
|
|
||||||
double flowTemperature();
|
|
||||||
bool hasFlowTemperature();
|
|
||||||
double externalTemperature();
|
|
||||||
bool hasExternalTemperature();
|
|
||||||
|
|
||||||
string statusHumanReadable();
|
|
||||||
string status();
|
|
||||||
string timeDry();
|
|
||||||
string timeReversed();
|
|
||||||
string timeLeaking();
|
|
||||||
string timeBursting();
|
|
||||||
|
|
||||||
void printMeter(Telegram *t,
|
|
||||||
string *human_readable,
|
|
||||||
string *fields, char separator,
|
|
||||||
string *json,
|
|
||||||
vector<string> *envs);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleTelegram(Telegram *t);
|
|
||||||
void processContent(Telegram *t);
|
void processContent(Telegram *t);
|
||||||
string decodeTime(int time);
|
|
||||||
|
|
||||||
double total_water_consumption_ {};
|
double total_water_consumption_m3_ {};
|
||||||
double target_water_consumption_ {};
|
double target_water_consumption_m3_ {};
|
||||||
};
|
};
|
||||||
|
|
||||||
MKRadio3::MKRadio3(WMBus *bus, string& name, string& id, string& key) :
|
MKRadio3::MKRadio3(WMBus *bus, string& name, string& id, string& key) :
|
||||||
|
@ -74,55 +53,25 @@ MKRadio3::MKRadio3(WMBus *bus, string& name, string& id, string& key) :
|
||||||
{
|
{
|
||||||
addMedia(0x62);
|
addMedia(0x62);
|
||||||
addMedia(0x72);
|
addMedia(0x72);
|
||||||
|
|
||||||
|
addPrint("total", Quantity::Volume,
|
||||||
|
[&](Unit u){ return totalWaterConsumption(u); },
|
||||||
|
"The total water consumption recorded by this meter.",
|
||||||
|
true);
|
||||||
|
|
||||||
|
addPrint("target", Quantity::Volume,
|
||||||
|
[&](Unit u){ return targetWaterConsumption(u); },
|
||||||
|
"The total water consumption recorded at the beginning of this month.",
|
||||||
|
true);
|
||||||
|
|
||||||
MeterCommonImplementation::bus()->onTelegram(calll(this,handleTelegram,Telegram*));
|
MeterCommonImplementation::bus()->onTelegram(calll(this,handleTelegram,Telegram*));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double MKRadio3::totalWaterConsumption()
|
|
||||||
{
|
|
||||||
return total_water_consumption_;
|
|
||||||
}
|
|
||||||
|
|
||||||
unique_ptr<WaterMeter> createMKRadio3(WMBus *bus, string& name, string& id, string& key)
|
unique_ptr<WaterMeter> createMKRadio3(WMBus *bus, string& name, string& id, string& key)
|
||||||
{
|
{
|
||||||
return unique_ptr<WaterMeter>(new MKRadio3(bus,name,id,key));
|
return unique_ptr<WaterMeter>(new MKRadio3(bus,name,id,key));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MKRadio3::handleTelegram(Telegram *t)
|
|
||||||
{
|
|
||||||
if (!isTelegramForMe(t)) {
|
|
||||||
// This telegram is not intended for this meter.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
verbose("(%s) telegram for %s %02x%02x%02x%02x\n", "mkradio3",
|
|
||||||
name().c_str(),
|
|
||||||
t->a_field_address[0], t->a_field_address[1], t->a_field_address[2],
|
|
||||||
t->a_field_address[3]);
|
|
||||||
|
|
||||||
t->expectVersion("mkradio3", 0x74);
|
|
||||||
|
|
||||||
if (t->isEncrypted() && !useAes() && !t->isSimulated()) {
|
|
||||||
warning("(mkradio3) warning: telegram is encrypted but no key supplied!\n");
|
|
||||||
}
|
|
||||||
if (useAes()) {
|
|
||||||
vector<uchar> aeskey = key();
|
|
||||||
decryptMode5_AES_CBC(t, aeskey);
|
|
||||||
} else {
|
|
||||||
t->content = t->payload;
|
|
||||||
}
|
|
||||||
char log_prefix[256];
|
|
||||||
snprintf(log_prefix, 255, "(%s) log", "mkradio3");
|
|
||||||
logTelegram(log_prefix, t->parsed, t->content);
|
|
||||||
int content_start = t->parsed.size();
|
|
||||||
processContent(t);
|
|
||||||
if (isDebugEnabled()) {
|
|
||||||
snprintf(log_prefix, 255, "(%s)", "mkradio3");
|
|
||||||
t->explainParse(log_prefix, content_start);
|
|
||||||
}
|
|
||||||
triggerUpdate(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MKRadio3::processContent(Telegram *t)
|
void MKRadio3::processContent(Telegram *t)
|
||||||
{
|
{
|
||||||
// Meter record:
|
// Meter record:
|
||||||
|
@ -154,75 +103,14 @@ void MKRadio3::processContent(Telegram *t)
|
||||||
t->explanations.push_back({ offset, currs });
|
t->explanations.push_back({ offset, currs });
|
||||||
t->addMoreExplanation(offset, " curr consumption (%f m3)", curr);
|
t->addMoreExplanation(offset, " curr consumption (%f m3)", curr);
|
||||||
|
|
||||||
total_water_consumption_ = prev+curr;
|
total_water_consumption_m3_ = prev+curr;
|
||||||
target_water_consumption_ = prev;
|
target_water_consumption_m3_ = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MKRadio3::printMeter(Telegram *t,
|
double MKRadio3::totalWaterConsumption(Unit u)
|
||||||
string *human_readable,
|
|
||||||
string *fields, char separator,
|
|
||||||
string *json,
|
|
||||||
vector<string> *envs)
|
|
||||||
{
|
{
|
||||||
char buf[65536];
|
assertQuantity(u, Quantity::Volume);
|
||||||
buf[65535] = 0;
|
return convert(total_water_consumption_m3_, Unit::M3, u);
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf)-1,
|
|
||||||
"%s\t"
|
|
||||||
"%s\t"
|
|
||||||
"% 3.3f m3\t"
|
|
||||||
"% 3.3f m3\t"
|
|
||||||
"%s",
|
|
||||||
name().c_str(),
|
|
||||||
t->id.c_str(),
|
|
||||||
totalWaterConsumption(),
|
|
||||||
targetWaterConsumption(),
|
|
||||||
datetimeOfUpdateHumanReadable().c_str());
|
|
||||||
|
|
||||||
*human_readable = buf;
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf)-1,
|
|
||||||
"%s%c"
|
|
||||||
"%s%c"
|
|
||||||
"%f%c"
|
|
||||||
"%f%c"
|
|
||||||
"%s",
|
|
||||||
name().c_str(), separator,
|
|
||||||
t->id.c_str(), separator,
|
|
||||||
totalWaterConsumption(), separator,
|
|
||||||
targetWaterConsumption(), separator,
|
|
||||||
datetimeOfUpdateRobot().c_str());
|
|
||||||
|
|
||||||
*fields = buf;
|
|
||||||
|
|
||||||
#define Q(x,y) "\""#x"\":"#y","
|
|
||||||
#define QS(x,y) "\""#x"\":\""#y"\","
|
|
||||||
#define QSE(x,y) "\""#x"\":\""#y"\""
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf)-1, "{"
|
|
||||||
QS(media,%s)
|
|
||||||
QS(meter,mkradio3)
|
|
||||||
QS(name,%s)
|
|
||||||
QS(id,%s)
|
|
||||||
Q(total_m3,%f)
|
|
||||||
Q(target_m3,%f)
|
|
||||||
QSE(timestamp,%s)
|
|
||||||
"}",
|
|
||||||
mediaTypeJSON(t->a_field_device_type).c_str(),
|
|
||||||
name().c_str(),
|
|
||||||
t->id.c_str(),
|
|
||||||
totalWaterConsumption(),
|
|
||||||
targetWaterConsumption(),
|
|
||||||
datetimeOfUpdateRobot().c_str());
|
|
||||||
|
|
||||||
*json = buf;
|
|
||||||
|
|
||||||
envs->push_back(string("METER_JSON=")+*json);
|
|
||||||
envs->push_back(string("METER_TYPE=mkradio3"));
|
|
||||||
envs->push_back(string("METER_ID=")+t->id);
|
|
||||||
envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption()));
|
|
||||||
envs->push_back(string("METER_TARGET_M3=")+to_string(targetWaterConsumption()));
|
|
||||||
envs->push_back(string("METER_TIMESTAMP=")+datetimeOfUpdateRobot());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MKRadio3::hasTotalWaterConsumption()
|
bool MKRadio3::hasTotalWaterConsumption()
|
||||||
|
@ -230,72 +118,12 @@ bool MKRadio3::hasTotalWaterConsumption()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MKRadio3::targetWaterConsumption()
|
double MKRadio3::targetWaterConsumption(Unit u)
|
||||||
{
|
{
|
||||||
return target_water_consumption_;
|
return target_water_consumption_m3_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MKRadio3::hasTargetWaterConsumption()
|
bool MKRadio3::hasTargetWaterConsumption()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MKRadio3::maxFlow()
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MKRadio3::hasMaxFlow()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
double MKRadio3::flowTemperature()
|
|
||||||
{
|
|
||||||
return 127;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MKRadio3::hasFlowTemperature()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
double MKRadio3::externalTemperature()
|
|
||||||
{
|
|
||||||
return 127;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MKRadio3::hasExternalTemperature()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
string MKRadio3::statusHumanReadable()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
string MKRadio3::status()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
string MKRadio3::timeDry()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
string MKRadio3::timeReversed()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
string MKRadio3::timeLeaking()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
string MKRadio3::timeBursting()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
|
@ -48,23 +48,23 @@ struct MeterMultical21 : public virtual WaterMeter, public virtual MeterCommonIm
|
||||||
MeterMultical21(WMBus *bus, string& name, string& id, string& key, MeterType mt);
|
MeterMultical21(WMBus *bus, string& name, string& id, string& key, MeterType mt);
|
||||||
|
|
||||||
// Total water counted through the meter
|
// Total water counted through the meter
|
||||||
double totalWaterConsumption();
|
double totalWaterConsumption(Unit u);
|
||||||
bool hasTotalWaterConsumption();
|
bool hasTotalWaterConsumption();
|
||||||
|
|
||||||
// Meter sends target water consumption or max flow, depending on meter configuration
|
// Meter sends target water consumption or max flow, depending on meter configuration
|
||||||
// We can see which was sent inside the wmbus message!
|
// We can see which was sent inside the wmbus message!
|
||||||
|
|
||||||
// Target water consumption: The total consumption at the start of the previous 30 day period.
|
// Target water consumption: The total consumption at the start of the previous 30 day period.
|
||||||
double targetWaterConsumption();
|
double targetWaterConsumption(Unit u);
|
||||||
bool hasTargetWaterConsumption();
|
bool hasTargetWaterConsumption();
|
||||||
// Max flow during last month or last 24 hours depending on meter configuration.
|
// Max flow during last month or last 24 hours depending on meter configuration.
|
||||||
double maxFlow();
|
double maxFlow(Unit u);
|
||||||
bool hasMaxFlow();
|
bool hasMaxFlow();
|
||||||
// Water temperature
|
// Water temperature
|
||||||
double flowTemperature();
|
double flowTemperature(Unit u);
|
||||||
bool hasFlowTemperature();
|
bool hasFlowTemperature();
|
||||||
// Surrounding temperature
|
// Surrounding temperature
|
||||||
double externalTemperature();
|
double externalTemperature(Unit u);
|
||||||
bool hasExternalTemperature();
|
bool hasExternalTemperature();
|
||||||
|
|
||||||
// statusHumanReadable: DRY,REVERSED,LEAK,BURST if that status is detected right now, followed by
|
// statusHumanReadable: DRY,REVERSED,LEAK,BURST if that status is detected right now, followed by
|
||||||
|
@ -122,7 +122,7 @@ MeterMultical21::MeterMultical21(WMBus *bus, string& name, string& id, string& k
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double MeterMultical21::totalWaterConsumption()
|
double MeterMultical21::totalWaterConsumption(Unit u)
|
||||||
{
|
{
|
||||||
return total_water_consumption_;
|
return total_water_consumption_;
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ bool MeterMultical21::hasTotalWaterConsumption()
|
||||||
return has_total_water_consumption_;
|
return has_total_water_consumption_;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterMultical21::targetWaterConsumption()
|
double MeterMultical21::targetWaterConsumption(Unit u)
|
||||||
{
|
{
|
||||||
return target_volume_;
|
return target_volume_;
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ bool MeterMultical21::hasTargetWaterConsumption()
|
||||||
return has_target_volume_;
|
return has_target_volume_;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterMultical21::maxFlow()
|
double MeterMultical21::maxFlow(Unit u)
|
||||||
{
|
{
|
||||||
return max_flow_;
|
return max_flow_;
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ bool MeterMultical21::hasMaxFlow()
|
||||||
return has_max_flow_;
|
return has_max_flow_;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterMultical21::flowTemperature()
|
double MeterMultical21::flowTemperature(Unit u)
|
||||||
{
|
{
|
||||||
return flow_temperature_;
|
return flow_temperature_;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +162,7 @@ bool MeterMultical21::hasFlowTemperature()
|
||||||
return has_flow_temperature_;
|
return has_flow_temperature_;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterMultical21::externalTemperature()
|
double MeterMultical21::externalTemperature(Unit u)
|
||||||
{
|
{
|
||||||
return external_temperature_;
|
return external_temperature_;
|
||||||
}
|
}
|
||||||
|
@ -500,14 +500,14 @@ void MeterMultical21::printMeter(Telegram *t,
|
||||||
et[9] = 0;
|
et[9] = 0;
|
||||||
|
|
||||||
if (hasFlowTemperature()) {
|
if (hasFlowTemperature()) {
|
||||||
snprintf(ft, sizeof(ft)-1, "% 2.0f", flowTemperature());
|
snprintf(ft, sizeof(ft)-1, "% 2.0f", flowTemperature(Unit::C));
|
||||||
} else {
|
} else {
|
||||||
ft[0] = '-';
|
ft[0] = '-';
|
||||||
ft[1] = 0;
|
ft[1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasExternalTemperature()) {
|
if (hasExternalTemperature()) {
|
||||||
snprintf(et, sizeof(et)-1, "% 2.0f", externalTemperature());
|
snprintf(et, sizeof(et)-1, "% 2.0f", externalTemperature(Unit::C));
|
||||||
} else {
|
} else {
|
||||||
et[0] = '-';
|
et[0] = '-';
|
||||||
et[1] = 0;
|
et[1] = 0;
|
||||||
|
@ -525,9 +525,9 @@ void MeterMultical21::printMeter(Telegram *t,
|
||||||
"%s",
|
"%s",
|
||||||
name().c_str(),
|
name().c_str(),
|
||||||
t->id.c_str(),
|
t->id.c_str(),
|
||||||
totalWaterConsumption(),
|
totalWaterConsumption(Unit::M3),
|
||||||
targetWaterConsumption(),
|
targetWaterConsumption(Unit::M3),
|
||||||
maxFlow(),
|
maxFlow(Unit::M3H),
|
||||||
ft,
|
ft,
|
||||||
et,
|
et,
|
||||||
statusHumanReadable().c_str(),
|
statusHumanReadable().c_str(),
|
||||||
|
@ -547,11 +547,11 @@ void MeterMultical21::printMeter(Telegram *t,
|
||||||
"%s",
|
"%s",
|
||||||
name().c_str(), separator,
|
name().c_str(), separator,
|
||||||
t->id.c_str(), separator,
|
t->id.c_str(), separator,
|
||||||
totalWaterConsumption(), separator,
|
totalWaterConsumption(Unit::M3), separator,
|
||||||
targetWaterConsumption(), separator,
|
targetWaterConsumption(Unit::M3), separator,
|
||||||
maxFlow(), separator,
|
maxFlow(Unit::M3H), separator,
|
||||||
flowTemperature(), separator,
|
flowTemperature(Unit::C), separator,
|
||||||
externalTemperature(), separator,
|
externalTemperature(Unit::C), separator,
|
||||||
statusHumanReadable().c_str(), separator,
|
statusHumanReadable().c_str(), separator,
|
||||||
datetimeOfUpdateRobot().c_str());
|
datetimeOfUpdateRobot().c_str());
|
||||||
|
|
||||||
|
@ -582,11 +582,11 @@ void MeterMultical21::printMeter(Telegram *t,
|
||||||
meter_name_,
|
meter_name_,
|
||||||
name().c_str(),
|
name().c_str(),
|
||||||
t->id.c_str(),
|
t->id.c_str(),
|
||||||
totalWaterConsumption(),
|
totalWaterConsumption(Unit::M3),
|
||||||
targetWaterConsumption(),
|
targetWaterConsumption(Unit::M3),
|
||||||
maxFlow(),
|
maxFlow(Unit::M3H),
|
||||||
flowTemperature(),
|
flowTemperature(Unit::C),
|
||||||
externalTemperature(),
|
externalTemperature(Unit::C),
|
||||||
status().c_str(), // DRY REVERSED LEAK BURST
|
status().c_str(), // DRY REVERSED LEAK BURST
|
||||||
timeDry().c_str(),
|
timeDry().c_str(),
|
||||||
timeReversed().c_str(),
|
timeReversed().c_str(),
|
||||||
|
@ -599,11 +599,11 @@ void MeterMultical21::printMeter(Telegram *t,
|
||||||
envs->push_back(string("METER_JSON=")+*json);
|
envs->push_back(string("METER_JSON=")+*json);
|
||||||
envs->push_back(string("METER_TYPE=")+meter_name_);
|
envs->push_back(string("METER_TYPE=")+meter_name_);
|
||||||
envs->push_back(string("METER_ID=")+t->id);
|
envs->push_back(string("METER_ID=")+t->id);
|
||||||
envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption()));
|
envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption(Unit::M3)));
|
||||||
envs->push_back(string("METER_TARGET_M3=")+to_string(targetWaterConsumption()));
|
envs->push_back(string("METER_TARGET_M3=")+to_string(targetWaterConsumption(Unit::M3)));
|
||||||
envs->push_back(string("METER_MAX_FLOW_M3H=")+to_string(maxFlow()));
|
envs->push_back(string("METER_MAX_FLOW_M3H=")+to_string(maxFlow(Unit::M3H)));
|
||||||
envs->push_back(string("METER_FLOW_TEMPERATURE=")+to_string(flowTemperature()));
|
envs->push_back(string("METER_FLOW_TEMPERATURE=")+to_string(flowTemperature(Unit::C)));
|
||||||
envs->push_back(string("METER_EXTERNAL_TEMPERATURE=")+to_string(externalTemperature()));
|
envs->push_back(string("METER_EXTERNAL_TEMPERATURE=")+to_string(externalTemperature(Unit::C)));
|
||||||
envs->push_back(string("METER_STATUS=")+status());
|
envs->push_back(string("METER_STATUS=")+status());
|
||||||
envs->push_back(string("METER_TIME_DRY=")+timeDry());
|
envs->push_back(string("METER_TIME_DRY=")+timeDry());
|
||||||
envs->push_back(string("METER_TIME_REVERSED=")+timeReversed());
|
envs->push_back(string("METER_TIME_REVERSED=")+timeReversed());
|
||||||
|
|
|
@ -36,56 +36,42 @@ struct MeterSupercom587 : public virtual WaterMeter, public virtual MeterCommonI
|
||||||
MeterSupercom587(WMBus *bus, string& name, string& id, string& key);
|
MeterSupercom587(WMBus *bus, string& name, string& id, string& key);
|
||||||
|
|
||||||
// Total water counted through the meter
|
// Total water counted through the meter
|
||||||
double totalWaterConsumption();
|
double totalWaterConsumption(Unit u);
|
||||||
bool hasTotalWaterConsumption();
|
bool hasTotalWaterConsumption();
|
||||||
double targetWaterConsumption();
|
|
||||||
bool hasTargetWaterConsumption();
|
|
||||||
double maxFlow();
|
|
||||||
bool hasMaxFlow();
|
|
||||||
double flowTemperature();
|
|
||||||
bool hasFlowTemperature();
|
|
||||||
double externalTemperature();
|
|
||||||
bool hasExternalTemperature();
|
|
||||||
|
|
||||||
string statusHumanReadable();
|
|
||||||
string status();
|
|
||||||
string timeDry();
|
|
||||||
string timeReversed();
|
|
||||||
string timeLeaking();
|
|
||||||
string timeBursting();
|
|
||||||
|
|
||||||
void printMeter(Telegram *t,
|
|
||||||
string *human_readable,
|
|
||||||
string *fields, char separator,
|
|
||||||
string *json,
|
|
||||||
vector<string> *envs);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleTelegram(Telegram *t);
|
void handleTelegram(Telegram *t);
|
||||||
void processContent(Telegram *t);
|
void processContent(Telegram *t);
|
||||||
string decodeTime(int time);
|
string decodeTime(int time);
|
||||||
|
|
||||||
double total_water_consumption_ {};
|
double total_water_consumption_m3_ {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
unique_ptr<WaterMeter> createSupercom587(WMBus *bus, string& name, string& id, string& key)
|
||||||
|
{
|
||||||
|
return unique_ptr<WaterMeter>(new MeterSupercom587(bus,name,id,key));
|
||||||
|
}
|
||||||
|
|
||||||
MeterSupercom587::MeterSupercom587(WMBus *bus, string& name, string& id, string& key) :
|
MeterSupercom587::MeterSupercom587(WMBus *bus, string& name, string& id, string& key) :
|
||||||
MeterCommonImplementation(bus, name, id, key, MeterType::SUPERCOM587, MANUFACTURER_SON, LinkMode::T1)
|
MeterCommonImplementation(bus, name, id, key, MeterType::SUPERCOM587, MANUFACTURER_SON, LinkMode::T1)
|
||||||
{
|
{
|
||||||
addMedia(0x06);
|
addMedia(0x06);
|
||||||
addMedia(0x07);
|
addMedia(0x07);
|
||||||
|
|
||||||
|
addPrint("total", Quantity::Volume,
|
||||||
|
[&](Unit u){ return totalWaterConsumption(u); },
|
||||||
|
"The total water consumption recorded by this meter.",
|
||||||
|
true);
|
||||||
|
|
||||||
MeterCommonImplementation::bus()->onTelegram(calll(this,handleTelegram,Telegram*));
|
MeterCommonImplementation::bus()->onTelegram(calll(this,handleTelegram,Telegram*));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double MeterSupercom587::totalWaterConsumption(Unit u)
|
||||||
double MeterSupercom587::totalWaterConsumption()
|
|
||||||
{
|
{
|
||||||
return total_water_consumption_;
|
assertQuantity(u, Quantity::Volume);
|
||||||
|
return convert(total_water_consumption_m3_, Unit::M3, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr<WaterMeter> createSupercom587(WMBus *bus, string& name, string& id, string& key)
|
|
||||||
{
|
|
||||||
return unique_ptr<WaterMeter>(new MeterSupercom587(bus,name,id,key));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeterSupercom587::handleTelegram(Telegram *t)
|
void MeterSupercom587::handleTelegram(Telegram *t)
|
||||||
{
|
{
|
||||||
|
@ -131,141 +117,11 @@ void MeterSupercom587::processContent(Telegram *t)
|
||||||
|
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
extractDVdouble(&values, "0C13", &offset, &total_water_consumption_);
|
extractDVdouble(&values, "0C13", &offset, &total_water_consumption_m3_);
|
||||||
t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_);
|
t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_m3_);
|
||||||
}
|
|
||||||
|
|
||||||
void MeterSupercom587::printMeter(Telegram *t,
|
|
||||||
string *human_readable,
|
|
||||||
string *fields, char separator,
|
|
||||||
string *json,
|
|
||||||
vector<string> *envs)
|
|
||||||
{
|
|
||||||
char buf[65536];
|
|
||||||
buf[65535] = 0;
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf)-1,
|
|
||||||
"%s\t"
|
|
||||||
"%s\t"
|
|
||||||
"% 3.3f m3\t"
|
|
||||||
"%s",
|
|
||||||
name().c_str(),
|
|
||||||
t->id.c_str(),
|
|
||||||
totalWaterConsumption(),
|
|
||||||
datetimeOfUpdateHumanReadable().c_str());
|
|
||||||
|
|
||||||
*human_readable = buf;
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf)-1,
|
|
||||||
"%s%c"
|
|
||||||
"%s%c"
|
|
||||||
"%f%c"
|
|
||||||
"%s",
|
|
||||||
name().c_str(), separator,
|
|
||||||
t->id.c_str(), separator,
|
|
||||||
totalWaterConsumption(), separator,
|
|
||||||
datetimeOfUpdateRobot().c_str());
|
|
||||||
|
|
||||||
*fields = buf;
|
|
||||||
|
|
||||||
#define Q(x,y) "\""#x"\":"#y","
|
|
||||||
#define QS(x,y) "\""#x"\":\""#y"\","
|
|
||||||
#define QSE(x,y) "\""#x"\":\""#y"\""
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf)-1, "{"
|
|
||||||
QS(media,%s)
|
|
||||||
QS(meter,supercom587)
|
|
||||||
QS(name,%s)
|
|
||||||
QS(id,%s)
|
|
||||||
Q(total_m3,%f)
|
|
||||||
QSE(timestamp,%s)
|
|
||||||
"}",
|
|
||||||
mediaTypeJSON(t->a_field_device_type).c_str(),
|
|
||||||
name().c_str(),
|
|
||||||
t->id.c_str(),
|
|
||||||
totalWaterConsumption(),
|
|
||||||
datetimeOfUpdateRobot().c_str());
|
|
||||||
|
|
||||||
*json = buf;
|
|
||||||
|
|
||||||
envs->push_back(string("METER_JSON=")+*json);
|
|
||||||
envs->push_back(string("METER_TYPE=supercom587"));
|
|
||||||
envs->push_back(string("METER_ID=")+t->id);
|
|
||||||
envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption()));
|
|
||||||
envs->push_back(string("METER_TIMESTAMP=")+datetimeOfUpdateRobot());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MeterSupercom587::hasTotalWaterConsumption()
|
bool MeterSupercom587::hasTotalWaterConsumption()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterSupercom587::targetWaterConsumption()
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MeterSupercom587::hasTargetWaterConsumption()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
double MeterSupercom587::maxFlow()
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MeterSupercom587::hasMaxFlow()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
double MeterSupercom587::flowTemperature()
|
|
||||||
{
|
|
||||||
return 127;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MeterSupercom587::hasFlowTemperature()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
double MeterSupercom587::externalTemperature()
|
|
||||||
{
|
|
||||||
return 127;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MeterSupercom587::hasExternalTemperature()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
string MeterSupercom587::statusHumanReadable()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
string MeterSupercom587::status()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
string MeterSupercom587::timeDry()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
string MeterSupercom587::timeReversed()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
string MeterSupercom587::timeLeaking()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
string MeterSupercom587::timeBursting()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,11 +23,7 @@
|
||||||
#include"units.h"
|
#include"units.h"
|
||||||
#include"util.h"
|
#include"util.h"
|
||||||
|
|
||||||
#include<algorithm>
|
|
||||||
#include<memory.h>
|
|
||||||
#include<stdio.h>
|
|
||||||
#include<string>
|
#include<string>
|
||||||
#include<time.h>
|
|
||||||
#include<vector>
|
#include<vector>
|
||||||
|
|
||||||
struct MeterVario451 : public virtual HeatMeter, public virtual MeterCommonImplementation
|
struct MeterVario451 : public virtual HeatMeter, public virtual MeterCommonImplementation
|
||||||
|
@ -36,13 +32,10 @@ struct MeterVario451 : public virtual HeatMeter, public virtual MeterCommonImple
|
||||||
|
|
||||||
double totalEnergyConsumption(Unit u);
|
double totalEnergyConsumption(Unit u);
|
||||||
double currentPeriodEnergyConsumption(Unit u);
|
double currentPeriodEnergyConsumption(Unit u);
|
||||||
double currentPowerConsumption(Unit u);
|
|
||||||
double previousPeriodEnergyConsumption(Unit u);
|
double previousPeriodEnergyConsumption(Unit u);
|
||||||
double totalVolume(Unit u);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void handleTelegram(Telegram *t);
|
|
||||||
void processContent(Telegram *t);
|
void processContent(Telegram *t);
|
||||||
|
|
||||||
double total_energy_gj_ {};
|
double total_energy_gj_ {};
|
||||||
|
@ -50,6 +43,11 @@ struct MeterVario451 : public virtual HeatMeter, public virtual MeterCommonImple
|
||||||
double prev_energy_gj_ {};
|
double prev_energy_gj_ {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
unique_ptr<HeatMeter> createVario451(WMBus *bus, string& name, string& id, string& key)
|
||||||
|
{
|
||||||
|
return unique_ptr<HeatMeter>(new MeterVario451(bus,name,id,key));
|
||||||
|
}
|
||||||
|
|
||||||
MeterVario451::MeterVario451(WMBus *bus, string& name, string& id, string& key) :
|
MeterVario451::MeterVario451(WMBus *bus, string& name, string& id, string& key) :
|
||||||
MeterCommonImplementation(bus, name, id, key, MeterType::VARIO451, MANUFACTURER_TCH, LinkMode::T1)
|
MeterCommonImplementation(bus, name, id, key, MeterType::VARIO451, MANUFACTURER_TCH, LinkMode::T1)
|
||||||
{
|
{
|
||||||
|
@ -86,58 +84,12 @@ double MeterVario451::currentPeriodEnergyConsumption(Unit u)
|
||||||
return convert(curr_energy_gj_, Unit::GJ, u);
|
return convert(curr_energy_gj_, Unit::GJ, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterVario451::currentPowerConsumption(Unit u)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double MeterVario451::previousPeriodEnergyConsumption(Unit u)
|
double MeterVario451::previousPeriodEnergyConsumption(Unit u)
|
||||||
{
|
{
|
||||||
assertQuantity(u, Quantity::Energy);
|
assertQuantity(u, Quantity::Energy);
|
||||||
return convert(prev_energy_gj_, Unit::GJ, u);
|
return convert(prev_energy_gj_, Unit::GJ, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
double MeterVario451::totalVolume(Unit u)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeterVario451::handleTelegram(Telegram *t) {
|
|
||||||
|
|
||||||
if (!isTelegramForMe(t)) {
|
|
||||||
// This telegram is not intended for this meter.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
verbose("(vario451) %s %02x%02x%02x%02x ",
|
|
||||||
name().c_str(),
|
|
||||||
t->a_field_address[0], t->a_field_address[1], t->a_field_address[2],
|
|
||||||
t->a_field_address[3]);
|
|
||||||
|
|
||||||
if (t->isEncrypted() && !useAes() && !t->isSimulated()) {
|
|
||||||
|
|
||||||
// This is ugly but I have no idea how to do this proper way :/
|
|
||||||
// Techem Vario 4 Typ 4.5.1 sends T and also encrypted C telegrams
|
|
||||||
// We are intrested in T only (for now)
|
|
||||||
|
|
||||||
//warning("(vario451) warning: telegram is encrypted but no key supplied!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (useAes()) {
|
|
||||||
vector<uchar> aeskey = key();
|
|
||||||
decryptMode1_AES_CTR(t, aeskey);
|
|
||||||
} else {
|
|
||||||
t->content = t->payload;
|
|
||||||
}
|
|
||||||
logTelegram("(vario451) log", t->parsed, t->content);
|
|
||||||
int content_start = t->parsed.size();
|
|
||||||
processContent(t);
|
|
||||||
if (isDebugEnabled()) {
|
|
||||||
t->explainParse("(vario451)", content_start);
|
|
||||||
}
|
|
||||||
triggerUpdate(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeterVario451::processContent(Telegram *t)
|
void MeterVario451::processContent(Telegram *t)
|
||||||
{
|
{
|
||||||
map<string,pair<int,DVEntry>> vendor_values;
|
map<string,pair<int,DVEntry>> vendor_values;
|
||||||
|
@ -172,8 +124,3 @@ void MeterVario451::processContent(Telegram *t)
|
||||||
curr_energy_gj_ = curr;
|
curr_energy_gj_ = curr;
|
||||||
prev_energy_gj_ = prev;
|
prev_energy_gj_ = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr<HeatMeter> createVario451(WMBus *bus, string& name, string& id, string& key)
|
|
||||||
{
|
|
||||||
return unique_ptr<HeatMeter>(new MeterVario451(bus,name,id,key));
|
|
||||||
}
|
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include"meters.h"
|
#include"meters.h"
|
||||||
#include"meters_common_implementation.h"
|
#include"meters_common_implementation.h"
|
||||||
#include"units.h"
|
#include"units.h"
|
||||||
|
#include"wmbus.h"
|
||||||
|
#include"wmbus_utils.h"
|
||||||
|
|
||||||
#include<algorithm>
|
#include<algorithm>
|
||||||
#include<memory.h>
|
#include<memory.h>
|
||||||
|
@ -253,6 +255,51 @@ string concatFields(Meter *m, Telegram *t, char c, vector<Print> &prints, vector
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MeterCommonImplementation::handleTelegram(Telegram *t)
|
||||||
|
{
|
||||||
|
if (!isTelegramForMe(t)) {
|
||||||
|
// This telegram is not intended for this meter.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
verbose("(%s) %s %02x%02x%02x%02x ",
|
||||||
|
meterName().c_str(),
|
||||||
|
name().c_str(),
|
||||||
|
t->a_field_address[0], t->a_field_address[1], t->a_field_address[2],
|
||||||
|
t->a_field_address[3]);
|
||||||
|
|
||||||
|
//t->expectVersion("mkradio3", 0x74);
|
||||||
|
|
||||||
|
if (t->isEncrypted() && !useAes() && !t->isSimulated())
|
||||||
|
{
|
||||||
|
warning("(%s) warning: telegram is encrypted but no key supplied!\n",
|
||||||
|
meterName().c_str());
|
||||||
|
}
|
||||||
|
if (useAes()) {
|
||||||
|
vector<uchar> aeskey = key();
|
||||||
|
decryptMode1_AES_CTR(t, aeskey);
|
||||||
|
} else {
|
||||||
|
t->content = t->payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
char log_prefix[256];
|
||||||
|
snprintf(log_prefix, 255, "(%s) log", meterName().c_str());
|
||||||
|
logTelegram(log_prefix, t->parsed, t->content);
|
||||||
|
int content_start = t->parsed.size();
|
||||||
|
|
||||||
|
// Invoke meter specific parsing!
|
||||||
|
processContent(t);
|
||||||
|
// All done....
|
||||||
|
|
||||||
|
if (isDebugEnabled())
|
||||||
|
{
|
||||||
|
char log_prefix[256];
|
||||||
|
snprintf(log_prefix, 255, "(%s)", meterName().c_str());
|
||||||
|
t->explainParse("(vario451)", content_start);
|
||||||
|
}
|
||||||
|
triggerUpdate(t);
|
||||||
|
}
|
||||||
|
|
||||||
void MeterCommonImplementation::printMeter(Telegram *t,
|
void MeterCommonImplementation::printMeter(Telegram *t,
|
||||||
string *human_readable,
|
string *human_readable,
|
||||||
string *fields, char separator,
|
string *fields, char separator,
|
||||||
|
@ -313,3 +360,36 @@ void MeterCommonImplementation::printMeter(Telegram *t,
|
||||||
}
|
}
|
||||||
envs->push_back(string("METER_TIMESTAMP=")+datetimeOfUpdateRobot());
|
envs->push_back(string("METER_TIMESTAMP=")+datetimeOfUpdateRobot());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double WaterMeter::totalWaterConsumption(Unit u) { return -47.11; }
|
||||||
|
bool WaterMeter::hasTotalWaterConsumption() { return false; }
|
||||||
|
double WaterMeter::targetWaterConsumption(Unit u) { return -47.11; }
|
||||||
|
bool WaterMeter::hasTargetWaterConsumption() { return false; }
|
||||||
|
double WaterMeter::maxFlow(Unit u) { return -47.11; }
|
||||||
|
bool WaterMeter::hasMaxFlow() { return false; }
|
||||||
|
double WaterMeter::flowTemperature(Unit u) { return -47.11; }
|
||||||
|
bool WaterMeter::hasFlowTemperature() { return false; }
|
||||||
|
double WaterMeter::externalTemperature(Unit u) { return -47.11; }
|
||||||
|
bool WaterMeter::hasExternalTemperature() { return false; }
|
||||||
|
|
||||||
|
string WaterMeter::statusHumanReadable() { return "-47.11"; }
|
||||||
|
string WaterMeter::status() { return "-47.11"; }
|
||||||
|
string WaterMeter::timeDry() { return "-47.11"; }
|
||||||
|
string WaterMeter::timeReversed() { return "-47.11"; }
|
||||||
|
string WaterMeter::timeLeaking() { return "-47.11"; }
|
||||||
|
string WaterMeter::timeBursting() { return "-47.11"; }
|
||||||
|
|
||||||
|
double HeatMeter::totalEnergyConsumption(Unit u) { return -47.11; }
|
||||||
|
double HeatMeter::currentPeriodEnergyConsumption(Unit u) { return -47.11; }
|
||||||
|
double HeatMeter::previousPeriodEnergyConsumption(Unit u) { return -47.11; }
|
||||||
|
double HeatMeter::currentPowerConsumption(Unit u) { return -47.11; }
|
||||||
|
double HeatMeter::totalVolume(Unit u) { return -47.11; }
|
||||||
|
|
||||||
|
double ElectricityMeter::totalEnergyConsumption() { return -47.11; }
|
||||||
|
double ElectricityMeter::currentPowerConsumption() { return -47.11; }
|
||||||
|
double ElectricityMeter::totalEnergyProduction() { return -47.11; }
|
||||||
|
double ElectricityMeter::currentPowerProduction() { return -47.11; }
|
||||||
|
|
||||||
|
double HeatCostMeter::currentConsumption() { return -47.11; }
|
||||||
|
string HeatCostMeter::setDate() { return "47.11"; }
|
||||||
|
double HeatCostMeter::consumptionAtSetDate() { return -47.11; }
|
||||||
|
|
57
src/meters.h
57
src/meters.h
|
@ -71,6 +71,7 @@ struct Meter {
|
||||||
string *json,
|
string *json,
|
||||||
vector<string> *envs) = 0;
|
vector<string> *envs) = 0;
|
||||||
|
|
||||||
|
void handleTelegram(Telegram *t);
|
||||||
virtual bool isTelegramForMe(Telegram *t) = 0;
|
virtual bool isTelegramForMe(Telegram *t) = 0;
|
||||||
virtual bool useAes() = 0;
|
virtual bool useAes() = 0;
|
||||||
virtual vector<uchar> key() = 0;
|
virtual vector<uchar> key() = 0;
|
||||||
|
@ -86,44 +87,44 @@ struct Meter {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WaterMeter : public virtual Meter {
|
struct WaterMeter : public virtual Meter {
|
||||||
virtual double totalWaterConsumption() = 0; // m3
|
virtual double totalWaterConsumption(Unit u); // m3
|
||||||
virtual bool hasTotalWaterConsumption() = 0;
|
virtual bool hasTotalWaterConsumption();
|
||||||
virtual double targetWaterConsumption() = 0; // m3
|
virtual double targetWaterConsumption(Unit u); // m3
|
||||||
virtual bool hasTargetWaterConsumption() = 0;
|
virtual bool hasTargetWaterConsumption();
|
||||||
virtual double maxFlow() = 0;
|
virtual double maxFlow(Unit u); // m3/s
|
||||||
virtual bool hasMaxFlow() = 0;
|
virtual bool hasMaxFlow();
|
||||||
virtual double flowTemperature() = 0; // °C
|
virtual double flowTemperature(Unit u); // °C
|
||||||
virtual bool hasFlowTemperature() = 0;
|
virtual bool hasFlowTemperature();
|
||||||
virtual double externalTemperature() = 0; // °C
|
virtual double externalTemperature(Unit u); // °C
|
||||||
virtual bool hasExternalTemperature() = 0;
|
virtual bool hasExternalTemperature();
|
||||||
|
|
||||||
virtual string statusHumanReadable() = 0;
|
virtual string statusHumanReadable();
|
||||||
virtual string status() = 0;
|
virtual string status();
|
||||||
virtual string timeDry() = 0;
|
virtual string timeDry();
|
||||||
virtual string timeReversed() = 0;
|
virtual string timeReversed();
|
||||||
virtual string timeLeaking() = 0;
|
virtual string timeLeaking();
|
||||||
virtual string timeBursting() = 0;
|
virtual string timeBursting();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HeatMeter : public virtual Meter {
|
struct HeatMeter : public virtual Meter {
|
||||||
virtual double totalEnergyConsumption(Unit u) = 0; // kwh
|
virtual double totalEnergyConsumption(Unit u); // kwh
|
||||||
virtual double currentPeriodEnergyConsumption(Unit u) = 0; // kwh
|
virtual double currentPeriodEnergyConsumption(Unit u); // kwh
|
||||||
virtual double previousPeriodEnergyConsumption(Unit u) = 0; // kwh
|
virtual double previousPeriodEnergyConsumption(Unit u); // kwh
|
||||||
virtual double currentPowerConsumption(Unit u) = 0; // kw
|
virtual double currentPowerConsumption(Unit u); // kw
|
||||||
virtual double totalVolume(Unit u) = 0; // m3
|
virtual double totalVolume(Unit u); // m3
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ElectricityMeter : public virtual Meter {
|
struct ElectricityMeter : public virtual Meter {
|
||||||
virtual double totalEnergyConsumption() = 0; // kwh
|
virtual double totalEnergyConsumption(); // kwh
|
||||||
virtual double currentPowerConsumption() = 0; // kw
|
virtual double currentPowerConsumption(); // kw
|
||||||
virtual double totalEnergyProduction() = 0; // kwh
|
virtual double totalEnergyProduction(); // kwh
|
||||||
virtual double currentPowerProduction() = 0; // kw
|
virtual double currentPowerProduction(); // kw
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HeatCostMeter : public virtual Meter {
|
struct HeatCostMeter : public virtual Meter {
|
||||||
virtual double currentConsumption() = 0;
|
virtual double currentConsumption();
|
||||||
virtual string setDate() = 0;
|
virtual string setDate();
|
||||||
virtual double consumptionAtSetDate() = 0;
|
virtual double consumptionAtSetDate();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GenericMeter : public virtual Meter {
|
struct GenericMeter : public virtual Meter {
|
||||||
|
|
|
@ -72,12 +72,15 @@ protected:
|
||||||
void addMedia(int media);
|
void addMedia(int media);
|
||||||
void addManufacturer(int m);
|
void addManufacturer(int m);
|
||||||
void addPrint(string vname, Quantity vquantity, function<double(Unit)> getValueFunc, string help, bool field);
|
void addPrint(string vname, Quantity vquantity, function<double(Unit)> getValueFunc, string help, bool field);
|
||||||
|
void handleTelegram(Telegram *t);
|
||||||
void printMeter(Telegram *t,
|
void printMeter(Telegram *t,
|
||||||
string *human_readable,
|
string *human_readable,
|
||||||
string *fields, char separator,
|
string *fields, char separator,
|
||||||
string *json,
|
string *json,
|
||||||
vector<string> *envs);
|
vector<string> *envs);
|
||||||
|
|
||||||
|
virtual void processContent(Telegram *t) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
MeterType type_ {};
|
MeterType type_ {};
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
X(Energy,KWH) \
|
X(Energy,KWH) \
|
||||||
X(Power,KW) \
|
X(Power,KW) \
|
||||||
X(Volume,M3) \
|
X(Volume,M3) \
|
||||||
|
X(Flow,M3H) \
|
||||||
|
X(Temperature,C) \
|
||||||
|
|
||||||
|
|
||||||
#define LIST_OF_UNITS \
|
#define LIST_OF_UNITS \
|
||||||
|
@ -33,6 +35,8 @@
|
||||||
X(M3,m3,m3,Volume,"cubic meter") \
|
X(M3,m3,m3,Volume,"cubic meter") \
|
||||||
X(L,l,l,Volume,"litre") \
|
X(L,l,l,Volume,"litre") \
|
||||||
X(KW,kw,kW,Power,"kilo Watt") \
|
X(KW,kw,kW,Power,"kilo Watt") \
|
||||||
|
X(M3H,m3h,m3/h,Flow,"cubic meters per hour") \
|
||||||
|
X(C,c,°C,Temperature,"celsius") \
|
||||||
|
|
||||||
enum class Unit
|
enum class Unit
|
||||||
{
|
{
|
||||||
|
|
Ładowanie…
Reference in New Issue