diff --git a/src/meter_apator162.cc b/src/meter_apator162.cc index 5d5d659..e619770 100644 --- a/src/meter_apator162.cc +++ b/src/meter_apator162.cc @@ -36,15 +36,15 @@ struct MeterApator162 : public virtual WaterMeter, public virtual MeterCommonImp MeterApator162(WMBus *bus, string& name, string& id, string& key); // Total water counted through the meter - double totalWaterConsumption(); + double totalWaterConsumption(Unit u); bool hasTotalWaterConsumption(); - double targetWaterConsumption(); + double targetWaterConsumption(Unit u); bool hasTargetWaterConsumption(); - double maxFlow(); + double maxFlow(Unit u); bool hasMaxFlow(); - double flowTemperature(); + double flowTemperature(Unit u); bool hasFlowTemperature(); - double externalTemperature(); + double externalTemperature(Unit u); bool hasExternalTemperature(); 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_; } @@ -166,7 +166,7 @@ void MeterApator162::printMeter(Telegram *t, "%s", name().c_str(), t->id.c_str(), - totalWaterConsumption(), + totalWaterConsumption(Unit::M3), datetimeOfUpdateHumanReadable().c_str()); *human_readable = buf; @@ -178,7 +178,7 @@ void MeterApator162::printMeter(Telegram *t, "%s", name().c_str(), separator, t->id.c_str(), separator, - totalWaterConsumption(), separator, + totalWaterConsumption(Unit::M3), separator, datetimeOfUpdateRobot().c_str()); *fields = buf; @@ -198,7 +198,7 @@ void MeterApator162::printMeter(Telegram *t, mediaTypeJSON(t->a_field_device_type).c_str(), name().c_str(), t->id.c_str(), - totalWaterConsumption(), + totalWaterConsumption(Unit::M3), datetimeOfUpdateRobot().c_str()); *json = buf; @@ -206,7 +206,7 @@ void MeterApator162::printMeter(Telegram *t, envs->push_back(string("METER_JSON=")+*json); envs->push_back(string("METER_TYPE=apator162")); 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()); } @@ -215,7 +215,7 @@ bool MeterApator162::hasTotalWaterConsumption() return true; } -double MeterApator162::targetWaterConsumption() +double MeterApator162::targetWaterConsumption(Unit u) { return 0.0; } @@ -225,7 +225,7 @@ bool MeterApator162::hasTargetWaterConsumption() return false; } -double MeterApator162::maxFlow() +double MeterApator162::maxFlow(Unit u) { return 0.0; } @@ -235,7 +235,7 @@ bool MeterApator162::hasMaxFlow() return false; } -double MeterApator162::flowTemperature() +double MeterApator162::flowTemperature(Unit u) { return 127; } @@ -245,7 +245,7 @@ bool MeterApator162::hasFlowTemperature() return false; } -double MeterApator162::externalTemperature() +double MeterApator162::externalTemperature(Unit u) { return 127; } diff --git a/src/meter_iperl.cc b/src/meter_iperl.cc index 48fcfc6..3e8190b 100644 --- a/src/meter_iperl.cc +++ b/src/meter_iperl.cc @@ -37,15 +37,15 @@ struct MeterIperl : public virtual WaterMeter, public virtual MeterCommonImpleme MeterIperl(WMBus *bus, string& name, string& id, string& key); // Total water counted through the meter - double totalWaterConsumption(); + double totalWaterConsumption(Unit u); bool hasTotalWaterConsumption(); - double targetWaterConsumption(); + double targetWaterConsumption(Unit u); bool hasTargetWaterConsumption(); - double maxFlow(); + double maxFlow(Unit u); bool hasMaxFlow(); - double flowTemperature(); + double flowTemperature(Unit u); bool hasFlowTemperature(); - double externalTemperature(); + double externalTemperature(Unit u); bool hasExternalTemperature(); 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_; } @@ -160,8 +160,8 @@ void MeterIperl::printMeter(Telegram *t, "%s", name().c_str(), t->id.c_str(), - totalWaterConsumption(), - maxFlow(), + totalWaterConsumption(Unit::M3), + maxFlow(Unit::M3H), datetimeOfUpdateHumanReadable().c_str()); *human_readable = buf; @@ -174,8 +174,8 @@ void MeterIperl::printMeter(Telegram *t, "%s", name().c_str(), separator, t->id.c_str(), separator, - totalWaterConsumption(), separator, - maxFlow(), separator, + totalWaterConsumption(Unit::M3), separator, + maxFlow(Unit::M3H), separator, datetimeOfUpdateRobot().c_str()); *fields = buf; @@ -196,8 +196,8 @@ void MeterIperl::printMeter(Telegram *t, mediaTypeJSON(t->a_field_device_type).c_str(), name().c_str(), t->id.c_str(), - totalWaterConsumption(), - maxFlow(), + totalWaterConsumption(Unit::M3), + maxFlow(Unit::M3H), datetimeOfUpdateRobot().c_str()); *json = buf; @@ -205,8 +205,8 @@ void MeterIperl::printMeter(Telegram *t, envs->push_back(string("METER_JSON=")+*json); envs->push_back(string("METER_TYPE=iperl")); envs->push_back(string("METER_ID=")+t->id); - envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption())); - envs->push_back(string("METER_MAX_FLOW_M3H=")+to_string(maxFlow())); + envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption(Unit::M3))); + envs->push_back(string("METER_MAX_FLOW_M3H=")+to_string(maxFlow(Unit::M3H))); envs->push_back(string("METER_TIMESTAMP=")+datetimeOfUpdateRobot()); } @@ -215,7 +215,7 @@ bool MeterIperl::hasTotalWaterConsumption() return true; } -double MeterIperl::targetWaterConsumption() +double MeterIperl::targetWaterConsumption(Unit u) { return 0.0; } @@ -225,7 +225,7 @@ bool MeterIperl::hasTargetWaterConsumption() return false; } -double MeterIperl::maxFlow() +double MeterIperl::maxFlow(Unit u) { return max_flow_; } @@ -235,7 +235,7 @@ bool MeterIperl::hasMaxFlow() return true; } -double MeterIperl::flowTemperature() +double MeterIperl::flowTemperature(Unit u) { return 127; } @@ -245,7 +245,7 @@ bool MeterIperl::hasFlowTemperature() return false; } -double MeterIperl::externalTemperature() +double MeterIperl::externalTemperature(Unit u) { return 127; } diff --git a/src/meter_mkradio3.cc b/src/meter_mkradio3.cc index 3f2e26d..3b1f038 100644 --- a/src/meter_mkradio3.cc +++ b/src/meter_mkradio3.cc @@ -32,41 +32,20 @@ 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); - // Total water counted through the meter - double totalWaterConsumption(); + double totalWaterConsumption(Unit u); bool hasTotalWaterConsumption(); - double targetWaterConsumption(); + double targetWaterConsumption(Unit u); 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 *envs); private: - void handleTelegram(Telegram *t); void processContent(Telegram *t); - string decodeTime(int time); - double total_water_consumption_ {}; - double target_water_consumption_ {}; + double total_water_consumption_m3_ {}; + double target_water_consumption_m3_ {}; }; 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(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*)); } - -double MKRadio3::totalWaterConsumption() -{ - return total_water_consumption_; -} - unique_ptr createMKRadio3(WMBus *bus, string& name, string& id, string& key) { return unique_ptr(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 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) { // Meter record: @@ -154,75 +103,14 @@ void MKRadio3::processContent(Telegram *t) t->explanations.push_back({ offset, currs }); t->addMoreExplanation(offset, " curr consumption (%f m3)", curr); - total_water_consumption_ = prev+curr; - target_water_consumption_ = prev; + total_water_consumption_m3_ = prev+curr; + target_water_consumption_m3_ = prev; } -void MKRadio3::printMeter(Telegram *t, - string *human_readable, - string *fields, char separator, - string *json, - vector *envs) +double MKRadio3::totalWaterConsumption(Unit u) { - char buf[65536]; - buf[65535] = 0; - - 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()); + assertQuantity(u, Quantity::Volume); + return convert(total_water_consumption_m3_, Unit::M3, u); } bool MKRadio3::hasTotalWaterConsumption() @@ -230,72 +118,12 @@ bool MKRadio3::hasTotalWaterConsumption() return true; } -double MKRadio3::targetWaterConsumption() +double MKRadio3::targetWaterConsumption(Unit u) { - return target_water_consumption_; + return target_water_consumption_m3_; } bool MKRadio3::hasTargetWaterConsumption() { 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 ""; -} diff --git a/src/meter_multical21.cc b/src/meter_multical21.cc index 31bb889..e2ff143 100644 --- a/src/meter_multical21.cc +++ b/src/meter_multical21.cc @@ -48,23 +48,23 @@ struct MeterMultical21 : public virtual WaterMeter, public virtual MeterCommonIm MeterMultical21(WMBus *bus, string& name, string& id, string& key, MeterType mt); // Total water counted through the meter - double totalWaterConsumption(); + double totalWaterConsumption(Unit u); bool hasTotalWaterConsumption(); // Meter sends target water consumption or max flow, depending on meter configuration // 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. - double targetWaterConsumption(); + double targetWaterConsumption(Unit u); bool hasTargetWaterConsumption(); // Max flow during last month or last 24 hours depending on meter configuration. - double maxFlow(); + double maxFlow(Unit u); bool hasMaxFlow(); // Water temperature - double flowTemperature(); + double flowTemperature(Unit u); bool hasFlowTemperature(); // Surrounding temperature - double externalTemperature(); + double externalTemperature(Unit u); bool hasExternalTemperature(); // 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_; } @@ -132,7 +132,7 @@ bool MeterMultical21::hasTotalWaterConsumption() return has_total_water_consumption_; } -double MeterMultical21::targetWaterConsumption() +double MeterMultical21::targetWaterConsumption(Unit u) { return target_volume_; } @@ -142,7 +142,7 @@ bool MeterMultical21::hasTargetWaterConsumption() return has_target_volume_; } -double MeterMultical21::maxFlow() +double MeterMultical21::maxFlow(Unit u) { return max_flow_; } @@ -152,7 +152,7 @@ bool MeterMultical21::hasMaxFlow() return has_max_flow_; } -double MeterMultical21::flowTemperature() +double MeterMultical21::flowTemperature(Unit u) { return flow_temperature_; } @@ -162,7 +162,7 @@ bool MeterMultical21::hasFlowTemperature() return has_flow_temperature_; } -double MeterMultical21::externalTemperature() +double MeterMultical21::externalTemperature(Unit u) { return external_temperature_; } @@ -500,14 +500,14 @@ void MeterMultical21::printMeter(Telegram *t, et[9] = 0; if (hasFlowTemperature()) { - snprintf(ft, sizeof(ft)-1, "% 2.0f", flowTemperature()); + snprintf(ft, sizeof(ft)-1, "% 2.0f", flowTemperature(Unit::C)); } else { ft[0] = '-'; ft[1] = 0; } if (hasExternalTemperature()) { - snprintf(et, sizeof(et)-1, "% 2.0f", externalTemperature()); + snprintf(et, sizeof(et)-1, "% 2.0f", externalTemperature(Unit::C)); } else { et[0] = '-'; et[1] = 0; @@ -525,9 +525,9 @@ void MeterMultical21::printMeter(Telegram *t, "%s", name().c_str(), t->id.c_str(), - totalWaterConsumption(), - targetWaterConsumption(), - maxFlow(), + totalWaterConsumption(Unit::M3), + targetWaterConsumption(Unit::M3), + maxFlow(Unit::M3H), ft, et, statusHumanReadable().c_str(), @@ -547,11 +547,11 @@ void MeterMultical21::printMeter(Telegram *t, "%s", name().c_str(), separator, t->id.c_str(), separator, - totalWaterConsumption(), separator, - targetWaterConsumption(), separator, - maxFlow(), separator, - flowTemperature(), separator, - externalTemperature(), separator, + totalWaterConsumption(Unit::M3), separator, + targetWaterConsumption(Unit::M3), separator, + maxFlow(Unit::M3H), separator, + flowTemperature(Unit::C), separator, + externalTemperature(Unit::C), separator, statusHumanReadable().c_str(), separator, datetimeOfUpdateRobot().c_str()); @@ -582,11 +582,11 @@ void MeterMultical21::printMeter(Telegram *t, meter_name_, name().c_str(), t->id.c_str(), - totalWaterConsumption(), - targetWaterConsumption(), - maxFlow(), - flowTemperature(), - externalTemperature(), + totalWaterConsumption(Unit::M3), + targetWaterConsumption(Unit::M3), + maxFlow(Unit::M3H), + flowTemperature(Unit::C), + externalTemperature(Unit::C), status().c_str(), // DRY REVERSED LEAK BURST timeDry().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_TYPE=")+meter_name_); 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_MAX_FLOW_M3H=")+to_string(maxFlow())); - envs->push_back(string("METER_FLOW_TEMPERATURE=")+to_string(flowTemperature())); - envs->push_back(string("METER_EXTERNAL_TEMPERATURE=")+to_string(externalTemperature())); + envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption(Unit::M3))); + envs->push_back(string("METER_TARGET_M3=")+to_string(targetWaterConsumption(Unit::M3))); + envs->push_back(string("METER_MAX_FLOW_M3H=")+to_string(maxFlow(Unit::M3H))); + envs->push_back(string("METER_FLOW_TEMPERATURE=")+to_string(flowTemperature(Unit::C))); + envs->push_back(string("METER_EXTERNAL_TEMPERATURE=")+to_string(externalTemperature(Unit::C))); envs->push_back(string("METER_STATUS=")+status()); envs->push_back(string("METER_TIME_DRY=")+timeDry()); envs->push_back(string("METER_TIME_REVERSED=")+timeReversed()); diff --git a/src/meter_supercom587.cc b/src/meter_supercom587.cc index a9e8114..5b489b5 100644 --- a/src/meter_supercom587.cc +++ b/src/meter_supercom587.cc @@ -36,56 +36,42 @@ struct MeterSupercom587 : public virtual WaterMeter, public virtual MeterCommonI MeterSupercom587(WMBus *bus, string& name, string& id, string& key); // Total water counted through the meter - double totalWaterConsumption(); + double totalWaterConsumption(Unit u); 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 *envs); private: void handleTelegram(Telegram *t); void processContent(Telegram *t); string decodeTime(int time); - double total_water_consumption_ {}; + double total_water_consumption_m3_ {}; }; +unique_ptr createSupercom587(WMBus *bus, string& name, string& id, string& key) +{ + return unique_ptr(new MeterSupercom587(bus,name,id,key)); +} + MeterSupercom587::MeterSupercom587(WMBus *bus, string& name, string& id, string& key) : MeterCommonImplementation(bus, name, id, key, MeterType::SUPERCOM587, MANUFACTURER_SON, LinkMode::T1) { addMedia(0x06); 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*)); } - -double MeterSupercom587::totalWaterConsumption() +double MeterSupercom587::totalWaterConsumption(Unit u) { - return total_water_consumption_; + assertQuantity(u, Quantity::Volume); + return convert(total_water_consumption_m3_, Unit::M3, u); } -unique_ptr createSupercom587(WMBus *bus, string& name, string& id, string& key) -{ - return unique_ptr(new MeterSupercom587(bus,name,id,key)); -} void MeterSupercom587::handleTelegram(Telegram *t) { @@ -131,141 +117,11 @@ void MeterSupercom587::processContent(Telegram *t) int offset; - extractDVdouble(&values, "0C13", &offset, &total_water_consumption_); - t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_); -} - -void MeterSupercom587::printMeter(Telegram *t, - string *human_readable, - string *fields, char separator, - string *json, - vector *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()); + extractDVdouble(&values, "0C13", &offset, &total_water_consumption_m3_); + t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_m3_); } bool MeterSupercom587::hasTotalWaterConsumption() { 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 ""; -} diff --git a/src/meter_vario451.cc b/src/meter_vario451.cc index 15d93fb..6736b5a 100644 --- a/src/meter_vario451.cc +++ b/src/meter_vario451.cc @@ -23,11 +23,7 @@ #include"units.h" #include"util.h" -#include -#include -#include #include -#include #include 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 currentPeriodEnergyConsumption(Unit u); - double currentPowerConsumption(Unit u); double previousPeriodEnergyConsumption(Unit u); - double totalVolume(Unit u); private: - void handleTelegram(Telegram *t); void processContent(Telegram *t); double total_energy_gj_ {}; @@ -50,6 +43,11 @@ struct MeterVario451 : public virtual HeatMeter, public virtual MeterCommonImple double prev_energy_gj_ {}; }; +unique_ptr createVario451(WMBus *bus, string& name, string& id, string& key) +{ + return unique_ptr(new MeterVario451(bus,name,id,key)); +} + MeterVario451::MeterVario451(WMBus *bus, string& name, string& id, string& key) : 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); } -double MeterVario451::currentPowerConsumption(Unit u) -{ - return 0; -} - double MeterVario451::previousPeriodEnergyConsumption(Unit u) { assertQuantity(u, Quantity::Energy); 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 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) { map> vendor_values; @@ -172,8 +124,3 @@ void MeterVario451::processContent(Telegram *t) curr_energy_gj_ = curr; prev_energy_gj_ = prev; } - -unique_ptr createVario451(WMBus *bus, string& name, string& id, string& key) -{ - return unique_ptr(new MeterVario451(bus,name,id,key)); -} diff --git a/src/meters.cc b/src/meters.cc index 65789b0..dad24a6 100644 --- a/src/meters.cc +++ b/src/meters.cc @@ -18,6 +18,8 @@ #include"meters.h" #include"meters_common_implementation.h" #include"units.h" +#include"wmbus.h" +#include"wmbus_utils.h" #include #include @@ -253,6 +255,51 @@ string concatFields(Meter *m, Telegram *t, char c, vector &prints, vector 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 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, string *human_readable, string *fields, char separator, @@ -313,3 +360,36 @@ void MeterCommonImplementation::printMeter(Telegram *t, } 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; } diff --git a/src/meters.h b/src/meters.h index 3cb9bbb..df6df74 100644 --- a/src/meters.h +++ b/src/meters.h @@ -71,6 +71,7 @@ struct Meter { string *json, vector *envs) = 0; + void handleTelegram(Telegram *t); virtual bool isTelegramForMe(Telegram *t) = 0; virtual bool useAes() = 0; virtual vector key() = 0; @@ -86,44 +87,44 @@ struct Meter { }; struct WaterMeter : public virtual Meter { - virtual double totalWaterConsumption() = 0; // m3 - virtual bool hasTotalWaterConsumption() = 0; - virtual double targetWaterConsumption() = 0; // m3 - virtual bool hasTargetWaterConsumption() = 0; - virtual double maxFlow() = 0; - virtual bool hasMaxFlow() = 0; - virtual double flowTemperature() = 0; // °C - virtual bool hasFlowTemperature() = 0; - virtual double externalTemperature() = 0; // °C - virtual bool hasExternalTemperature() = 0; + virtual double totalWaterConsumption(Unit u); // m3 + virtual bool hasTotalWaterConsumption(); + virtual double targetWaterConsumption(Unit u); // m3 + virtual bool hasTargetWaterConsumption(); + virtual double maxFlow(Unit u); // m3/s + virtual bool hasMaxFlow(); + virtual double flowTemperature(Unit u); // °C + virtual bool hasFlowTemperature(); + virtual double externalTemperature(Unit u); // °C + virtual bool hasExternalTemperature(); - virtual string statusHumanReadable() = 0; - virtual string status() = 0; - virtual string timeDry() = 0; - virtual string timeReversed() = 0; - virtual string timeLeaking() = 0; - virtual string timeBursting() = 0; + virtual string statusHumanReadable(); + virtual string status(); + virtual string timeDry(); + virtual string timeReversed(); + virtual string timeLeaking(); + virtual string timeBursting(); }; struct HeatMeter : public virtual Meter { - virtual double totalEnergyConsumption(Unit u) = 0; // kwh - virtual double currentPeriodEnergyConsumption(Unit u) = 0; // kwh - virtual double previousPeriodEnergyConsumption(Unit u) = 0; // kwh - virtual double currentPowerConsumption(Unit u) = 0; // kw - virtual double totalVolume(Unit u) = 0; // m3 + virtual double totalEnergyConsumption(Unit u); // kwh + virtual double currentPeriodEnergyConsumption(Unit u); // kwh + virtual double previousPeriodEnergyConsumption(Unit u); // kwh + virtual double currentPowerConsumption(Unit u); // kw + virtual double totalVolume(Unit u); // m3 }; struct ElectricityMeter : public virtual Meter { - virtual double totalEnergyConsumption() = 0; // kwh - virtual double currentPowerConsumption() = 0; // kw - virtual double totalEnergyProduction() = 0; // kwh - virtual double currentPowerProduction() = 0; // kw + virtual double totalEnergyConsumption(); // kwh + virtual double currentPowerConsumption(); // kw + virtual double totalEnergyProduction(); // kwh + virtual double currentPowerProduction(); // kw }; struct HeatCostMeter : public virtual Meter { - virtual double currentConsumption() = 0; - virtual string setDate() = 0; - virtual double consumptionAtSetDate() = 0; + virtual double currentConsumption(); + virtual string setDate(); + virtual double consumptionAtSetDate(); }; struct GenericMeter : public virtual Meter { diff --git a/src/meters_common_implementation.h b/src/meters_common_implementation.h index 39de977..29f9c94 100644 --- a/src/meters_common_implementation.h +++ b/src/meters_common_implementation.h @@ -72,12 +72,15 @@ protected: void addMedia(int media); void addManufacturer(int m); void addPrint(string vname, Quantity vquantity, function getValueFunc, string help, bool field); + void handleTelegram(Telegram *t); void printMeter(Telegram *t, string *human_readable, string *fields, char separator, string *json, vector *envs); + virtual void processContent(Telegram *t) = 0; + private: MeterType type_ {}; diff --git a/src/units.h b/src/units.h index 7b48234..d6a9c25 100644 --- a/src/units.h +++ b/src/units.h @@ -25,6 +25,8 @@ X(Energy,KWH) \ X(Power,KW) \ X(Volume,M3) \ + X(Flow,M3H) \ + X(Temperature,C) \ #define LIST_OF_UNITS \ @@ -33,6 +35,8 @@ X(M3,m3,m3,Volume,"cubic meter") \ X(L,l,l,Volume,"litre") \ 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 {