From 73c18c18318c604caecc435fc8bbb2bf4b304df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Tue, 26 Jan 2021 22:22:59 +0100 Subject: [PATCH] Added evo868 water wmbus module. --- CHANGES | 1 + Makefile | 1 + README.md | 1 + simulations/simulation_t1.txt | 5 + src/meter_evo868.cc | 369 ++++++++++++++++++++++++++++++++++ src/meters.h | 2 + src/testinternals.cc | 25 +++ src/util.cc | 55 +++++ src/util.h | 1 + tests/test_listen_to_all.sh | 5 + tests/test_t1_meters.sh | 1 + 11 files changed, 466 insertions(+) create mode 100644 src/meter_evo868.cc diff --git a/CHANGES b/CHANGES index a39a35d..758c652 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,5 @@ +Added support for evo868 water meter addon module. Added support for whe542 heat cost allocator. Marc Kolly improved the Waterstar meter and added better error codes diff --git a/Makefile b/Makefile index 5a125c0..2e158c0 100644 --- a/Makefile +++ b/Makefile @@ -129,6 +129,7 @@ METER_OBJS:=\ $(BUILD)/meter_em24.o \ $(BUILD)/meter_emerlin868.o \ $(BUILD)/meter_ev200.o \ + $(BUILD)/meter_evo868.o \ $(BUILD)/meter_eurisii.o \ $(BUILD)/meter_fhkvdataiii.o \ $(BUILD)/meter_fhkvdataiv.o \ diff --git a/README.md b/README.md index d4aebeb..86adf90 100644 --- a/README.md +++ b/README.md @@ -267,6 +267,7 @@ Diehl/Sappel IZAR RC 868 I R4 PL (izar) (non-standard protocol) Diehl HYDRUS (hydrus) Elster Merlin 868 (emerlin868) Elster V200H (ev200) +Maddalena EVO 868 (evo868) Honeywell Q400 (q400) Kamstrup Multical 21 (multical21) Kamstrup flowIQ 2200 (flowiq2200) diff --git a/simulations/simulation_t1.txt b/simulations/simulation_t1.txt index d977396..c3f78a2 100644 --- a/simulations/simulation_t1.txt +++ b/simulations/simulation_t1.txt @@ -218,3 +218,8 @@ telegram=|294468506935639176F0A0|009F2782290060822900000401D6311AF93E1BF93E008DC telegram=|36446850626262624543A1|009F2777010060780000000A000000000000000000000000000000000000000000000000A0400000B4010000| {"media":"heat","meter":"compact5","name":"Heating","id":"62626262","total_kwh":495,"current_kwh":120,"previous_kwh":375,"timestamp":"1111-11-11T11:11:11Z"} |Heating;62626262;495.000000;120.000000;375.000000;1111-11-11 11:11.11 + +# Test Maddalena EVO 868 wmbus module on water meter +telegram=|aa4424347677787950077ac10000202f2f041306070000046d1e31b12104fd17000000000e787880048120004413c9040000426c9f2c840113c904000082016c9f2cd3013b9a0200c4016d0534a7218104fd280182046c9f2c840413c9040000c404131b00000084051300000000c405130000000084061300000000c406130000000084071300000000c407130000000084081300000000c408130000000084091300000000c4091300000000ffff| +{"media":"water","meter":"evo868","name":"Votchka","id":"79787776","total_m3":1.798,"device_date_time":"2021-01-17 17:30","current_status":"OK","fabrication_no":"000218400887","consumption_at_set_date_m3":1.225,"set_date":"2020-12-31","consumption_at_set_date_2_m3":1.225,"set_date_2":"2020-12-31","max_flow_since_datetime_m3h":0.666,"max_flow_datetime":"2021-01-07 20:05","consumption_at_history_1_m3":1.225,"history_1_date":"2020-12-31","consumption_at_history_2_m3":0.027,"history_2_date":"2020-11-30","consumption_at_history_3_m3":0,"history_3_date":"2020-10-31","consumption_at_history_4_m3":0,"history_4_date":"2020-09-30","consumption_at_history_5_m3":0,"history_5_date":"2020-08-31","consumption_at_history_6_m3":0,"history_6_date":"2020-07-31","consumption_at_history_7_m3":0,"history_7_date":"2020-06-30","consumption_at_history_8_m3":0,"history_8_date":"2020-05-31","consumption_at_history_9_m3":0,"history_9_date":"2020-04-30","consumption_at_history_10_m3":0,"history_10_date":"2020-03-31","consumption_at_history_11_m3":0,"history_11_date":"2020-02-29","consumption_at_history_12_m3":0,"history_12_date":"2020-01-31","timestamp":"1111-11-11T11:11:11Z"} +|Votchka;79787776;1.798000;OK;1.225000;2020-12-31;1111-11-11 11:11.11 diff --git a/src/meter_evo868.cc b/src/meter_evo868.cc new file mode 100644 index 0000000..1398565 --- /dev/null +++ b/src/meter_evo868.cc @@ -0,0 +1,369 @@ +/* + Copyright (C) 2017-2020 Fredrik Öhrström + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include"dvparser.h" +#include"meters.h" +#include"meters_common_implementation.h" +#include"wmbus.h" +#include"wmbus_utils.h" +#include"util.h" + +#include +using namespace std; + +struct MeterEvo868 : public virtual WaterMeter, public virtual MeterCommonImplementation { + MeterEvo868(MeterInfo &mi); + + // Total water counted through the meter + double totalWaterConsumption(Unit u); + bool hasTotalWaterConsumption(); + uint32_t error_flags_ {}; + string fabrication_no_; + double consumption_at_set_date_m3_ {}; + string set_date_; + double consumption_at_set_date_2_m3_ {}; + string set_date_2_; + double max_flow_since_datetime_m3h_ {}; + string max_flow_datetime_; + + double consumption_at_history_date_m3_[12]; + string history_date_[12]; + + string status(); + +private: + void processContent(Telegram *t); + + double total_water_consumption_m3_ {}; + string device_date_time_; +}; + +shared_ptr createEVO868(MeterInfo &mi) +{ + return shared_ptr(new MeterEvo868(mi)); +} + +MeterEvo868::MeterEvo868(MeterInfo &mi) : + MeterCommonImplementation(mi, MeterType::EVO868) +{ + setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV); + + addLinkMode(LinkMode::T1); + + addPrint("total", Quantity::Volume, + [&](Unit u){ return totalWaterConsumption(u); }, + "The total water consumption recorded by this meter.", + true, true); + + addPrint("device_date_time", Quantity::Text, + [&](){ return device_date_time_; }, + "Device date time.", + false, true); + + addPrint("current_status", Quantity::Text, + [&](){ return status(); }, + "Status of meter.", + true, true); + + addPrint("fabrication_no", Quantity::Text, + [&](){ return fabrication_no_; }, + "Fabrication number.", + false, true); + + addPrint("consumption_at_set_date", Quantity::Volume, + [&](Unit u){ assertQuantity(u, Quantity::Volume); return convert(consumption_at_set_date_m3_, Unit::M3, u); }, + "The total water consumption at the most recent billing period date.", + true, true); + + addPrint("set_date", Quantity::Text, + [&](){ return set_date_; }, + "The most recent billing period date.", + true, true); + + addPrint("consumption_at_set_date_2", Quantity::Volume, + [&](Unit u){ assertQuantity(u, Quantity::Volume); return convert(consumption_at_set_date_2_m3_, Unit::M3, u); }, + "The total water consumption at the second recent billing period date.", + false, true); + + addPrint("set_date_2", Quantity::Text, + [&](){ return set_date_2_; }, + "The second recent billing period date.", + false, true); + + addPrint("max_flow_since_datetime", Quantity::Flow, + [&](Unit u){ assertQuantity(u, Quantity::Flow); return convert(max_flow_since_datetime_m3h_, Unit::M3H, u); }, + "Maximum water flow since date time.", + false, true); + + addPrint("max_flow_datetime", Quantity::Text, + [&](){ return max_flow_datetime_; }, + "The datetime to which maximum flow is measured.", + false, true); + + for (int i=1; i<=12; ++i) + { + string key = tostrprintf("consumption_at_history_%d", i); + string epl = tostrprintf("The total water consumption at the history date %d.", i); + + addPrint(key, Quantity::Volume, + [this,i](Unit u){ assertQuantity(u, Quantity::Volume); return convert(consumption_at_history_date_m3_[i-1], Unit::M3, u); }, + epl, + false, true); + key = tostrprintf("history_%d_date", i); + epl = tostrprintf("The history date %d.", i); + + addPrint(key, Quantity::Text, + [this,i](){ return history_date_[i-1]; }, + epl, + false, true); + } + +} + +void MeterEvo868::processContent(Telegram *t) +{ + /* +(evo868) 11: 04 dif (32 Bit Integer/Binary Instantaneous value) +(evo868) 12: 13 vif (Volume l) +(evo868) 13: * 06070000 total consumption (1.798000 m3) + +(evo868) 17: 04 dif (32 Bit Integer/Binary Instantaneous value) +(evo868) 18: 6D vif (Date and time type) +(evo868) 19: 1E31B121 + +(evo868) 1d: 04 dif (32 Bit Integer/Binary Instantaneous value) +(evo868) 1e: FD vif (Second extension of VIF-codes) +(evo868) 1f: 17 vife (Error flags (binary)) +(evo868) 20: 00000000 + +(evo868) 24: 0E dif (12 digit BCD Instantaneous value) +(evo868) 25: 78 vif (Fabrication no) +(evo868) 26: 788004812000 + +(evo868) 2c: 44 dif (32 Bit Integer/Binary Instantaneous value storagenr=1) +(evo868) 2d: 13 vif (Volume l) +(evo868) 2e: C9040000 + +(evo868) 32: 42 dif (16 Bit Integer/Binary Instantaneous value storagenr=1) +(evo868) 33: 6C vif (Date type G) +(evo868) 34: 9F2C + +(evo868) 36: 84 dif (32 Bit Integer/Binary Instantaneous value) +(evo868) 37: 01 dife (subunit=0 tariff=0 storagenr=2) +(evo868) 38: 13 vif (Volume l) +(evo868) 39: C9040000 + +(evo868) 3d: 82 dif (16 Bit Integer/Binary Instantaneous value) +(evo868) 3e: 01 dife (subunit=0 tariff=0 storagenr=2) +(evo868) 3f: 6C vif (Date type G) +(evo868) 40: 9F2C + +(evo868) 42: D3 dif (24 Bit Integer/Binary Maximum value storagenr=1) +(evo868) 43: 01 dife (subunit=0 tariff=0 storagenr=3) +(evo868) 44: 3B vif (Volume flow l/h) +(evo868) 45: 9A0200 + +(evo868) 48: C4 dif (32 Bit Integer/Binary Instantaneous value storagenr=1) +(evo868) 49: 01 dife (subunit=0 tariff=0 storagenr=3) +(evo868) 4a: 6D vif (Date and time type) +(evo868) 4b: 0534A721 + +(evo868) 4f: 81 dif (8 Bit Integer/Binary Instantaneous value) +(evo868) 50: 04 dife (subunit=0 tariff=0 storagenr=8) +(evo868) 51: FD vif (Second extension of VIF-codes) +(evo868) 52: 28 vife (Storage interval month(s)) +(evo868) 53: 01 + +(evo868) 54: 82 dif (16 Bit Integer/Binary Instantaneous value) +(evo868) 55: 04 dife (subunit=0 tariff=0 storagenr=8) +(evo868) 56: 6C vif (Date type G) +(evo868) 57: 9F2C + +(evo868) 59: 84 dif (32 Bit Integer/Binary Instantaneous value) +(evo868) 5a: 04 dife (subunit=0 tariff=0 storagenr=8) +(evo868) 5b: 13 vif (Volume l) +(evo868) 5c: C9040000 + +(evo868) 60: C4 dif (32 Bit Integer/Binary Instantaneous value storagenr=1) +(evo868) 61: 04 dife (subunit=0 tariff=0 storagenr=9) +(evo868) 62: 13 vif (Volume l) +(evo868) 63: 1B000000 + +(evo868) 67: 84 dif (32 Bit Integer/Binary Instantaneous value) +(evo868) 68: 05 dife (subunit=0 tariff=0 storagenr=10) +(evo868) 69: 13 vif (Volume l) +(evo868) 6a: 00000000 + +(evo868) 6e: C4 dif (32 Bit Integer/Binary Instantaneous value storagenr=1) +(evo868) 6f: 05 dife (subunit=0 tariff=0 storagenr=11) +(evo868) 70: 13 vif (Volume l) +(evo868) 71: 00000000 + +(evo868) 75: 84 dif (32 Bit Integer/Binary Instantaneous value) +(evo868) 76: 06 dife (subunit=0 tariff=0 storagenr=12) +(evo868) 77: 13 vif (Volume l) +(evo868) 78: 00000000 + +(evo868) 7c: C4 dif (32 Bit Integer/Binary Instantaneous value storagenr=1) +(evo868) 7d: 06 dife (subunit=0 tariff=0 storagenr=13) +(evo868) 7e: 13 vif (Volume l) +(evo868) 7f: 00000000 + +(evo868) 83: 84 dif (32 Bit Integer/Binary Instantaneous value) +(evo868) 84: 07 dife (subunit=0 tariff=0 storagenr=14) +(evo868) 85: 13 vif (Volume l) +(evo868) 86: 00000000 + +(evo868) 8a: C4 dif (32 Bit Integer/Binary Instantaneous value storagenr=1) +(evo868) 8b: 07 dife (subunit=0 tariff=0 storagenr=15) +(evo868) 8c: 13 vif (Volume l) +(evo868) 8d: 00000000 + +(evo868) 91: 84 dif (32 Bit Integer/Binary Instantaneous value) +(evo868) 92: 08 dife (subunit=0 tariff=0 storagenr=16) +(evo868) 93: 13 vif (Volume l) +(evo868) 94: 00000000 + +(evo868) 98: C4 dif (32 Bit Integer/Binary Instantaneous value storagenr=1) +(evo868) 99: 08 dife (subunit=0 tariff=0 storagenr=17) +(evo868) 9a: 13 vif (Volume l) +(evo868) 9b: 00000000 + +(evo868) 9f: 84 dif (32 Bit Integer/Binary Instantaneous value) +(evo868) a0: 09 dife (subunit=0 tariff=0 storagenr=18) +(evo868) a1: 13 vif (Volume l) +(evo868) a2: 00000000 + +(evo868) a6: C4 dif (32 Bit Integer/Binary Instantaneous value storagenr=1) +(evo868) a7: 09 dife (subunit=0 tariff=0 storagenr=19) +(evo868) a8: 13 vif (Volume l) +(evo868) a9: 00000000 + */ + int offset; + string key; + + if(findKey(MeasurementType::Instantaneous, ValueInformation::Volume, 0, 0, &key, &t->values)) { + extractDVdouble(&t->values, key, &offset, &total_water_consumption_m3_); + t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_m3_); + } + + if (findKey(MeasurementType::Instantaneous, ValueInformation::DateTime, 0, 0, &key, &t->values)) { + struct tm datetime; + extractDVdate(&t->values, key, &offset, &datetime); + device_date_time_ = strdatetime(&datetime); + t->addMoreExplanation(offset, " device datetime (%s)", device_date_time_.c_str()); + } + + extractDVuint32(&t->values, "04FD17", &offset, &error_flags_); + t->addMoreExplanation(offset, " error flags (%s)", status().c_str()); + + extractDVstring(&t->values, "0E78", &offset, &fabrication_no_); + reverse(fabrication_no_.begin(), fabrication_no_.end()); + t->addMoreExplanation(offset, " fabrication no (%s)", fabrication_no_.c_str()); + + if(findKey(MeasurementType::Instantaneous, ValueInformation::Volume, 1, 0, &key, &t->values)) { + extractDVdouble(&t->values, key, &offset, &consumption_at_set_date_m3_); + t->addMoreExplanation(offset, " consumption at set date (%f m3)", consumption_at_set_date_m3_); + } + + if (findKey(MeasurementType::Instantaneous, ValueInformation::Date, 1, 0, &key, &t->values)) { + struct tm date; + extractDVdate(&t->values, key, &offset, &date); + set_date_ = strdate(&date); + t->addMoreExplanation(offset, " set date (%s)", set_date_.c_str()); + } + + if(findKey(MeasurementType::Instantaneous, ValueInformation::Volume, 2, 0, &key, &t->values)) { + extractDVdouble(&t->values, key, &offset, &consumption_at_set_date_2_m3_); + t->addMoreExplanation(offset, " consumption at set date 2 (%f m3)", consumption_at_set_date_2_m3_); + } + + if (findKey(MeasurementType::Instantaneous, ValueInformation::Date, 2, 0, &key, &t->values)) { + struct tm date; + extractDVdate(&t->values, key, &offset, &date); + set_date_2_ = strdate(&date); + t->addMoreExplanation(offset, " set date 2 (%s)", set_date_2_.c_str()); + } + + if(findKey(MeasurementType::Maximum, ValueInformation::VolumeFlow, 3, 0, &key, &t->values)) { + extractDVdouble(&t->values, key, &offset, &max_flow_since_datetime_m3h_); + t->addMoreExplanation(offset, " max flow (%f m3/h)", max_flow_since_datetime_m3h_); + } + + if (findKey(MeasurementType::Instantaneous, ValueInformation::DateTime, 3, 0, &key, &t->values)) { + struct tm datetime; + extractDVdate(&t->values, key, &offset, &datetime); + max_flow_datetime_ = strdatetime(&datetime); + t->addMoreExplanation(offset, " max flow since datetime (%s)", max_flow_datetime_.c_str()); + } + + uint8_t month_increment = 0; + extractDVuint8(&t->values, "8104FD28", &offset, &month_increment); + t->addMoreExplanation(offset, " month increment (%d)", month_increment); + + struct tm date; + if (findKey(MeasurementType::Instantaneous, ValueInformation::Date, 8, 0, &key, &t->values)) { + extractDVdate(&t->values, key, &offset, &date); + string start = strdate(&date); + t->addMoreExplanation(offset, " history starts with date (%s)", start.c_str()); + } + + // 12 months of historical data, starting in storage 8. + for (int i=1; i<=12; ++i) + { + if(findKey(MeasurementType::Instantaneous, ValueInformation::Volume, i+7, 0, &key, &t->values)) { + extractDVdouble(&t->values, key, &offset, &consumption_at_history_date_m3_[i-1]); + t->addMoreExplanation(offset, " consumption at history %d (%f m3)", i, consumption_at_history_date_m3_[i-1]); + struct tm d = date; + if (i>1) addMonths(&d, 1-i); + history_date_[i-1] = strdate(&d); + } + } +} + +double MeterEvo868::totalWaterConsumption(Unit u) +{ + assertQuantity(u, Quantity::Volume); + return convert(total_water_consumption_m3_, Unit::M3, u); +} + +bool MeterEvo868::hasTotalWaterConsumption() +{ + return true; +} + +string MeterEvo868::status() +{ + if (error_flags_ == 0) + { + return "OK"; + } + + /* Possible errors according to datasheet: + overflow (threshold configurable, must be activated) + backflow (threshold set, configurable) + leak + meter blocked + non-used (days threshold set, configurable) + magnetic and mechanical tampering (removal) + */ + + // How do we decode these? + string info; + strprintf(info, "ERROR bits %08x", error_flags_); + return info; +} diff --git a/src/meters.h b/src/meters.h index 85347a2..11f197a 100644 --- a/src/meters.h +++ b/src/meters.h @@ -41,6 +41,7 @@ X(em24, C1_bit, ElectricityMeter, EM24, EM24) \ X(emerlin868, T1_bit, WaterMeter, EMERLIN868, EMerlin868) \ X(ev200, T1_bit, WaterMeter, EV200, EV200) \ + X(evo868, T1_bit, WaterMeter, EVO868, EVO868) \ X(fhkvdataiii,T1_bit, HeatCostAllocationMeter, FHKVDATAIII, FHKVDataIII) \ X(fhkvdataiv, T1_bit, HeatCostAllocationMeter, FHKVDATAIV, FHKVDataIV) \ X(hydrus, T1_bit, WaterMeter, HYDRUS, Hydrus) \ @@ -111,6 +112,7 @@ X(EM24, MANUFACTURER_KAM, 0x02, 0x33) \ X(EMERLIN868,MANUFACTURER_ELR, 0x37, 0x11) \ X(EV200, MANUFACTURER_ELR, 0x07, 0x0d) \ + X(EVO868, MANUFACTURER_MAD, 0x07, 0x50) \ X(FHKVDATAIII,MANUFACTURER_TCH, 0x80, 0x69) \ X(FHKVDATAIII,MANUFACTURER_TCH, 0x80, 0x94) \ X(FHKVDATAIV,MANUFACTURER_TCH, 0x08, 0x69) \ diff --git a/src/testinternals.cc b/src/testinternals.cc index 4a545db..354abae 100644 --- a/src/testinternals.cc +++ b/src/testinternals.cc @@ -37,6 +37,7 @@ void test_ids(); void test_kdf(); void test_periods(); void test_devices(); +void test_months(); int main(int argc, char **argv) { @@ -62,6 +63,7 @@ int main(int argc, char **argv) test_ids(); test_kdf(); test_periods(); + test_months(); return 0; } @@ -644,3 +646,26 @@ void test_devices() } + +void test_months() +{ + struct tm date; + date.tm_year = 2020-1900; + date.tm_mon = 12-1; + date.tm_mday = 31; + + string s = strdate(&date); + + struct tm d; + d = date; + addMonths(&d, -10); + + string os = strdate(&d); + + if (s != "2020-12-31" || + os != "2020-02-29") + { + printf("ERROR! Expected 2020-12-31 - 10 months should be 2020-02-29\n" + "But got %s - 11 = %s\n", s.c_str(), os.c_str()); + } +} diff --git a/src/util.cc b/src/util.cc index 9d472b8..cb08392 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1180,6 +1180,61 @@ string strdatetimesec(struct tm *datetime) return string(buf); } +bool is_leap_year(int year) +{ + if (year % 4 != 0) return false; + if (year % 400 == 0) return true; + if (year % 100 == 0) return false; + return true; +} + +int days_in_months[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +int get_days_in_month(int year, int month) +{ + assert(month >= 0); + assert(month < 12); + + int days = days_in_months[month]; + + if (month == 1 && is_leap_year(year)) + { + // Handle february in a leap year. + days += 1; + } + + return days; +} + +void addMonths(struct tm *date, int months) +{ + bool is_last_day_in_month = date->tm_mday == get_days_in_month(date->tm_year, date->tm_mon); + + int year = date->tm_year + months / 12; + int month = date->tm_mon + months % 12; + + if (month > 11) + { + year += 1; + month -= 12; + } + + int day; + + if (is_last_day_in_month) + { + day = get_days_in_month(year, month); // Last day of month maps to last day of result month + } + else + { + day = std::min(date->tm_mday, get_days_in_month(year, month)); + } + + date->tm_year = year; + date->tm_mon = month; + date->tm_mday = day; +} + AccessCheck checkIfExistsAndSameGroup(string device) { struct stat sb; diff --git a/src/util.h b/src/util.h index e81eded..21d57c7 100644 --- a/src/util.h +++ b/src/util.h @@ -55,6 +55,7 @@ std::string strdate(struct tm *date); std::string strdatetime(struct tm *date); // Return for example: 2010-03-21 15:22:03 std::string strdatetimesec(struct tm *date); +void addMonths(struct tm* date, int m); bool stringFoundCaseIgnored(std::string haystack, std::string needle); diff --git a/tests/test_listen_to_all.sh b/tests/test_listen_to_all.sh index 0f6e190..7ad1b6e 100755 --- a/tests/test_listen_to_all.sh +++ b/tests/test_listen_to_all.sh @@ -220,6 +220,11 @@ Received telegram from: 62626262 type: Heat meter (0x43) ver: 0x45 driver: compact5 +Received telegram from: 79787776 + manufacturer: (MAD) Maddalena, Italy (0x3424) + type: Water meter (0x07) + ver: 0x50 + driver: evo868 EOF RES=$($PROG --logfile=$LOGFILE --t1 simulations/simulation_t1.txt 2>&1) diff --git a/tests/test_t1_meters.sh b/tests/test_t1_meters.sh index c700b72..4e490a5 100755 --- a/tests/test_t1_meters.sh +++ b/tests/test_t1_meters.sh @@ -20,6 +20,7 @@ METERS="MyWarmWater supercom587 12345678 NOKEY Room fhkvdataiii 11776622 NOKEY Rooom fhkvdataiv 14542076 FCF41938F63432975B52505F547FCEDF HeatMeter eurisii 88018801 NOKEY + Votchka evo868 79787776 NOKEY Smokeo lansensm 00010204 NOKEY Tempoo lansenth 00010203 NOKEY Dooro lansendw 00010205 NOKEY