From bda349bcd2699da2dffbe25daa297374bd0bd7a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Sun, 11 Dec 2022 15:20:23 +0100 Subject: [PATCH] Clean up tpl status reporting. --- simulations/simulation_s1.txt | 2 +- simulations/simulation_t1.txt | 2 +- src/driver_ei6500.cc | 18 +++------- src/driver_elf.cc | 13 ------- src/driver_hydrocalm3.cc | 8 ++++- src/driver_lansenpu.cc | 18 +++------- src/driver_lansenth.cc | 18 +++------- src/driver_lse_08.cc | 2 +- src/meters.cc | 2 +- src/meters.h | 2 +- src/meters_common_implementation.h | 2 +- src/translatebits.cc | 18 +++++++++- src/translatebits.h | 4 ++- src/wmbus.cc | 57 +++--------------------------- src/wmbus.h | 4 --- tests/test_drivers.sh | 11 +++++- 16 files changed, 62 insertions(+), 119 deletions(-) diff --git a/simulations/simulation_s1.txt b/simulations/simulation_s1.txt index 25b12ed..e245794 100644 --- a/simulations/simulation_s1.txt +++ b/simulations/simulation_s1.txt @@ -8,7 +8,7 @@ telegram=|244465323251839134087a4f0000000b6e0403004b6e660300426c9e29326cffff046d # Test another HCA from Qundis telegram=|294465324185990401087a0080000082046c7f018b046e210300046d1a0e6f0202fdac7e012301fd0c01| -{"media":"heat cost allocation","meter":"lse_08","name":"HCA2","id":"04998541","status":"TPL_MFCT_80","set_date":"2003-01-31","consumption_at_set_date_hca":321,"device_date_time":"2003-02-15 14:26","duration_since_readout_h":2.489167,"model_version":"01","timestamp":"1111-11-11T11:11:11Z"} +{"media":"heat cost allocation","meter":"lse_08","name":"HCA2","id":"04998541","status":"UNKNOWN_80","set_date":"2003-01-31","consumption_at_set_date_hca":321,"device_date_time":"2003-02-15 14:26","duration_since_readout_h":2.489167,"model_version":"01","timestamp":"1111-11-11T11:11:11Z"} |HCA2;04998541;2003-01-31;321;1111-11-11 11:11.11 # Test Qundis QWater5.5 S1 meter. diff --git a/simulations/simulation_t1.txt b/simulations/simulation_t1.txt index 76dafed..cc22f29 100644 --- a/simulations/simulation_t1.txt +++ b/simulations/simulation_t1.txt @@ -295,7 +295,7 @@ telegram=|6044B8059430040001037A1D005085E2B670BCF1A5C87E0C1A51DA18924EF984613DA2 # Test Hydrocal M3 heat/cooling meter telegram=|8E44B409747372710B0D7A798080052F2F_0C0E59600100046D1D36B9290C13679947000C0E000000000C13590000000C13000000000C13000000000A5A18020A5E11020F823D06003D06003D06003D0600140600620500480400E402001601000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002F2F| -{"media":"heat/cooling load","meter":"hydrocalm3","name":"HeatCool","id":"71727374","status": "TPL_MFCT_80","total_heating_kwh":4460.833333,"total_cooling_kwh":0,"device_datetime":"2021-09-25 22:29","total_heating_m3":479.967,"total_cooling_m3":0.059,"c1_volume_m3":0,"c2_volume_m3":0,"supply_temperature_c":21.8,"return_temperature_c":21.1,"timestamp":"1111-11-11T11:11:11Z"} +{"media":"heat/cooling load","meter":"hydrocalm3","name":"HeatCool","id":"71727374","status": "SABOTAGE_ENCLOSURE","total_heating_kwh":4460.833333,"total_cooling_kwh":0,"device_datetime":"2021-09-25 22:29","total_heating_m3":479.967,"total_cooling_m3":0.059,"c1_volume_m3":0,"c2_volume_m3":0,"supply_temperature_c":21.8,"return_temperature_c":21.1,"timestamp":"1111-11-11T11:11:11Z"} |HeatCool;71727374;4460.833333;2021-09-25 22:29;1111-11-11 11:11.11 # Test Weptech Munia temperature hygrometer diff --git a/src/driver_ei6500.cc b/src/driver_ei6500.cc index 30bdeb8..671ffb9 100644 --- a/src/driver_ei6500.cc +++ b/src/driver_ei6500.cc @@ -31,19 +31,11 @@ namespace di.addLinkMode(LinkMode::T1); di.addDetection(MANUFACTURER_EIE, 0x1a, 0x0c); di.addMfctTPLStatusBits( - { - { - { - "TPL_STS", - Translate::Type::BitToString, - AlwaysTrigger, MaskBits(0xe0), // Always use 0xe0 for tpl mfct status bits. - "OK", - { - { 0x40, "RTC_INVALID" } - } - }, - }, - }); + Translate::Lookup() + .add(Translate::Rule("TPL_STS", Translate::Type::BitToString) + .set(MaskBits(0xe0)) + .set(DefaultMessage("OK")) + .add(Translate::Map(0x04 ,"RTC_INVALID", TestBit::Set)))); di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr(new Driver(mi, di)); }); }); diff --git a/src/driver_elf.cc b/src/driver_elf.cc index 411ef5b..913d9b1 100644 --- a/src/driver_elf.cc +++ b/src/driver_elf.cc @@ -30,19 +30,6 @@ namespace di.setDefaultFields("name,id,total_energy_consumption_kwh,current_power_consumption_kw,total_volume_m3,flow_temperature_c,return_temperature_c,external_temperature_c,status,timestamp"); di.setMeterType(MeterType::HeatMeter); di.addDetection(MANUFACTURER_APA, 0x04, 0x40); - di.addMfctTPLStatusBits( - { - { - { - "TPL_STS", - Translate::Type::BitToString, - AlwaysTrigger, MaskBits(0xe0), // Always use 0xe0 for tpl mfct status bits. - "OK", - { - } - }, - }, - }); di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr(new Driver(mi, di)); }); }); diff --git a/src/driver_hydrocalm3.cc b/src/driver_hydrocalm3.cc index 8e4d352..9626dec 100644 --- a/src/driver_hydrocalm3.cc +++ b/src/driver_hydrocalm3.cc @@ -31,6 +31,12 @@ namespace di.setMeterType(MeterType::HeatMeter); di.addLinkMode(LinkMode::T1); di.addDetection(MANUFACTURER_BMT, 0x0d, 0x0b); + di.addMfctTPLStatusBits( + Translate::Lookup() + .add(Translate::Rule("TPL_STS", Translate::Type::BitToString) + .set(MaskBits(0xe0)) + .set(DefaultMessage("OK")) + .add(Translate::Map(0x80 ,"SABOTAGE_ENCLOSURE", TestBit::Set)))); di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr(new Driver(mi, di)); }); }); @@ -153,5 +159,5 @@ namespace // Test:HeatCool hydrocalm3 71727374 NOKEY // telegram=|8E44B409747372710B0D7A798080052F2F_0C0E59600100046D1D36B9290C13679947000C0E000000000C13590000000C13000000000C13000000000A5A18020A5E11020F823D06003D06003D06003D0600140600620500480400E402001601000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002F2F| -// {"media":"heat/cooling load","meter":"hydrocalm3","name":"HeatCool","id":"71727374","status": "TPL_MFCT_80","total_heating_kwh":4460.833333,"total_cooling_kwh":0,"device_datetime":"2021-09-25 22:29","total_heating_m3":479.967,"total_cooling_m3":0.059,"c1_volume_m3":0,"c2_volume_m3":0,"supply_temperature_c":21.8,"return_temperature_c":21.1,"timestamp":"1111-11-11T11:11:11Z"} +// {"media":"heat/cooling load","meter":"hydrocalm3","name":"HeatCool","id":"71727374","status": "SABOTAGE_ENCLOSURE","total_heating_kwh":4460.833333,"total_cooling_kwh":0,"device_datetime":"2021-09-25 22:29","total_heating_m3":479.967,"total_cooling_m3":0.059,"c1_volume_m3":0,"c2_volume_m3":0,"supply_temperature_c":21.8,"return_temperature_c":21.1,"timestamp":"1111-11-11T11:11:11Z"} // |HeatCool;71727374;4460.833333;2021-09-25 22:29;1111-11-11 11:11.11 diff --git a/src/driver_lansenpu.cc b/src/driver_lansenpu.cc index 7ea5890..29f140c 100644 --- a/src/driver_lansenpu.cc +++ b/src/driver_lansenpu.cc @@ -33,19 +33,11 @@ namespace di.addDetection(MANUFACTURER_LAS, 0x00, 0x1b); di.addDetection(MANUFACTURER_LAS, 0x02, 0x0b); di.addMfctTPLStatusBits( - { - { - { - "TPL_STS", - Translate::Type::BitToString, - AlwaysTrigger, MaskBits(0xe0), // Always use 0xe0 for tpl mfct status bits. - "OK", - { - { 0x40, "SABOTAGE_ENCLOSURE" } - } - }, - }, - }); + Translate::Lookup() + .add(Translate::Rule("TPL_STS", Translate::Type::BitToString) + .set(MaskBits(0xe0)) + .set(DefaultMessage("OK")) + .add(Translate::Map(0x40 ,"SABOTAGE_ENCLOSURE", TestBit::Set)))); di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr(new Driver(mi, di)); }); }); diff --git a/src/driver_lansenth.cc b/src/driver_lansenth.cc index 36866b1..46e49b5 100644 --- a/src/driver_lansenth.cc +++ b/src/driver_lansenth.cc @@ -31,19 +31,11 @@ namespace di.setMeterType(MeterType::TempHygroMeter); di.addDetection(MANUFACTURER_LAS, 0x1b, 0x07); di.addMfctTPLStatusBits( - { - { - { - "TPL_STS", - Translate::Type::BitToString, - AlwaysTrigger, MaskBits(0xe0), // Always use 0xe0 for tpl mfct status bits. - "OK", - { - { 0x40, "SABOTAGE_ENCLOSURE" } - } - }, - }, - }); + Translate::Lookup() + .add(Translate::Rule("TPL_STS", Translate::Type::BitToString) + .set(MaskBits(0xe0)) + .set(DefaultMessage("OK")) + .add(Translate::Map(0x40 ,"SABOTAGE_ENCLOSURE", TestBit::Set)))); di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr(new Driver(mi, di)); }); }); diff --git a/src/driver_lse_08.cc b/src/driver_lse_08.cc index c0293b5..5d28d85 100644 --- a/src/driver_lse_08.cc +++ b/src/driver_lse_08.cc @@ -128,5 +128,5 @@ namespace // Test: HCA2 lse_08 04998541 NOKEY // telegram=|294465324185990401087a0080000082046c7f018b046e210300046d1a0e6f0202fdac7e012301fd0c01| -// {"media":"heat cost allocation","meter":"lse_08","name":"HCA2","id":"04998541","status":"TPL_MFCT_80","set_date":"2003-01-31","consumption_at_set_date_hca":321,"device_date_time":"2003-02-15 14:26","duration_since_readout_h":2.489167,"model_version":"01","timestamp":"1111-11-11T11:11:11Z"} +// {"media":"heat cost allocation","meter":"lse_08","name":"HCA2","id":"04998541","status":"UNKNOWN_80","set_date":"2003-01-31","consumption_at_set_date_hca":321,"device_date_time":"2003-02-15 14:26","duration_since_readout_h":2.489167,"model_version":"01","timestamp":"1111-11-11T11:11:11Z"} // |HCA2;04998541;2003-01-31;321;1111-11-11 11:11.11 diff --git a/src/meters.cc b/src/meters.cc index 9d787e6..16f9550 100644 --- a/src/meters.cc +++ b/src/meters.cc @@ -286,7 +286,7 @@ void MeterCommonImplementation::addLinkMode(LinkMode lm) link_modes_.addLinkMode(lm); } -void MeterCommonImplementation::addMfctTPLStatusBits(Translate::Lookup lookup) +void MeterCommonImplementation::addMfctTPLStatusBits(Translate::Lookup &lookup) { mfct_tpl_status_bits_ = lookup; } diff --git a/src/meters.h b/src/meters.h index 2ddbf6e..f9763c4 100644 --- a/src/meters.h +++ b/src/meters.h @@ -191,7 +191,7 @@ public: void setDefaultFields(string f) { default_fields_ = splitString(f, ','); } void addLinkMode(LinkMode lm) { linkmodes_.addLinkMode(lm); } void forceMfctIndex(int i) { force_mfct_index_ = i; } - void addMfctTPLStatusBits(Translate::Lookup lookup) { mfct_tpl_status_bits_ = lookup; } + void addMfctTPLStatusBits(Translate::Lookup &lookup) { mfct_tpl_status_bits_ = lookup; } void setConstructor(function(MeterInfo&,DriverInfo&)> c) { constructor_ = c; } void addDetection(uint16_t mfct, uchar type, uchar ver) { detect_.push_back({ mfct, type, ver }); } vector &detect() { return detect_; } diff --git a/src/meters_common_implementation.h b/src/meters_common_implementation.h index 69cd6dc..0005932 100644 --- a/src/meters_common_implementation.h +++ b/src/meters_common_implementation.h @@ -98,7 +98,7 @@ protected: std::vector &meterExtraConstantFields(); void setMeterType(MeterType mt); void addLinkMode(LinkMode lm); - void addMfctTPLStatusBits(Translate::Lookup lookup); + void addMfctTPLStatusBits(Translate::Lookup &lookup); // Print with the default unit for this quantity. void addPrint(string vname, Quantity vquantity, diff --git a/src/translatebits.cc b/src/translatebits.cc index c04df1a..8a7ec9f 100644 --- a/src/translatebits.cc +++ b/src/translatebits.cc @@ -55,7 +55,7 @@ void handleBitToString(Rule& rule, string &out_s, uint64_t bits) { // Check that the match rule does not extend outside of the mask! // If mask is 0xff then a match for 0x100 will trigger this bad warning! - string tmp = tostrprintf("BAD_RULE_%s(from=0x%x mask=0x%x)", rule.name.c_str(), m.from, rule.mask); + string tmp = tostrprintf("BAD_RULE_%s(from=0x%x mask=0x%x)", rule.name.c_str(), m.from, mask); s += tmp+" "; } @@ -243,6 +243,22 @@ string Lookup::translate(uint64_t bits) return sortStatusString(total); } +string Lookup::str() +{ + string x = " Lookup {\n"; + + for (Rule& r : rules) + { + x += " Rulex {\n"; + x += " name = "+r.name+"\n"; + x += " }\n"; + } + + x += "}\n"; + + return x; +} + Lookup NoLookup = {}; diff --git a/src/translatebits.h b/src/translatebits.h index acd6a96..fac0e2b 100644 --- a/src/translatebits.h +++ b/src/translatebits.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2021 Fredrik Öhrström (gpl-3.0-or-later) + Copyright (C) 2021-2022 Fredrik Öhrström (gpl-3.0-or-later) 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 @@ -111,6 +111,8 @@ namespace Translate bool hasLookups() { return rules.size() > 0; } Lookup &add(Rule r) { rules.push_back(r); return *this; } + + std::string str(); }; }; diff --git a/src/wmbus.cc b/src/wmbus.cc index 4d69b78..b890f46 100644 --- a/src/wmbus.cc +++ b/src/wmbus.cc @@ -1439,9 +1439,9 @@ bool Telegram::parseShortTPL(std::vector::iterator &pos) CHECK(1); tpl_sts = *pos; + tpl_sts_offset = distance(frame.begin(), pos); addExplanationAndIncrementPos(pos, 1, KindOfData::PROTOCOL, Understanding::FULL, - "%02x tpl-sts-field (%s)", tpl_sts, decodeTPLStatusByteWithLookup(tpl_sts, NULL).c_str()); - + "%02x tpl-sts-field (%s)", tpl_sts, decodeTPLStatusByteOnlyStandardBits(tpl_sts).c_str()); bool ok = parseTPLConfig(pos); if (!ok) return false; @@ -3962,21 +3962,6 @@ uint64_t dataAsUint64(int dif, int vif, int vife, string data) return -1; } -string formatData(int dif, int vif, int vife, string data) -{ - string r; - - int t = vif & 0x7f; - if (t >= 0 && t <= 0x77 && !(t >= 0x6c && t<=0x6f)) { - // These are vif codes with an understandable key and unit. - double val = dataAsDouble(dif, vif, vife, data); - strprintf(&r, "%d", val); - return r; - } - - return data; -} - string linkModeName(LinkMode link_mode) { @@ -4980,39 +4965,8 @@ string decodeTPLStatusByteOnlyStandardBits(uchar sts) return s; } -string decodeTPLStatusByteWithLookup(uchar sts, map *vendor_lookup) -{ - string s = decodeTPLStatusByteOnlyStandardBits(sts); - string t = "OK"; - - if ((sts & 0xe0) != 0) - { - t = ""; - // Vendor specific bits are set, lets translate them. - int v = sts & 0xf8; // Zero the 3 lowest bits. Including the temp and permanent bits is wrong here. - // But that is how it is implemented right now. This code is about to go away. - if (vendor_lookup != NULL && vendor_lookup->count(v) != 0) - { - t += (*vendor_lookup)[v]; - t += " "; - } - else - { - // We could not translate, just print the bits. - t += tostrprintf("TPL_MFCT_%02X ", sts & 0xe0); - } - while (t.size() > 0 && t.back() == ' ') t.pop_back(); - } - - if (t == "OK" || t == "") return s; - if (s == "OK" || s == "") return t; - - return s+" "+t; -} - string decodeTPLStatusByteNoMfct(uchar sts) { - string s = decodeTPLStatusByteOnlyStandardBits(sts); string t = "OK"; if ((sts & 0xe0) != 0) @@ -5020,10 +4974,7 @@ string decodeTPLStatusByteNoMfct(uchar sts) t = tostrprintf("UNKNOWN_%02X", sts & 0xe0); } - if (t == "OK" || t == "") return s; - if (s == "OK" || s == "") return t; - - return s+" "+t; + return t; } string decodeTPLStatusByteWithMfct(uchar sts, Translate::Lookup &lookup) @@ -5040,7 +4991,7 @@ string decodeTPLStatusByteWithMfct(uchar sts, Translate::Lookup &lookup) } else { - t = decodeTPLStatusByteWithLookup(sts & 0xe0, NULL); + t = decodeTPLStatusByteNoMfct(sts & 0xe0); } } diff --git a/src/wmbus.h b/src/wmbus.h index 94e34df..c22f5f8 100644 --- a/src/wmbus.h +++ b/src/wmbus.h @@ -755,7 +755,6 @@ string vifKey(int vif); // E.g. temperature energy power mass_flow volume_flow string vifUnit(int vif); // E.g. m3 c kwh kw MJ MJh string vifType(int vif); // Long description string vifeType(int dif, int vif, int vife); // Long description -string formatData(int dif, int vif, int vife, string data); // Decode only the standard defined bits in the tpl status byte. Ignore the top 3 bits. // Return "OK" if sts == 0 @@ -766,9 +765,6 @@ string decodeTPLStatusByteNoMfct(uchar sts); // Decode the standard bits and translate the top 3 bits if set. // Return "OK" if sts == 0 string decodeTPLStatusByteWithMfct(uchar sts, Translate::Lookup &lookup); -// Old style lookup to go away. -// Return "OK" if sts == 0 -string decodeTPLStatusByteWithLookup(uchar sts, map *vendor_lookup); int difLenBytes(int dif); MeasurementType difMeasurementType(int dif); diff --git a/tests/test_drivers.sh b/tests/test_drivers.sh index 011ae1c..3845f37 100755 --- a/tests/test_drivers.sh +++ b/tests/test_drivers.sh @@ -10,6 +10,7 @@ echo "Testing drivers" TESTNAME="Test driver tests" TESTRESULT="ERROR" +FAILED=false ALL_DRIVERS=$(cd src; echo driver_*cc) @@ -46,11 +47,15 @@ do then meld $TEST/test_expected_json.txt $TEST/test_response_json.txt fi + echo "Failure: $TESTNAME" + FAILED=true fi else echo "wmbusmeters returned error code: $?" cat $TEST/test_output_json.txt cat $TEST/test_stderr_json.txt + echo "Failure: $TESTNAME" + FAILED=true fi cat $TEST/simulation.txt | grep '^|' | sed 's/^|//' > $TEST/test_expected_fields.txt @@ -69,14 +74,18 @@ do then meld $TEST/test_expected_fields.txt $TEST/test_response_fields.txt fi + echo "Failure: $TESTNAME" + FAILED=true fi else echo "wmbusmeters returned error code: $?" cat $TEST/test_output_fields.txt cat $TEST/test_stderr_fields.txt + echo "Failure: $TESTNAME" + FAILED=true fi - if [ "$TESTRESULT" = "ERROR" ] + if [ "$TESTRESULT" = "ERROR" ] || "$FAILED" = "true" then echo ERROR: $TESTNAME exit 1