From 8fd98c2562e12671ee35a8f9e07cae9e53e6f93a Mon Sep 17 00:00:00 2001 From: Andreas Horrer Date: Sat, 11 Nov 2023 13:20:20 +0100 Subject: [PATCH 01/10] Added new driver for itron heatmeter ultramaxx --- src/driver_itronheat.cc | 94 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/driver_itronheat.cc diff --git a/src/driver_itronheat.cc b/src/driver_itronheat.cc new file mode 100644 index 0000000..ea15691 --- /dev/null +++ b/src/driver_itronheat.cc @@ -0,0 +1,94 @@ +/* + Copyright (C) 2022 Fredrik Öhrström (gpl-3.0-or-later) + 2023 Andreas Horrer (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); + }; + + static bool ok = registerDriver([](DriverInfo&di) + { + di.setName("itronheat"); + di.addNameAlias("ultramaxx"); + di.setDefaultFields("name,id,status,total_energy_consumption_kwh,total_volume_m3,timestamp"); + di.setMeterType(MeterType::HeatMeter); + di.addLinkMode(LinkMode::C1); + di.addDetection(MANUFACTURER_ITW, 0x04, 0x00); + di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr(new Driver(mi, di)); }); + }); + + Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di) + { + addOptionalCommonFields("meter_datetime"); + + addStringFieldWithExtractorAndLookup( + "status", + "Meter status from error flags and tpl status field.", + DEFAULT_PRINT_PROPERTIES | + PrintProperty::STATUS | PrintProperty::INCLUDE_TPL_STATUS, + FieldMatcher::build() + .set(MeasurementType::Instantaneous) + .set(VIFRange::ErrorFlags), + Translate::Lookup( + { + { + { + "ERROR_FLAGS", + Translate::Type::BitToString, + AlwaysTrigger, MaskBits(0xffff), + "OK", + { + } + }, + }, + })); + + addNumericFieldWithExtractor( + "total_energy_consumption", + "The total heat energy consumption recorded by this meter.", + DEFAULT_PRINT_PROPERTIES, + Quantity::Energy, + VifScaling::Auto, + FieldMatcher::build() + .set(MeasurementType::Instantaneous) + .set(VIFRange::AnyEnergyVIF) + ); + + addNumericFieldWithExtractor( + "total_volume", + "The total heating media volume recorded by this meter.", + DEFAULT_PRINT_PROPERTIES, + Quantity::Volume, + VifScaling::Auto, + FieldMatcher::build() + .set(MeasurementType::Instantaneous) + .set(VIFRange::Volume) + ); + } +} + +// Test: Heat itronheat 23340485 NOKEY +// Comment: Allmess UltraMaXX with ITRON EquaScan hMIU RF Module +// telegram=|444497268504342300047AD00030A52F2F_04062C0100000C1429270000066D2D130AE12B007406FEFEFEFE426C1F010D7FEB0E00000006040C995500372F2F0C7951622223| +// {"id":"23340485","media":"heat","meter":"itronheat","meter_datetime":"2023-11-01 10:19:45","name":"Heat","status":"OK","timestamp":"1111-11-11T11:11:11Z","total_energy_consumption_kwh":300,"total_volume_m3":27.29} +// |Heat;23340485;OK;300;27.29;1111-11-11 11:11.11 + From 752fd2f1c622384be645f1884acecd28d249ec9d Mon Sep 17 00:00:00 2001 From: Andreas Horrer Date: Sat, 11 Nov 2023 13:26:25 +0100 Subject: [PATCH 02/10] replaced tab with space --- src/driver_itronheat.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver_itronheat.cc b/src/driver_itronheat.cc index ea15691..765c39e 100644 --- a/src/driver_itronheat.cc +++ b/src/driver_itronheat.cc @@ -28,7 +28,7 @@ namespace static bool ok = registerDriver([](DriverInfo&di) { di.setName("itronheat"); - di.addNameAlias("ultramaxx"); + di.addNameAlias("ultramaxx"); di.setDefaultFields("name,id,status,total_energy_consumption_kwh,total_volume_m3,timestamp"); di.setMeterType(MeterType::HeatMeter); di.addLinkMode(LinkMode::C1); From 29b04f3365aecbb0c24543b62c4b393df94f665d Mon Sep 17 00:00:00 2001 From: Andreas Horrer Date: Mon, 1 Jan 2024 19:47:22 +0100 Subject: [PATCH 03/10] added new field for last_year_date and last_year_energy_consumption --- src/driver_itronheat.cc | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/driver_itronheat.cc b/src/driver_itronheat.cc index 765c39e..4474f0d 100644 --- a/src/driver_itronheat.cc +++ b/src/driver_itronheat.cc @@ -83,12 +83,34 @@ namespace .set(MeasurementType::Instantaneous) .set(VIFRange::Volume) ); + + addStringFieldWithExtractor( + "last_year_date", + "Last day previous year when total energy consumption was recorded.", + DEFAULT_PRINT_PROPERTIES, + FieldMatcher::build() + .set(MeasurementType::Instantaneous) + .set(StorageNr(1)) + .set(VIFRange::Date) + ); + + addNumericFieldWithExtractor( + "last_year_energy_consumption", + "The total energy consumption recorded at the last day of the previous year.", + DEFAULT_PRINT_PROPERTIES, + Quantity::Energy, + VifScaling::Auto, + FieldMatcher::build() + .set(MeasurementType::Instantaneous) + .set(StorageNr(1)) + .set(VIFRange::AnyEnergyVIF) + ); } } // Test: Heat itronheat 23340485 NOKEY // Comment: Allmess UltraMaXX with ITRON EquaScan hMIU RF Module // telegram=|444497268504342300047AD00030A52F2F_04062C0100000C1429270000066D2D130AE12B007406FEFEFEFE426C1F010D7FEB0E00000006040C995500372F2F0C7951622223| -// {"id":"23340485","media":"heat","meter":"itronheat","meter_datetime":"2023-11-01 10:19:45","name":"Heat","status":"OK","timestamp":"1111-11-11T11:11:11Z","total_energy_consumption_kwh":300,"total_volume_m3":27.29} +// {"id":"23340485","media":"heat","meter":"itronheat","meter_datetime":"2023-11-01 10:19:45","name":"Heat","status":"OK","timestamp":"1111-11-11T11:11:11Z","total_energy_consumption_kwh":300,"total_volume_m3":27.29,"last_year_date":"2000-01-31"} // |Heat;23340485;OK;300;27.29;1111-11-11 11:11.11 From 97715d75015658e9276e6c2474201743d9afe767 Mon Sep 17 00:00:00 2001 From: Andreas Horrer Date: Fri, 12 Jan 2024 22:08:14 +0100 Subject: [PATCH 04/10] improved matching of mfct where first character is lower case --- src/meters.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/meters.cc b/src/meters.cc index 7044bb2..5d5dd4d 100644 --- a/src/meters.cc +++ b/src/meters.cc @@ -97,6 +97,8 @@ bool DriverInfo::detect(uint16_t mfct, uchar type, uchar version) { if (dd.mfct == 0 && dd.type == 0 && dd.version == 0) continue; // Ignore drivers with no detection. if (dd.mfct == mfct && dd.type == type && dd.version == version) return true; + //some meters send mfct where the first character ist lower case, therefor % ( 32 * 1024 ) to convert mfct to upper case + if (dd.mfct == mfct % ( 32 * 1024 ) && dd.type == type && dd.version == version) return true; } return false; } From 7d4eda96237e0cf8932e5c9fe029c8f7164c6f5d Mon Sep 17 00:00:00 2001 From: Andreas Horrer Date: Fri, 12 Jan 2024 22:09:10 +0100 Subject: [PATCH 05/10] Added test for heat-meter from itron where MFCT is iTW instead of ITW --- src/driver_itronheat.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/driver_itronheat.cc b/src/driver_itronheat.cc index 4474f0d..45d8940 100644 --- a/src/driver_itronheat.cc +++ b/src/driver_itronheat.cc @@ -114,3 +114,9 @@ namespace // {"id":"23340485","media":"heat","meter":"itronheat","meter_datetime":"2023-11-01 10:19:45","name":"Heat","status":"OK","timestamp":"1111-11-11T11:11:11Z","total_energy_consumption_kwh":300,"total_volume_m3":27.29,"last_year_date":"2000-01-31"} // |Heat;23340485;OK;300;27.29;1111-11-11 11:11.11 +// Test: Heat_lower_case itronheat 11755757 NOKEY +// Comment: Itron Heatmeter with strange MFCT iTW instead of ITW +// telegram=|_404497A65757751100047A040000A00406494C0000041348318000066D2B0ED7EE2A0044069A360000426CDF2C0D7FEB0700000006040C5C7E034E0C7942502321| +// {"id":"11755757","media":"heat","meter":"itronheat","meter_datetime":"2023-10-14 23:14:43","name":"Heat_lower_case","status":"OK","timestamp":"1111-11-11T11:11:11Z","total_energy_consumption_kwh":19529,"total_volume_m3":8401.224,"last_year_date":"2022-12-31","last_year_energy_consumption_kwh": 13978} +// |Heat_lower_case;11755757;OK;19529;8401.224;1111-11-11 11:11.11 + From a009f672db89cb1756e58952e789fa8da8a8e700 Mon Sep 17 00:00:00 2001 From: Andreas Horrer Date: Sun, 14 Jan 2024 20:07:31 +0100 Subject: [PATCH 06/10] corrected indent --- src/meters.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/meters.cc b/src/meters.cc index 5d5dd4d..82a81d1 100644 --- a/src/meters.cc +++ b/src/meters.cc @@ -97,8 +97,8 @@ bool DriverInfo::detect(uint16_t mfct, uchar type, uchar version) { if (dd.mfct == 0 && dd.type == 0 && dd.version == 0) continue; // Ignore drivers with no detection. if (dd.mfct == mfct && dd.type == type && dd.version == version) return true; - //some meters send mfct where the first character ist lower case, therefor % ( 32 * 1024 ) to convert mfct to upper case - if (dd.mfct == mfct % ( 32 * 1024 ) && dd.type == type && dd.version == version) return true; + //some meters send mfct where the first character ist lower case, therefor % ( 32 * 1024 ) to convert mfct to upper case + if (dd.mfct == mfct % ( 32 * 1024 ) && dd.type == type && dd.version == version) return true; } return false; } From 0cd75bec8e6fde7730b3d3be8de595357d4aecd4 Mon Sep 17 00:00:00 2001 From: Andreas Horrer Date: Thu, 18 Jan 2024 20:58:55 +0100 Subject: [PATCH 07/10] restricted incoming mfct to correct range. Specifiation allows 3*5 bit => any mfct must be smaller than 32767. --- src/meters.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/meters.cc b/src/meters.cc index 82a81d1..0c44f82 100644 --- a/src/meters.cc +++ b/src/meters.cc @@ -96,9 +96,9 @@ bool DriverInfo::detect(uint16_t mfct, uchar type, uchar version) for (auto &dd : detect_) { if (dd.mfct == 0 && dd.type == 0 && dd.version == 0) continue; // Ignore drivers with no detection. - if (dd.mfct == mfct && dd.type == type && dd.version == version) return true; - //some meters send mfct where the first character ist lower case, therefor % ( 32 * 1024 ) to convert mfct to upper case - if (dd.mfct == mfct % ( 32 * 1024 ) && dd.type == type && dd.version == version) return true; + //some meters send mfct where the first character ist lower case, which results in mfct which are bigger + //than 32767, therefore restrict mfct to correct range + if (dd.mfct == (mfct & 0x7fff) && dd.type == type && dd.version == version) return true; } return false; } From 086532373c79b67cf18826c3b166e2d13734b954 Mon Sep 17 00:00:00 2001 From: Andreas Horrer Date: Thu, 18 Jan 2024 21:00:11 +0100 Subject: [PATCH 08/10] corrected mfct of apator. Old version had 0x8614 als mfct because 'aPT' will result in 0x8614. Changes in meters.cc will compensate for wrong mfct definition. --- src/driver_apator08.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver_apator08.cc b/src/driver_apator08.cc index 9e15d0f..671f8e0 100644 --- a/src/driver_apator08.cc +++ b/src/driver_apator08.cc @@ -34,7 +34,7 @@ namespace di.setDefaultFields("name,id,total_m3,timestamp"); di.setMeterType(MeterType::WaterMeter); di.addLinkMode(LinkMode::T1); - di.addDetection(0x8614/*APT?*/, 0x03, 0x03); + di.addDetection(MANUFACTURER_APT, 0x03, 0x03); di.usesProcessContent(); di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr(new Driver(mi, di)); }); }); From ac0f0d8243229ec72bd921b347280dd28ca42406 Mon Sep 17 00:00:00 2001 From: Andreas Horrer Date: Sat, 2 Mar 2024 21:07:02 +0100 Subject: [PATCH 09/10] Corrected method name --- src/driver_itronheat.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver_itronheat.cc b/src/driver_itronheat.cc index 45d8940..c175917 100644 --- a/src/driver_itronheat.cc +++ b/src/driver_itronheat.cc @@ -38,7 +38,7 @@ namespace Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di) { - addOptionalCommonFields("meter_datetime"); + addOptionalLibraryFields("meter_datetime"); addStringFieldWithExtractorAndLookup( "status", From 25108bd29085dd5e63a3c37496ec6d98c341a240 Mon Sep 17 00:00:00 2001 From: Andreas Horrer Date: Sat, 13 Apr 2024 16:43:35 +0200 Subject: [PATCH 10/10] Adapted to interface changes --- src/driver_itronheat.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/driver_itronheat.cc b/src/driver_itronheat.cc index c175917..01df39d 100644 --- a/src/driver_itronheat.cc +++ b/src/driver_itronheat.cc @@ -53,7 +53,7 @@ namespace { { "ERROR_FLAGS", - Translate::Type::BitToString, + Translate::MapType::BitToString, AlwaysTrigger, MaskBits(0xffff), "OK", { @@ -67,7 +67,7 @@ namespace "The total heat energy consumption recorded by this meter.", DEFAULT_PRINT_PROPERTIES, Quantity::Energy, - VifScaling::Auto, + VifScaling::Auto, DifSignedness::Signed, FieldMatcher::build() .set(MeasurementType::Instantaneous) .set(VIFRange::AnyEnergyVIF) @@ -78,7 +78,7 @@ namespace "The total heating media volume recorded by this meter.", DEFAULT_PRINT_PROPERTIES, Quantity::Volume, - VifScaling::Auto, + VifScaling::Auto, DifSignedness::Signed, FieldMatcher::build() .set(MeasurementType::Instantaneous) .set(VIFRange::Volume) @@ -99,7 +99,7 @@ namespace "The total energy consumption recorded at the last day of the previous year.", DEFAULT_PRINT_PROPERTIES, Quantity::Energy, - VifScaling::Auto, + VifScaling::Auto, DifSignedness::Signed, FieldMatcher::build() .set(MeasurementType::Instantaneous) .set(StorageNr(1))