Converted water meters to unit scaling.

pull/31/head
weetmuts 2019-05-04 17:38:10 +02:00
rodzic 49f7410519
commit 2a47115cb9
10 zmienionych plików z 225 dodań i 506 usunięć

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -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 "";
}

Wyświetl plik

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

Wyświetl plik

@ -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 "";
}

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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