From b999952fb50471405b9f37c4b0502f46ca204526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Fri, 11 Nov 2022 20:20:06 +0100 Subject: [PATCH] Refactor vario451 to new driver format. --- src/driver_vario451.cc | 113 +++++++++++++++++++++++++++++++++++ src/meter_detection.h | 2 - src/meter_vario451.cc | 130 ----------------------------------------- src/meters.h | 1 - 4 files changed, 113 insertions(+), 133 deletions(-) create mode 100644 src/driver_vario451.cc delete mode 100644 src/meter_vario451.cc diff --git a/src/driver_vario451.cc b/src/driver_vario451.cc new file mode 100644 index 0000000..a1ad949 --- /dev/null +++ b/src/driver_vario451.cc @@ -0,0 +1,113 @@ +/* + Copyright (C) 2019-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 + 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"meters_common_implementation.h" + +namespace +{ + struct Driver : public virtual MeterCommonImplementation + { + Driver(MeterInfo &mi, DriverInfo &di); + + void processContent(Telegram *t); + + double total_energy_gj_ {}; + double curr_energy_gj_ {}; + double prev_energy_gj_ {}; + }; + + static bool ok = registerDriver([](DriverInfo&di) + { + di.setName("vario451"); + di.setMeterType(MeterType::WaterMeter); + di.addLinkMode(LinkMode::C1); + di.addLinkMode(LinkMode::T1); + di.addDetection(MANUFACTURER_TCH, 0x04, 0x27); + di.addDetection(MANUFACTURER_TCH, 0xc3, 0x27); + di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr(new Driver(mi, di)); }); + }); + + Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di) + { + addNumericField("total", + Quantity::Energy, + PrintProperty::FIELD | PrintProperty::JSON, + "The total energy consumption recorded by this meter.", + SET_FUNC(total_energy_gj_, Unit::GJ), + GET_FUNC(total_energy_gj_, Unit::GJ)); + + addNumericField("current", + Quantity::Energy, + PrintProperty::FIELD | PrintProperty::JSON, + "Energy consumption so far in this billing period.", + SET_FUNC(curr_energy_gj_, Unit::GJ), + GET_FUNC(curr_energy_gj_, Unit::GJ)); + + addNumericField("previous", + Quantity::Energy, + PrintProperty::FIELD | PrintProperty::JSON, + "Energy consumption in previous billing period.", + SET_FUNC(prev_energy_gj_, Unit::GJ), + GET_FUNC(prev_energy_gj_, Unit::GJ)); + + } + + void Driver::processContent(Telegram *t) + { + // Unfortunately, the Techem Vario 4 Typ 4.5.1 is mostly a proprieatary protocol + // simple wrapped inside a wmbus telegram since the ci-field is 0xa2. + // Which means that the entire payload is manufacturer specific. + + map> vendor_values; + vector content; + + t->extractPayload(&content); + if (content.size() < 9) return; + + uchar prev_lo = content[3]; + uchar prev_hi = content[4]; + double prev = (256.0*prev_hi+prev_lo)/1000; + + string prevs; + strprintf(&prevs, "%02x%02x", prev_lo, prev_hi); + int offset = t->parsed.size()+3; + vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, 0, 0, 0, prevs) }; + t->explanations.push_back(Explanation(offset, 2, prevs, KindOfData::CONTENT, Understanding::FULL)); + t->addMoreExplanation(offset, " energy used in previous billing period (%f GJ)", prev); + + uchar curr_lo = content[7]; + uchar curr_hi = content[8]; + double curr = (256.0*curr_hi+curr_lo)/1000; + + string currs; + strprintf(&currs, "%02x%02x", curr_lo, curr_hi); + offset = t->parsed.size()+7; + vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, 0, 0, 0, currs) }; + t->explanations.push_back(Explanation(offset, 2, currs, KindOfData::CONTENT, Understanding::FULL)); + t->addMoreExplanation(offset, " energy used in current billing period (%f GJ)", curr); + + total_energy_gj_ = prev+curr; + curr_energy_gj_ = curr; + prev_energy_gj_ = prev; + } + +} + +// Test: HeatMeter vario451 58234965 NOKEY +// telegram=|374468506549235827C3A2_129F25383300A8622600008200800A2AF862115175552877A36F26C9AB1CB24400000004000000000004908002| +// {"media":"heat","meter":"vario451","name":"HeatMeter","id":"58234965","total_kwh":6371.666667,"current_kwh":2729.444444,"previous_kwh":3642.222222,"timestamp":"1111-11-11T11:11:11Z"} +// |HeatMeter;58234965;6371.666667;2729.444444;3642.222222;1111-11-11 11:11.11 diff --git a/src/meter_detection.h b/src/meter_detection.h index 082cc8f..214cda2 100644 --- a/src/meter_detection.h +++ b/src/meter_detection.h @@ -76,8 +76,6 @@ X(TOPASESKR, MANUFACTURER_AMT, 0x06, 0xf1) \ X(TOPASESKR, MANUFACTURER_AMT, 0x07, 0xf1) \ X(UNISMART, MANUFACTURER_AMX, 0x03, 0x01) \ - X(VARIO451, MANUFACTURER_TCH, 0x04, 0x27) \ - X(VARIO451, MANUFACTURER_TCH, 0xc3, 0x27) \ diff --git a/src/meter_vario451.cc b/src/meter_vario451.cc deleted file mode 100644 index aa5d2af..0000000 --- a/src/meter_vario451.cc +++ /dev/null @@ -1,130 +0,0 @@ -/* - Copyright (C) 2019-2020 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 - 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"units.h" -#include"util.h" - -struct MeterVario451 : public virtual MeterCommonImplementation -{ - MeterVario451(MeterInfo &mi); - - double totalEnergyConsumption(Unit u); - double currentPeriodEnergyConsumption(Unit u); - double previousPeriodEnergyConsumption(Unit u); - - private: - - void processContent(Telegram *t); - - double total_energy_gj_ {}; - double curr_energy_gj_ {}; - double prev_energy_gj_ {}; -}; - -shared_ptr createVario451(MeterInfo &mi) -{ - return shared_ptr(new MeterVario451(mi)); -} - -MeterVario451::MeterVario451(MeterInfo &mi) : - MeterCommonImplementation(mi, "vario451") -{ - setMeterType(MeterType::HeatMeter); - - // media 0x04 C telegrams - // media 0xC3 T telegrams - - addLinkMode(LinkMode::C1); - addLinkMode(LinkMode::T1); - - addPrint("total", Quantity::Energy, - [&](Unit u){ return totalEnergyConsumption(u); }, - "The total energy consumption recorded by this meter.", - PrintProperty::FIELD | PrintProperty::JSON); - - addPrint("current", Quantity::Energy, - [&](Unit u){ return currentPeriodEnergyConsumption(u); }, - "Energy consumption so far in this billing period.", - PrintProperty::FIELD | PrintProperty::JSON); - - addPrint("previous", Quantity::Energy, - [&](Unit u){ return previousPeriodEnergyConsumption(u); }, - "Energy consumption in previous billing period.", - PrintProperty::FIELD | PrintProperty::JSON); -} - -double MeterVario451::totalEnergyConsumption(Unit u) -{ - assertQuantity(u, Quantity::Energy); - return convert(total_energy_gj_, Unit::GJ, u); -} - -double MeterVario451::currentPeriodEnergyConsumption(Unit u) -{ - assertQuantity(u, Quantity::Energy); - return convert(curr_energy_gj_, Unit::GJ, u); -} - -double MeterVario451::previousPeriodEnergyConsumption(Unit u) -{ - assertQuantity(u, Quantity::Energy); - return convert(prev_energy_gj_, Unit::GJ, u); -} - -void MeterVario451::processContent(Telegram *t) -{ - // Unfortunately, the Techem Vario 4 Typ 4.5.1 is mostly a proprieatary protocol - // simple wrapped inside a wmbus telegram since the ci-field is 0xa2. - // Which means that the entire payload is manufacturer specific. - - map> vendor_values; - vector content; - - t->extractPayload(&content); - if (content.size() < 9) return; - - uchar prev_lo = content[3]; - uchar prev_hi = content[4]; - double prev = (256.0*prev_hi+prev_lo)/1000; - - string prevs; - strprintf(&prevs, "%02x%02x", prev_lo, prev_hi); - int offset = t->parsed.size()+3; - vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, 0, 0, 0, prevs) }; - t->explanations.push_back(Explanation(offset, 2, prevs, KindOfData::CONTENT, Understanding::FULL)); - t->addMoreExplanation(offset, " energy used in previous billing period (%f GJ)", prev); - - uchar curr_lo = content[7]; - uchar curr_hi = content[8]; - double curr = (256.0*curr_hi+curr_lo)/1000; - - string currs; - strprintf(&currs, "%02x%02x", curr_lo, curr_hi); - offset = t->parsed.size()+7; - vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, 0, 0, 0, currs) }; - t->explanations.push_back(Explanation(offset, 2, currs, KindOfData::CONTENT, Understanding::FULL)); - t->addMoreExplanation(offset, " energy used in current billing period (%f GJ)", curr); - - total_energy_gj_ = prev+curr; - curr_energy_gj_ = curr; - prev_energy_gj_ = prev; -} diff --git a/src/meters.h b/src/meters.h index 5993a6d..ca57221 100644 --- a/src/meters.h +++ b/src/meters.h @@ -82,7 +82,6 @@ LIST_OF_METER_TYPES X(tsd2, T1_bit, SmokeDetector, TSD2, TSD2) \ X(sontex868, T1_bit, HeatCostAllocationMeter, SONTEX868, Sontex868) \ X(topaseskr, T1_bit, WaterMeter, TOPASESKR, TopasEsKr) \ - X(vario451, T1_bit, HeatMeter, VARIO451, Vario451) \ X(lse_08, S1_bit|C1_bit, HeatCostAllocationMeter, LSE_08, LSE_08) \ X(unismart, T1_bit, GasMeter, UNISMART, Unismart) \