From 19263bcb46ebc959a7e8f6d9f4018463b0982fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Thu, 10 Nov 2022 22:06:51 +0100 Subject: [PATCH] Refactor ehzp and fix on_time_h bug. --- CHANGES | 2 + simulations/simulation_el_meters.txt | 10 -- simulations/simulation_t1.txt | 6 +- src/driver_ebzwmbe.cc | 28 +++++- src/driver_ehzp.cc | 86 ++++++++++++++++ src/driver_elf.cc | 2 +- src/driver_enercal.cc | 2 +- src/driver_minomess.cc | 2 +- src/driver_multical603.cc | 2 +- src/driver_qualcosonic.cc | 2 +- src/dvparser.h | 4 +- src/meter_detection.h | 1 - src/meter_ehzp.cc | 143 --------------------------- src/meters.cc | 21 +++- src/meters.h | 1 - src/meters_common_implementation.h | 7 ++ test.sh | 3 - tests/test_electricity_meters.sh | 56 ----------- 18 files changed, 147 insertions(+), 231 deletions(-) delete mode 100644 simulations/simulation_el_meters.txt create mode 100644 src/driver_ehzp.cc delete mode 100644 src/meter_ehzp.cc delete mode 100755 tests/test_electricity_meters.sh diff --git a/CHANGES b/CHANGES index e00a0b4..033e961 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +ATTENTION! A bug was fixed where the on_time_h and operating_time_h +(and related error times) were wrong. ATTENTION! The em24 driver has been refactored to the new driver format and some errors in the fields were discovered! The reactive diff --git a/simulations/simulation_el_meters.txt b/simulations/simulation_el_meters.txt deleted file mode 100644 index cc10932..0000000 --- a/simulations/simulation_el_meters.txt +++ /dev/null @@ -1,10 +0,0 @@ - -# Test different kinds of electricity meters with radio converters. -# The meters might report the same mfct/media/version but contains -# quite different content. - -# This is eBZ DD3 meter with a wMB-E01 wmbus radio converter module. - -telegram=|4B445A146450000002378C20F3900F002C25F38B00006CBB07CEB215901172635213015A140102F3002007102F2F#04039D3E03000429E82201000DFD110E333632353331313031305A424531| -{"media":"electricity","meter":"ehzp","name":"MyEl","id":"01135263","total_energy_consumption_kwh":212.637,"current_power_consumption_kw":0.74472,"total_energy_production_kwh":0,"on_time_h":0,"timestamp":"1111-11-11T11:11:11Z"} -|MyEl;01135263;212.637000;0.744720;0.000000;1111-11-11 11:11.11 diff --git a/simulations/simulation_t1.txt b/simulations/simulation_t1.txt index b1eec27..f89e234 100644 --- a/simulations/simulation_t1.txt +++ b/simulations/simulation_t1.txt @@ -175,8 +175,8 @@ telegram=|7B4479169977997730378C20F0900F002C2549EE0A0077C19D3D1A08ABCD7299779977 # Test electricity meter eHZ-P telegram=|5344A8159955995502028C201D900F002C250C390000ED176BBBB1591ADB7A1D003007102F2F_0700583B74020000000007803CBCD70200000000000728B070200000000000042092A406002F2F2F2F2F2F2F2F2F| -{"media":"electricity","meter":"ehzp","name":"Elen3","id":"55995599","total_energy_consumption_kwh":41.1718,"current_power_consumption_kw":2.126,"total_energy_production_kwh":0.1863,"on_time_h":120.929444,"timestamp":"1111-11-11T11:11:11Z"} -|Elen3;55995599;41.171800;2.126000;0.186300;1111-11-11 11:11.11 +{"media":"electricity","meter":"ehzp","name":"Elen3","id":"55995599","status":"OK","on_time_h":120.929444,"total_energy_consumption_kwh":41.1718,"current_power_consumption_kw":2.126,"total_energy_production_kwh":0.1863,"timestamp":"1111-11-11T11:11:11Z"} +|Elen3;55995599;41.1718;2.126;0.1863;1111-11-11 11:11.11 # Test water meter apator08 @@ -264,7 +264,7 @@ telegram=|534424232004256092687A370045752235854DEEEA5939FAD81C25FEEF5A23C38FB916 # Test Apator Elf Heat meter telegram=|51440186010905001837721956880101064004DA000020026CA9220E017799241103000C13641320000A2D00000A5A90060A5E800544050E77000001FD0C010A6564370AFD4731030A274907047F00000002| -{"media":"heat","meter":"elf","name":"Hetta","id":"01885619","status":"ERROR_FLAGS_2000000","meter_date":"2021-02-09","total_energy_consumption_kwh":3112.49977,"current_power_consumption_kw":0,"total_volume_m3":201.364,"total_energy_consumption_at_date_kwh":3047.8,"flow_temperature_c":69,"return_temperature_c":58,"external_temperature_c":37.64,"operating_time_h":4.993333,"version":"01","battery_v":3.31,"timestamp":"1111-11-11T11:11:11Z"} +{"media":"heat","meter":"elf","name":"Hetta","id":"01885619","status":"ERROR_FLAGS_2000000","meter_date":"2021-02-09","total_energy_consumption_kwh":3112.49977,"current_power_consumption_kw":0,"total_volume_m3":201.364,"total_energy_consumption_at_date_kwh":3047.8,"flow_temperature_c":69,"return_temperature_c":58,"external_temperature_c":37.64,"operating_time_h":17976,"version":"01","battery_v":3.31,"timestamp":"1111-11-11T11:11:11Z"} |Hetta;01885619;3112.49977;0;201.364;69;58;37.64;ERROR_FLAGS_2000000;1111-11-11 11:11.11 # Test Diehl IZAR RC I G4 water meter diff --git a/src/driver_ebzwmbe.cc b/src/driver_ebzwmbe.cc index 75523ef..0de964c 100644 --- a/src/driver_ebzwmbe.cc +++ b/src/driver_ebzwmbe.cc @@ -50,7 +50,7 @@ namespace addNumericFieldWithExtractor( "current_power_consumption_phase1", "Current power consumption at phase 1.", - PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT, + PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::OPTIONAL, Quantity::Power, VifScaling::Auto, FieldMatcher::build() @@ -60,7 +60,7 @@ namespace addNumericFieldWithExtractor( "current_power_consumption_phase2", "Current power consumption at phase 2.", - PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT, + PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::OPTIONAL, Quantity::Power, VifScaling::Auto, FieldMatcher::build() @@ -70,7 +70,7 @@ namespace addNumericFieldWithExtractor( "current_power_consumption_phase3", "Current power consumption at phase 3.", - PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT, + PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::OPTIONAL, Quantity::Power, VifScaling::Auto, FieldMatcher::build() @@ -86,13 +86,27 @@ namespace .set(VIFRange::Customer) ); +/* + addNumericFieldWithExtractor( + "current_power_consumption", + "Calculated sum of power consumption of all phases.", + PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::OPTIONAL, + Quantity::Power, + VifScaling::Auto, + FieldMatcher::build() + .set(MeasurementType::Instantaneous) + .set(VIFRange::AnyPowerVIF) + ); +*/ + addNumericFieldWithCalculator( "current_power_consumption", "Calculated sum of power consumption of all phases.", - PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT, + PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::OPTIONAL, Quantity::Power, "current_power_consumption_phase1_kw + current_power_consumption_phase2_kw + current_power_consumption_phase3_kw" ); + } } @@ -100,3 +114,9 @@ namespace // telegram=|5B445A149922992202378C20F6900F002C25BC9E0000BF48954821BC508D72992299225A140102F6003007102F2F040330F92A0004A9FF01FF24000004A9FF026A29000004A9FF03460600000DFD11063132333435362F2F2F2F2F2F| // {"media":"electricity","meter":"ebzwmbe","name":"Elen1","id":"22992299","total_energy_consumption_kwh":2816.304,"current_power_consumption_phase1_kw":0.09471,"current_power_consumption_phase2_kw":0.10602,"current_power_consumption_phase3_kw":0.01606,"customer":"654321","current_power_consumption_kw":0.21679,"timestamp":"1111-11-11T11:11:11Z"} // |Elen1;22992299;2816.304;0.21679;0.09471;0.10602;0.01606;1111-11-11 11:11.11 + +// Test: MyEl ebzwmbe 01135263 NOKEY +// Comment: This is eBZ DD3 meter with a wMB-E01 wmbus radio converter module. +// telegram=|4B445A146450000002378C20F3900F002C25F38B00006CBB07CEB215901172635213015A140102F3002007102F2F#04039D3E03000429E82201000DFD110E333632353331313031305A424531| +// {"media":"electricity","meter":"ebzwmbe","name":"MyEl","id":"01135263","total_energy_consumption_kwh":212.637,"customer":"1EBZ0101135263","current_power_consumption_kw":null,"timestamp":"1111-11-11T11:11:11Z"} +// |MyEl;01135263;212.637;null;null;null;null;1111-11-11 11:11.11 diff --git a/src/driver_ehzp.cc b/src/driver_ehzp.cc new file mode 100644 index 0000000..0e75fec --- /dev/null +++ b/src/driver_ehzp.cc @@ -0,0 +1,86 @@ +/* + Copyright (C) 2020-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); + }; + + static bool ok = registerDriver([](DriverInfo&di) + { + di.setName("ehzp"); + di.setDefaultFields("name,id,total_energy_consumption_kwh,current_power_consumption_kw,total_energy_production_kwh,timestamp"); + di.setMeterType(MeterType::ElectricityMeter); + di.addLinkMode(LinkMode::T1); + di.addDetection(MANUFACTURER_EMH, 0x02, 0x02); + di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr(new Driver(mi, di)); }); + }); + + Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di) + { + addStringField( + "status", + "Meter status. Includes both meter error field and tpl status field.", + PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT | + PrintProperty::STATUS | PrintProperty::JOIN_TPL_STATUS); + + addOptionalCommonFields(); + + addNumericFieldWithExtractor( + "total_energy_consumption", + "The total energy consumption recorded by this meter.", + PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT, + Quantity::Energy, + VifScaling::Auto, + FieldMatcher::build() + .set(MeasurementType::Instantaneous) + .set(VIFRange::AnyEnergyVIF) + ); + + addNumericFieldWithExtractor( + "current_power_consumption", + "Current power consumption.", + PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT, + Quantity::Power, + VifScaling::Auto, + FieldMatcher::build() + .set(MeasurementType::Instantaneous) + .set(VIFRange::AnyPowerVIF) + ); + + addNumericFieldWithExtractor( + "total_energy_production", + "The total energy production recorded by this meter.", + PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT, + Quantity::Energy, + VifScaling::Auto, + FieldMatcher::build() + .set(MeasurementType::Instantaneous) + .set(VIFRange::AnyEnergyVIF) + .add(VIFCombinable::BackwardFlow) + ); + + } +} + +// Test: Elen3 ehzp 55995599 NOKEY +// telegram=|5344A8159955995502028C201D900F002C250C390000ED176BBBB1591ADB7A1D003007102F2F_0700583B74020000000007803CBCD70200000000000728B070200000000000042092A406002F2F2F2F2F2F2F2F2F| +// {"media":"electricity","meter":"ehzp","name":"Elen3","id":"55995599","status":"OK","on_time_h":120.929444,"total_energy_consumption_kwh":41.1718,"current_power_consumption_kw":2.126,"total_energy_production_kwh":0.1863,"timestamp":"1111-11-11T11:11:11Z"} +// |Elen3;55995599;41.1718;2.126;0.1863;1111-11-11 11:11.11 diff --git a/src/driver_elf.cc b/src/driver_elf.cc index 866e8f6..460c59a 100644 --- a/src/driver_elf.cc +++ b/src/driver_elf.cc @@ -192,5 +192,5 @@ namespace // Test: Hetta elf 01885619 NOKEY // telegram=|51440186010905001837721956880101064004DA000020026CA9220E017799241103000C13641320000A2D00000A5A90060A5E800544050E77000001FD0C010A6564370AFD4731030A274907047F00000002| -// {"media":"heat","meter":"elf","name":"Hetta","id":"01885619","status":"ERROR_FLAGS_2000000","meter_date":"2021-02-09","total_energy_consumption_kwh":3112.49977,"current_power_consumption_kw":0,"total_volume_m3":201.364,"total_energy_consumption_at_date_kwh":3047.8,"flow_temperature_c":69,"return_temperature_c":58,"external_temperature_c":37.64,"operating_time_h":4.993333,"version":"01","battery_v":3.31,"timestamp":"1111-11-11T11:11:11Z"} +// {"media":"heat","meter":"elf","name":"Hetta","id":"01885619","status":"ERROR_FLAGS_2000000","meter_date":"2021-02-09","total_energy_consumption_kwh":3112.49977,"current_power_consumption_kw":0,"total_volume_m3":201.364,"total_energy_consumption_at_date_kwh":3047.8,"flow_temperature_c":69,"return_temperature_c":58,"external_temperature_c":37.64,"operating_time_h":17976,"version":"01","battery_v":3.31,"timestamp":"1111-11-11T11:11:11Z"} // |Hetta;01885619;3112.49977;0;201.364;69;58;37.64;ERROR_FLAGS_2000000;1111-11-11 11:11.11 diff --git a/src/driver_enercal.cc b/src/driver_enercal.cc index 8a7a1b7..22d4e32 100644 --- a/src/driver_enercal.cc +++ b/src/driver_enercal.cc @@ -244,5 +244,5 @@ namespace // Test: Heat enercal 00309924 NOKEY // Comment: // telegram=|688e8e6808017224993000e61e080406000000040681460600041488f2350084401426e02600025B2600025f220002622a00042247880200042647880200043B00000000042c00000000046d2d0ede2784406e000000008480406e00000000c4800006B1450600c48000143Be43500c4c000142fd22600c4c0006e00000000c480406e00000000c280006cc1271f00000000f416| -// {"media":"heat","meter":"enercal","name":"Heat","id":"00309924","status":"OK","total_kwh":411265,"target_kwh":411057,"power_kw":0,"flow_m3h":0,"forward_c":38,"return_c":34,"difference_c":4.2,"total_m3":35354.96,"target_m3":35318.35,"subunit1_m3":25477.5,"subunit1_target_m3":25441.75,"subunit1_hca":0,"subunit1_target_hca":0,"subunit2_hca":0,"subunit2_target_hca":0,"target_date":"2022-07-01","operating_time_h":46.099722,"on_time_h":46.099722,"meter_datetime":"2022-07-30 14:45","timestamp":"1111-11-11T11:11:11Z"} +// {"media":"heat","meter":"enercal","name":"Heat","id":"00309924","status":"OK","total_kwh":411265,"target_kwh":411057,"power_kw":0,"flow_m3h":0,"forward_c":38,"return_c":34,"difference_c":4.2,"total_m3":35354.96,"target_m3":35318.35,"subunit1_m3":25477.5,"subunit1_target_m3":25441.75,"subunit1_hca":0,"subunit1_target_hca":0,"subunit2_hca":0,"subunit2_target_hca":0,"target_date":"2022-07-01","operating_time_h":165959,"on_time_h":165959,"meter_datetime":"2022-07-30 14:45","timestamp":"1111-11-11T11:11:11Z"} // |Heat;00309924;OK;411265.000000;411057.000000;35354.960000;35318.350000;1111-11-11 11:11.11 diff --git a/src/driver_minomess.cc b/src/driver_minomess.cc index d87626e..1a8db51 100644 --- a/src/driver_minomess.cc +++ b/src/driver_minomess.cc @@ -210,5 +210,5 @@ namespace // Test: Minowired minomess 57575757 NOKEY // telegram=|6874746808007257575757496A000712000000_0C7857575757046D2414DE280413000000000C943C000000004413FFFFFFFF426CFFFF840113FFFFFFFF82016CFFFFC40113FFFFFFFFC2016CFFFF840213FFFFFFFF82026CFFFF043B000000000422E62F000004260000000034220000000002FD1700001F5716| -// {"media":"water","meter":"minomess","name":"Minowired","id":"57575757","fabrication_no":"57575757","operating_time_h":0,"on_time_h":3.406111,"on_time_at_error_h":0,"meter_datetime":"2022-08-30 20:36","total_m3":0,"total_backward_m3":0,"volume_flow_m3h":0,"target_m3":4294967.295,"target_date":"2127-15-31","status":"OK","timestamp":"1111-11-11T11:11:11Z"} +// {"media":"water","meter":"minomess","name":"Minowired","id":"57575757","fabrication_no":"57575757","operating_time_h":0,"on_time_h":12262,"on_time_at_error_h":0,"meter_datetime":"2022-08-30 20:36","total_m3":0,"total_backward_m3":0,"volume_flow_m3h":0,"target_m3":4294967.295,"target_date":"2127-15-31","status":"OK","timestamp":"1111-11-11T11:11:11Z"} // |Minowired;57575757;0;4294967.295;OK;1111-11-11 11:11.11 diff --git a/src/driver_multical603.cc b/src/driver_multical603.cc index 5d9bf60..bb31e61 100644 --- a/src/driver_multical603.cc +++ b/src/driver_multical603.cc @@ -331,5 +331,5 @@ namespace // Test: HeatInlet multical603 66666666 NOKEY // telegram=|5A442D2C66666666350C8D2066D0E16420C6A178_0406051C000004FF07393D000004FF08AE2400000414F7680000043B47000000042D1600000002596D14025DFD0804FF22000000000422E61A0000143B8C010000142D7C000000| -// {"media":"heat volume at inlet","meter":"multical603","name":"HeatInlet","id":"66666666","on_time_h":1.912778,"status":"OK","total_energy_consumption_kwh":7173,"total_volume_m3":268.71,"volume_flow_m3h":0.071,"power_kw":2.2,"max_power_kw":12.4,"t1_temperature_c":52.29,"t2_temperature_c":23.01,"max_flow_m3h":0.396,"current_status":"","forward_energy_m3c":15673,"return_energy_m3c":9390,"energy_forward_kwh":15673,"energy_returned_kwh":9390,"timestamp":"1111-11-11T11:11:11Z"} +// {"media":"heat volume at inlet","meter":"multical603","name":"HeatInlet","id":"66666666","on_time_h":6886,"status":"OK","total_energy_consumption_kwh":7173,"total_volume_m3":268.71,"volume_flow_m3h":0.071,"power_kw":2.2,"max_power_kw":12.4,"t1_temperature_c":52.29,"t2_temperature_c":23.01,"max_flow_m3h":0.396,"current_status":"","forward_energy_m3c":15673,"return_energy_m3c":9390,"energy_forward_kwh":15673,"energy_returned_kwh":9390,"timestamp":"1111-11-11T11:11:11Z"} // |HeatInlet;66666666;7173;268.71;0.071;52.29;23.01;;1111-11-11 11:11.11 diff --git a/src/driver_qualcosonic.cc b/src/driver_qualcosonic.cc index 771a2c9..558e20f 100644 --- a/src/driver_qualcosonic.cc +++ b/src/driver_qualcosonic.cc @@ -137,5 +137,5 @@ namespace // Test: qualco qualcosonic 03016408 NOKEY // telegram=|76440907086401030B0d7a78000000046d030fB726346d0000010134fd170000000004200f13cf0104240f13cf0104863B0000000004863cdc0000000413B5150600042B86f1ffff043B030200000259c002025d2c05026194fd0c780864010384086d3B17Bf258408863B000000008408863c0B000000| -// {"media":"heat/cooling load","meter":"qualcosonic","name":"qualco","id":"03016408","fabrication_no":"03016408","operating_time_h":2.34167,"on_time_h":2.34167,"meter_datetime":"2021-06-23 15:03","meter_datetime_at_error":"2000-01-01 00:00","total_m3":398.773,"flow_temperature_c":7.04,"return_temperature_c":13.24,"flow_return_temperature_difference_c":-6.2,"volume_flow_m3h":0.515,"status":"OK","total_heat_energy_kwh":0,"total_cooling_energy_kwh":220,"power_kw":-3.706,"target_datetime":"2021-05-31 23:59","target_heat_energy_kwh":0,"target_cooling_energy_kwh":11,"timestamp":"1111-11-11T11:11:11Z"} +// {"media":"heat/cooling load","meter":"qualcosonic","name":"qualco","id":"03016408","fabrication_no":"03016408","operating_time_h":8430.013056,"on_time_h":8430.013056,"meter_datetime":"2021-06-23 15:03","meter_datetime_at_error":"2000-01-01 00:00","total_m3":398.773,"flow_temperature_c":7.04,"return_temperature_c":13.24,"flow_return_temperature_difference_c":-6.2,"volume_flow_m3h":0.515,"status":"OK","total_heat_energy_kwh":0,"total_cooling_energy_kwh":220,"power_kw":-3.706,"target_datetime":"2021-05-31 23:59","target_heat_energy_kwh":0,"target_cooling_energy_kwh":11,"timestamp":"1111-11-11T11:11:11Z"} // |qualco;03016408;OK;0.000000;220.000000;-3.706000;2021-05-31 23:59;0.000000;11.000000;1111-11-11 11:11.11 diff --git a/src/dvparser.h b/src/dvparser.h index 9865a2d..16a3f4c 100644 --- a/src/dvparser.h +++ b/src/dvparser.h @@ -30,8 +30,8 @@ #define LIST_OF_VIF_RANGES \ X(Volume,0x10,0x17,Quantity::Volume,Unit::M3) \ - X(OnTime,0x20,0x23, Quantity::Time, Unit::Second) \ - X(OperatingTime,0x24,0x27, Quantity::Time, Unit::Second) \ + X(OnTime,0x20,0x23, Quantity::Time, Unit::Hour) \ + X(OperatingTime,0x24,0x27, Quantity::Time, Unit::Hour) \ X(VolumeFlow,0x38,0x3F, Quantity::Flow, Unit::M3H) \ X(FlowTemperature,0x58,0x5B, Quantity::Temperature, Unit::C) \ X(ReturnTemperature,0x5C,0x5F, Quantity::Temperature, Unit::C) \ diff --git a/src/meter_detection.h b/src/meter_detection.h index ad70098..f13fa9f 100644 --- a/src/meter_detection.h +++ b/src/meter_detection.h @@ -29,7 +29,6 @@ #define METER_DETECTION \ X(CCx01, MANUFACTURER_GSS, 0x02, 0x01) \ X(EURISII, MANUFACTURER_INE, 0x08, 0x55) \ - X(EHZP, MANUFACTURER_EMH, 0x02, 0x02) \ X(ESYSWM, MANUFACTURER_ESY, 0x37, 0x30) \ X(EVO868, MANUFACTURER_MAD, 0x07, 0x50) \ X(FHKVDATAIII,MANUFACTURER_TCH, 0x80, 0x69) \ diff --git a/src/meter_ehzp.cc b/src/meter_ehzp.cc deleted file mode 100644 index 2e451b4..0000000 --- a/src/meter_ehzp.cc +++ /dev/null @@ -1,143 +0,0 @@ -/* - Copyright (C) 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"util.h" - -struct MeterEHZP : public virtual MeterCommonImplementation -{ - MeterEHZP(MeterInfo &mi); - - double totalEnergyConsumption(Unit u); - double currentPowerConsumption(Unit u); - double totalEnergyProduction(Unit u); - double currentPowerProduction(Unit u); - -private: - - void processContent(Telegram *t); - - double total_energy_kwh_ {}; - double current_power_kw_ {}; - double total_energy_returned_kwh_ {}; - double current_power_returned_kw_ {}; - double on_time_h_ {}; -}; - -MeterEHZP::MeterEHZP(MeterInfo &mi) : - MeterCommonImplementation(mi, "ehzp") -{ - setMeterType(MeterType::ElectricityMeter); - - setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_NO_IV); - - addLinkMode(LinkMode::T1); - - addPrint("total_energy_consumption", Quantity::Energy, - [&](Unit u){ return totalEnergyConsumption(u); }, - "The total energy consumption recorded by this meter.", - PrintProperty::FIELD | PrintProperty::JSON); - - addPrint("current_power_consumption", Quantity::Power, - [&](Unit u){ return currentPowerConsumption(u); }, - "Current power consumption.", - PrintProperty::FIELD | PrintProperty::JSON); - - addPrint("total_energy_production", Quantity::Energy, - [&](Unit u){ return totalEnergyProduction(u); }, - "The total energy production recorded by this meter.", - PrintProperty::FIELD | PrintProperty::JSON); - - addPrint("on_time", Quantity::Time, - [&](Unit u){ assertQuantity(u, Quantity::Time); - return convert(on_time_h_, Unit::Hour, u); }, - "Device on time.", - PrintProperty::JSON); -} - -shared_ptr createEHZP(MeterInfo &mi) -{ - return shared_ptr(new MeterEHZP(mi)); -} - -double MeterEHZP::totalEnergyConsumption(Unit u) -{ - assertQuantity(u, Quantity::Energy); - return convert(total_energy_kwh_, Unit::KWH, u); -} - -double MeterEHZP::currentPowerConsumption(Unit u) -{ - assertQuantity(u, Quantity::Power); - return convert(current_power_kw_, Unit::KW, u); -} - -double MeterEHZP::totalEnergyProduction(Unit u) -{ - assertQuantity(u, Quantity::Energy); - return convert(total_energy_returned_kwh_, Unit::KWH, u); -} - -double MeterEHZP::currentPowerProduction(Unit u) -{ - assertQuantity(u, Quantity::Power); - return convert(current_power_returned_kw_, Unit::KW, u); -} - -void MeterEHZP::processContent(Telegram *t) -{ - /* - (ehzp) 26: 07 dif (64 Bit Integer/Binary Instantaneous value) - (ehzp) 27: 00 vif (Energy mWh) - (ehzp) 28: * 583B740200000000 total energy (41.171800 kwh) - (ehzp) 30: 07 dif (64 Bit Integer/Binary Instantaneous value) - (ehzp) 31: 80 vif (Energy mWh) - (ehzp) 32: 3C vife (backward flow) - (ehzp) 33: * BCD7020000000000 total energy returned (0.186300 kwh) - (ehzp) 3b: 07 dif (64 Bit Integer/Binary Instantaneous value) - (ehzp) 3c: 28 vif (Power mW) - (ehzp) 3d: * B070200000000000 current power (2.126000 kw) - (ehzp) 45: 04 dif (32 Bit Integer/Binary Instantaneous value) - (ehzp) 46: 20 vif (On time seconds) - (ehzp) 47: * 92A40600 on time (120.929444 h) - */ - int offset; - string key; - - if (findKey(MeasurementType::Instantaneous, VIFRange::EnergyWh, 0, 0, &key, &t->dv_entries)) - { - extractDVdouble(&t->dv_entries, key, &offset, &total_energy_kwh_); - t->addMoreExplanation(offset, " total energy (%f kwh)", total_energy_kwh_); - } - - if (findKey(MeasurementType::Instantaneous, VIFRange::PowerW, 0, 0, &key, &t->dv_entries)) - { - extractDVdouble(&t->dv_entries, key, &offset, ¤t_power_kw_); - t->addMoreExplanation(offset, " current power (%f kw)", current_power_kw_); - } - - extractDVdouble(&t->dv_entries, "07803C", &offset, &total_energy_returned_kwh_); - t->addMoreExplanation(offset, " total energy returned (%f kwh)", total_energy_returned_kwh_); - - extractDVdouble(&t->dv_entries, "0420", &offset, &on_time_h_); - t->addMoreExplanation(offset, " on time (%f h)", on_time_h_); - -} diff --git a/src/meters.cc b/src/meters.cc index 181e5ff..1602388 100644 --- a/src/meters.cc +++ b/src/meters.cc @@ -2234,8 +2234,8 @@ void MeterCommonImplementation::printMeter(Telegram *t, if (found.count(&fi) != 0) { DVEntry *dve = found[&fi]; - debug("(meters) render field %s(%s)[%d] with dventry @%d key %s data %s\n", - fi.vname().c_str(), toString(fi.xuantity()), fi.index(), + debug("(meters) render field %s(%s %s)[%d] with dventry @%d key %s data %s\n", + fi.vname().c_str(), toString(fi.xuantity()), unitToStringLowerCase(fi.defaultUnit()).c_str(), fi.index(), dve->offset, dve->dif_vif_key.str().c_str(), dve->value.c_str()); @@ -2775,8 +2775,23 @@ bool FieldInfo::extractNumeric(Meter *m, Telegram *t, DVEntry *dve) matcher_.vif_range != VIFRange::None) { decoded_unit = toDefaultUnit(matcher_.vif_range); + debug("(meter) NormalVif(%s) %s decoded %s default %s value %g\n", + toString(matcher_.vif_range), + field_name.c_str(), + unitToStringLowerCase(decoded_unit).c_str(), + unitToStringLowerCase(default_unit_).c_str(), + extracted_double_value); } - m->setNumericValue(this, decoded_unit, extracted_double_value); + else + { + debug("(meter) AnyVif(%s) %s decoded %s default %s value %g\n", + toString(matcher_.vif_range), + field_name.c_str(), + unitToStringLowerCase(decoded_unit).c_str(), + unitToStringLowerCase(default_unit_).c_str(), + extracted_double_value); + } + m->setNumericValue(this, default_unit_, convert(extracted_double_value, decoded_unit, default_unit_)); t->addMoreExplanation(dve->offset, renderJson(m, &m->conversions())); found = true; } diff --git a/src/meters.h b/src/meters.h index 7b09d26..483c9a0 100644 --- a/src/meters.h +++ b/src/meters.h @@ -62,7 +62,6 @@ LIST_OF_METER_TYPES X(auto, 0, AutoMeter, AUTO, Auto) \ X(unknown, 0, UnknownMeter, UNKNOWN, Unknown) \ X(eurisii, T1_bit, HeatCostAllocationMeter, EURISII, EurisII) \ - X(ehzp, T1_bit, ElectricityMeter, EHZP, EHZP) \ X(esyswm, T1_bit, ElectricityMeter, ESYSWM, ESYSWM) \ X(evo868, T1_bit, WaterMeter, EVO868, EVO868) \ X(fhkvdataiii,T1_bit, HeatCostAllocationMeter, FHKVDATAIII, FHKVDataIII) \ diff --git a/src/meters_common_implementation.h b/src/meters_common_implementation.h index 247f521..c0e0308 100644 --- a/src/meters_common_implementation.h +++ b/src/meters_common_implementation.h @@ -26,6 +26,13 @@ #include #include + +// Values in a meter are stored based on vname + Quantity. +// I.e. you can have a total_m3 and a total_kwh even though they share the same "total" vname +// since they have two different quantities (Volume and Energy). +// The field total_l refers to the same field storage in the meter as total_m3. +// If a wacko meter sends different values, one m3 and one l. then you +// have to name the fields using different vnames. struct NumericField { Unit unit {}; diff --git a/test.sh b/test.sh index d0a1a35..eb83096 100755 --- a/test.sh +++ b/test.sh @@ -24,9 +24,6 @@ if [ "$?" != "0" ]; then RC="1"; fi tests/test_s1_meters.sh $PROG if [ "$?" != "0" ]; then RC="1"; fi -tests/test_electricity_meters.sh $PROG -if [ "$?" != "0" ]; then RC="1"; fi - tests/test_mbus.sh $PROG if [ "$?" != "0" ]; then RC="1"; fi diff --git a/tests/test_electricity_meters.sh b/tests/test_electricity_meters.sh deleted file mode 100755 index c0b9fe0..0000000 --- a/tests/test_electricity_meters.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh - -PROG="$1" - -mkdir -p testoutput -TEST=testoutput - -TESTNAME="Test electricity meters with radio converter plugins" -TESTRESULT="ERROR" - -METERS="MyEl ehzp 01135263 NOKEY" - -cat simulations/simulation_el_meters.txt | grep '^{' > $TEST/test_expected.txt -$PROG --format=json simulations/simulation_el_meters.txt $METERS > $TEST/test_output.txt 2> $TEST/test_stderr.txt -if [ "$?" = "0" ] -then - cat $TEST/test_output.txt | sed 's/"timestamp":"....-..-..T..:..:..Z"/"timestamp":"1111-11-11T11:11:11Z"/' > $TEST/test_responses.txt - diff $TEST/test_expected.txt $TEST/test_responses.txt - if [ "$?" = "0" ] - then - echo OK json: $TESTNAME - TESTRESULT="OK" - else - TESTRESULT="ERROR" - fi -else - echo "wmbusmeters returned error code: $?" - cat $TEST/test_output.txt - cat $TEST/test_stderr.txt -fi - -cat simulations/simulation_el_meters.txt | grep '^|' | sed 's/^|//' > $TEST/test_expected.txt -$PROG --format=fields simulations/simulation_el_meters.txt $METERS > $TEST/test_output.txt 2> $TEST/test_stderr.txt -if [ "$?" = "0" ] -then - cat $TEST/test_output.txt | sed 's/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9].[0-9][0-9]$/1111-11-11 11:11.11/' > $TEST/test_responses.txt - diff $TEST/test_expected.txt $TEST/test_responses.txt - if [ "$?" = "0" ] - then - echo OK fields: $TESTNAME - TESTRESULT="OK" - else - TESTRESULT="ERROR" - fi -else - echo "wmbusmeters returned error code: $?" - cat $TEST/test_output.txt - cat $TEST/test_stderr.txt -fi - - -if [ "$TESTRESULT" = "ERROR" ] -then - echo ERROR: $TESTNAME - exit 1 -fi