diff --git a/simulations/simulation_t1.txt b/simulations/simulation_t1.txt index edb373f..4fa463a 100644 --- a/simulations/simulation_t1.txt +++ b/simulations/simulation_t1.txt @@ -35,8 +35,8 @@ telegram=|4E4401061010101002027A00004005|2F2F0E035040691500000B2B300300066D00790 # Test MKRadio3 T1 telegrams telegram=|2F446850313233347462A2|069F255900B029310000000306060906030609070606050509050505050407040605070500| -{"media":"warm water","meter":"mkradio3","name":"Duschen","id":"34333231","total_m3":13.8,"target_m3":8.9,"timestamp":"1111-11-11T11:11:11Z"} -|Duschen;34333231;13.800000;8.900000;1111-11-11 11:11.11 +{"media":"warm water","meter":"mkradio3","name":"Duschen","id":"34333231","total_m3":13.8,"target_m3":8.9,"current_date":"2021-04-27T02:00:00Z","prev_date":"2018-12-31T02:00:00Z","timestamp":"1111-11-11T11:11:11Z"} +|Duschen;34333231;13.800000;8.900000;2021-04-27T02:00:00Z;2018-12-31T02:00:00Z;1111-11-11 11:11.11 # Test MKRadio4 T1 telegrams @@ -198,8 +198,8 @@ telegram=|2E4492159293949511377ABE0020252F2F|04135515000004FD971D808000004413000 # Test Techem TSD2 smoke detector telegram=|294468506935639176F0A0|009F2782290060822900000401D6311AF93E1BF93E008DC3009ED4000FE500| -{"media":"smoke detector","meter":"tsd2","name":"Smokey","id":"91633569","status":"OK","timestamp":"1111-11-11T11:11:11Z"} -|Smokey;91633569;OK;1111-11-11 11:11.11 +{"media":"smoke detector","meter":"tsd2","name":"Smokey","id":"91633569","status":"OK","prev_date":"2019-12-31T02:00:00Z","timestamp":"1111-11-11T11:11:11Z"} +|Smokey;91633569;OK;2019-12-31T02:00:00Z;1111-11-11 11:11.11 # Test Techem Compact V heat meter telegram=|36446850626262624543A1|009F2777010060780000000A000000000000000000000000000000000000000000000000A0400000B4010000| diff --git a/src/meter_mkradio3.cc b/src/meter_mkradio3.cc index 52d17e0..115a16e 100644 --- a/src/meter_mkradio3.cc +++ b/src/meter_mkradio3.cc @@ -32,12 +32,16 @@ struct MKRadio3 : public virtual WaterMeter, public virtual MeterCommonImplement bool hasTotalWaterConsumption(); double targetWaterConsumption(Unit u); bool hasTargetWaterConsumption(); + string currentDate(); + string previousDate(); private: void processContent(Telegram *t); double total_water_consumption_m3_ {}; double target_water_consumption_m3_ {}; + string current_date_ {}; + string previous_date_ {}; }; MKRadio3::MKRadio3(MeterInfo &mi) : @@ -56,6 +60,16 @@ MKRadio3::MKRadio3(MeterInfo &mi) : [&](Unit u){ return targetWaterConsumption(u); }, "The total water consumption recorded at the beginning of this month.", true, true); + + addPrint("current_date", Quantity::Text, + [&](){ return currentDate(); }, + "Date of current billing period.", + true, true); + + addPrint("prev_date", Quantity::Text, + [&](){ return previousDate(); }, + "Date of previous billing period.", + true, true); } shared_ptr createMKRadio3(MeterInfo &mi) @@ -74,17 +88,46 @@ void MKRadio3::processContent(Telegram *t) t->extractPayload(&content); + // Previous date + uint16_t prev_date = (content[2] << 8) | content[1]; + uint prev_date_day = (prev_date >> 0) & 0x1F; + uint prev_date_month = (prev_date >> 5) & 0x0F; + uint prev_date_year = (prev_date >> 9) & 0x3F; + strprintf(previous_date_, "%d-%02d-%02dT02:00:00Z", prev_date_year+2000, prev_date_month, prev_date_day); + + string prev_date_str; + strprintf(prev_date_str, "%04x", prev_date); + uint offset = t->parsed.size() + 1; + vendor_values["0215"] = { offset, DVEntry(MeasurementType::Unknown, 0x6c, 0, 0, 0, prev_date_str) }; + t->explanations.push_back({ offset, prev_date_str }); + t->addMoreExplanation(offset, " previous date (%s)", previous_date_.c_str()); + + // Previous consumption uchar prev_lo = content[3]; uchar prev_hi = content[4]; double prev = (256.0*prev_hi+prev_lo)/10.0; string prevs; strprintf(prevs, "%02x%02x", prev_lo, prev_hi); - int offset = t->parsed.size()+3; + offset = t->parsed.size()+3; vendor_values["0215"] = { offset, DVEntry(MeasurementType::Instantaneous, 0x15, 0, 0, 0, prevs) }; t->explanations.push_back({ offset, prevs }); t->addMoreExplanation(offset, " prev consumption (%f m3)", prev); + // Current date + uint16_t current_date = (content[6] << 8) | content[5]; + uint current_date_day = (current_date >> 4) & 0x1F; + uint current_date_month = (current_date >> 9) & 0x0F; + strprintf(current_date_, "%s-%02d-%02dT02:00:00Z", currentYear().c_str(), current_date_month, current_date_day); + + string current_date_str; + strprintf(current_date_str, "%04x", current_date); + offset = t->parsed.size() + 5; + vendor_values["0215"] = { offset, DVEntry(MeasurementType::Unknown, 0x6c, 0, 0, 0, current_date_str) }; + t->explanations.push_back({ offset, current_date_str }); + t->addMoreExplanation(offset, " current date (%s)", current_date_.c_str()); + + // Current consumption uchar curr_lo = content[7]; uchar curr_hi = content[8]; double curr = (256.0*curr_hi+curr_lo)/10.0; @@ -120,3 +163,11 @@ bool MKRadio3::hasTargetWaterConsumption() { return true; } + +string MKRadio3::currentDate() { + return current_date_; +} + +string MKRadio3::previousDate() { + return previous_date_; +} diff --git a/src/meter_tsd2.cc b/src/meter_tsd2.cc index ec665d7..7a022a1 100644 --- a/src/meter_tsd2.cc +++ b/src/meter_tsd2.cc @@ -29,6 +29,7 @@ struct MeterTSD2 : public virtual SmokeDetector, public virtual MeterCommonImple string status(); bool smokeDetected(); + string previousDate(); private: @@ -38,6 +39,7 @@ private: uint16_t info_codes_ {}; bool error_ {}; + string previous_date_ {}; }; MeterTSD2::MeterTSD2(MeterInfo &mi) : @@ -51,6 +53,11 @@ MeterTSD2::MeterTSD2(MeterInfo &mi) : [&](){ return status(); }, "The current status: OK, SMOKE or ERROR.", true, true); + + addPrint("prev_date", Quantity::Text, + [&](){ return previousDate(); }, + "Date of previous billing period.", + true, true); } shared_ptr createTSD2(MeterInfo &mi) @@ -68,16 +75,28 @@ void MeterTSD2::processContent(Telegram *t) vector data; t->extractPayload(&data); - if (data.size() > 0) - { - info_codes_ = data[0]; - error_ = false; - // Check CRC etc here.... - } - else + if(data.empty()) { error_ = true; + return; } + + info_codes_ = data[0]; + error_ = false; + // Check CRC etc here.... + + // Previous date + uint16_t prev_date = (data[2] << 8) | data[1]; + uint prev_date_day = (prev_date >> 0) & 0x1F; + uint prev_date_month = (prev_date >> 5) & 0x0F; + uint prev_date_year = (prev_date >> 9) & 0x3F; + strprintf(previous_date_, "%d-%02d-%02dT02:00:00Z", prev_date_year+2000, prev_date_month, prev_date_day); + + string prev_date_str; + strprintf(prev_date_str, "%04x", prev_date); + uint offset = t->parsed.size() + 1; + t->explanations.push_back({ offset, prev_date_str }); + t->addMoreExplanation(offset, " previous date (%s)", previous_date_.c_str()); } string MeterTSD2::status() @@ -101,3 +120,7 @@ string MeterTSD2::status() } return "OK"; } + +string MeterTSD2::previousDate() { + return previous_date_; +} diff --git a/src/util.cc b/src/util.cc index a2d9a76..1141e35 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1320,6 +1320,17 @@ string makeQuotedJson(string &s) return string("\"")+key+"\":\""+value+"\""; } +string currentYear() { + char datetime[40]; + memset(datetime, 0, sizeof(datetime)); + + struct timeval tv; + gettimeofday(&tv, NULL); + + strftime(datetime, 20, "%Y", localtime(&tv.tv_sec)); + return string(datetime); +} + string currentDay() { char datetime[40]; diff --git a/src/util.h b/src/util.h index beacbcb..9bef1c9 100644 --- a/src/util.h +++ b/src/util.h @@ -170,6 +170,7 @@ bool startsWith(std::string &s, const char *prefix); // Given alfa=beta it returns "alfa":"beta" std::string makeQuotedJson(std::string &s); +std::string currentYear(); std::string currentDay(); std::string currentHour(); std::string currentMinute();