diff --git a/library.json b/library.json index bbcb2db..b83c709 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "dsmr_parser", - "version": "1.9.0", + "version": "1.10.0", "description": "A parser for Dutch Smart Meter Requirements (DSMR) telegrams. Fork of arduino-dsmr. Doesn't depend on the Arduino framework and has many bug fixes and code quality improvements. Supports encrypted DSMR packets.", "keywords": "dsmr", "repository": { diff --git a/specs/ewl-luzern.ch energy provider Switzerland.pdf b/specs/ewl-luzern.ch energy provider Switzerland.pdf new file mode 100644 index 0000000..7a9d712 Binary files /dev/null and b/specs/ewl-luzern.ch energy provider Switzerland.pdf differ diff --git a/src/dsmr_parser/fields.h b/src/dsmr_parser/fields.h index 79f0b13..91356cf 100644 --- a/src/dsmr_parser/fields.h +++ b/src/dsmr_parser/fields.h @@ -330,14 +330,58 @@ DEFINE_FIELD(reactive_energy_returned_tariff3, FixedValue, ObisId(1, 0, 4, 8, 3) DEFINE_FIELD(reactive_energy_returned_tariff4, FixedValue, ObisId(1, 0, 4, 8, 4), FixedField, units::kvarh, units::varh); // Specific fields used for Switzerland +// Meter Reading electricity delivered to client (total, no tariff) in 0,001 kWh +DEFINE_FIELD(energy_delivered_ch, FixedValue, ObisId(1, 1, 1, 8, 0), FixedField, units::kWh, units::Wh); // Meter Reading electricity delivered to client (Tariff 1) in 0,001 kWh DEFINE_FIELD(energy_delivered_tariff1_ch, FixedValue, ObisId(1, 1, 1, 8, 1), FixedField, units::kWh, units::Wh); // Meter Reading electricity delivered to client (Tariff 2) in 0,001 kWh DEFINE_FIELD(energy_delivered_tariff2_ch, FixedValue, ObisId(1, 1, 1, 8, 2), FixedField, units::kWh, units::Wh); +// Meter Reading electricity delivered by client (total, no tariff) in 0,001 kWh +DEFINE_FIELD(energy_returned_ch, FixedValue, ObisId(1, 1, 2, 8, 0), FixedField, units::kWh, units::Wh); // Meter Reading electricity delivered by client (Tariff 1) in 0,001 kWh DEFINE_FIELD(energy_returned_tariff1_ch, FixedValue, ObisId(1, 1, 2, 8, 1), FixedField, units::kWh, units::Wh); // Meter Reading electricity delivered by client (Tariff 2) in 0,001 kWh DEFINE_FIELD(energy_returned_tariff2_ch, FixedValue, ObisId(1, 1, 2, 8, 2), FixedField, units::kWh, units::Wh); +// Reactive energy +R (total, no tariff) in 0,001 kvarh +DEFINE_FIELD(total_imported_energy_ch, FixedValue, ObisId(1, 1, 3, 8, 0), FixedField, units::kvarh, units::varh); +// Reactive energy -R (total, no tariff) in 0,001 kvarh +DEFINE_FIELD(total_exported_energy_ch, FixedValue, ObisId(1, 1, 4, 8, 0), FixedField, units::kvarh, units::varh); +// Reactive energy Q1 +Ri (total / Tariff 1 / Tariff 2) in 0,001 kvarh +DEFINE_FIELD(reactive_energy_q1_ch, FixedValue, ObisId(1, 1, 5, 8, 0), FixedField, units::kvarh, units::varh); +DEFINE_FIELD(reactive_energy_q1_tariff1_ch, FixedValue, ObisId(1, 1, 5, 8, 1), FixedField, units::kvarh, units::varh); +DEFINE_FIELD(reactive_energy_q1_tariff2_ch, FixedValue, ObisId(1, 1, 5, 8, 2), FixedField, units::kvarh, units::varh); +// Reactive energy Q2 +Rc (total / Tariff 1 / Tariff 2) in 0,001 kvarh +DEFINE_FIELD(reactive_energy_q2_ch, FixedValue, ObisId(1, 1, 6, 8, 0), FixedField, units::kvarh, units::varh); +DEFINE_FIELD(reactive_energy_q2_tariff1_ch, FixedValue, ObisId(1, 1, 6, 8, 1), FixedField, units::kvarh, units::varh); +DEFINE_FIELD(reactive_energy_q2_tariff2_ch, FixedValue, ObisId(1, 1, 6, 8, 2), FixedField, units::kvarh, units::varh); +// Reactive energy Q3 -Ri (total / Tariff 1 / Tariff 2) in 0,001 kvarh +DEFINE_FIELD(reactive_energy_q3_ch, FixedValue, ObisId(1, 1, 7, 8, 0), FixedField, units::kvarh, units::varh); +DEFINE_FIELD(reactive_energy_q3_tariff1_ch, FixedValue, ObisId(1, 1, 7, 8, 1), FixedField, units::kvarh, units::varh); +DEFINE_FIELD(reactive_energy_q3_tariff2_ch, FixedValue, ObisId(1, 1, 7, 8, 2), FixedField, units::kvarh, units::varh); +// Reactive energy Q4 -Rc (total / Tariff 1 / Tariff 2) in 0,001 kvarh +DEFINE_FIELD(reactive_energy_q4_ch, FixedValue, ObisId(1, 1, 8, 8, 0), FixedField, units::kvarh, units::varh); +DEFINE_FIELD(reactive_energy_q4_tariff1_ch, FixedValue, ObisId(1, 1, 8, 8, 1), FixedField, units::kvarh, units::varh); +DEFINE_FIELD(reactive_energy_q4_tariff2_ch, FixedValue, ObisId(1, 1, 8, 8, 2), FixedField, units::kvarh, units::varh); +// Instantaneous active power L1 (+P) / L2 / L3 in W resolution +DEFINE_FIELD(power_delivered_l1_ch, FixedValue, ObisId(1, 1, 21, 7, 0), FixedField, units::kW, units::W); +DEFINE_FIELD(power_delivered_l2_ch, FixedValue, ObisId(1, 1, 41, 7, 0), FixedField, units::kW, units::W); +DEFINE_FIELD(power_delivered_l3_ch, FixedValue, ObisId(1, 1, 61, 7, 0), FixedField, units::kW, units::W); +// Instantaneous active power L1 (-P) / L2 / L3 in W resolution +DEFINE_FIELD(power_returned_l1_ch, FixedValue, ObisId(1, 1, 22, 7, 0), FixedField, units::kW, units::W); +DEFINE_FIELD(power_returned_l2_ch, FixedValue, ObisId(1, 1, 42, 7, 0), FixedField, units::kW, units::W); +DEFINE_FIELD(power_returned_l3_ch, FixedValue, ObisId(1, 1, 62, 7, 0), FixedField, units::kW, units::W); +// Instantaneous reactive power L1 (+Q) / L2 / L3 in var resolution +DEFINE_FIELD(reactive_power_delivered_l1_ch, FixedValue, ObisId(1, 1, 23, 7, 0), FixedField, units::kvar, units::var); +DEFINE_FIELD(reactive_power_delivered_l2_ch, FixedValue, ObisId(1, 1, 43, 7, 0), FixedField, units::kvar, units::var); +DEFINE_FIELD(reactive_power_delivered_l3_ch, FixedValue, ObisId(1, 1, 63, 7, 0), FixedField, units::kvar, units::var); +// Instantaneous reactive power L1 (-Q) / L2 / L3 in var resolution +DEFINE_FIELD(reactive_power_returned_l1_ch, FixedValue, ObisId(1, 1, 24, 7, 0), FixedField, units::kvar, units::var); +DEFINE_FIELD(reactive_power_returned_l2_ch, FixedValue, ObisId(1, 1, 44, 7, 0), FixedField, units::kvar, units::var); +DEFINE_FIELD(reactive_power_returned_l3_ch, FixedValue, ObisId(1, 1, 64, 7, 0), FixedField, units::kvar, units::var); +// Maximum active power demand delivered (+P) with timestamp [kW] +DEFINE_FIELD(maximum_power_delivered_ch, TimestampedFixedValue, ObisId(1, 1, 1, 6, 0), TimestampedFixedField, units::kW, units::W); +// Maximum active power demand returned (-P) with timestamp [kW] +DEFINE_FIELD(maximum_power_returned_ch, TimestampedFixedValue, ObisId(1, 1, 2, 6, 0), TimestampedFixedField, units::kW, units::W); // Specific fields used for Israel // Meter Reading electricity delivered to client (Tariff 1) in 0,001 kWh diff --git a/tests/parser_test.cpp b/tests/parser_test.cpp index aa0c964..86cb800 100644 --- a/tests/parser_test.cpp +++ b/tests/parser_test.cpp @@ -58,6 +58,36 @@ TEST_CASE_FIXTURE(LogFixture, "Should parse all fields in the DSMR message corre "1-0:0.2.8(1.0.smth smth-123)\r\n" "1-1:0.2.0((ER12)\r\n" "1-1:0.2.8(ER13))\r\n" + "1-1:1.8.0(001234567*Wh)\r\n" + "1-1:2.8.0(000012.345*kWh)\r\n" + "1-1:3.8.0(000456.789*kvarh)\r\n" + "1-1:4.8.0(000000.000*kvarh)\r\n" + "1-1:5.8.0(000100.000*kvarh)\r\n" + "1-1:5.8.1(000060.000*kvarh)\r\n" + "1-1:5.8.2(000040.000*kvarh)\r\n" + "1-1:6.8.0(000010.000*kvarh)\r\n" + "1-1:6.8.1(000005.000*kvarh)\r\n" + "1-1:6.8.2(000005.000*kvarh)\r\n" + "1-1:7.8.0(000000.000*kvarh)\r\n" + "1-1:7.8.1(000000.000*kvarh)\r\n" + "1-1:7.8.2(000000.000*kvarh)\r\n" + "1-1:8.8.0(000002.500*kvarh)\r\n" + "1-1:8.8.1(000001.000*kvarh)\r\n" + "1-1:8.8.2(000001.500*kvarh)\r\n" + "1-1:21.7.0(00.332*kW)\r\n" + "1-1:41.7.0(00.430*kW)\r\n" + "1-1:61.7.0(00.000*kW)\r\n" + "1-1:22.7.0(00.000*kW)\r\n" + "1-1:42.7.0(00.100*kW)\r\n" + "1-1:62.7.0(00.050*kW)\r\n" + "1-1:23.7.0(00.120*kvar)\r\n" + "1-1:43.7.0(00.080*kvar)\r\n" + "1-1:63.7.0(00.000*kvar)\r\n" + "1-1:24.7.0(00.000*kvar)\r\n" + "1-1:44.7.0(00.010*kvar)\r\n" + "1-1:64.7.0(00.005*kvar)\r\n" + "1-1:1.6.0(250601000000W)(001.234*kW)\r\n" + "1-1:2.6.0(250601120000W)(000.000*kW)\r\n" "0-1:24.4.0(1)\r\n" "1-0:16.24.0(-03.618*kW)\r\n" "1-0:13.7.0(0.998)\r\n" @@ -131,6 +161,36 @@ TEST_CASE_FIXTURE(LogFixture, "Should parse all fields in the DSMR message corre /* String */ fw_core_checksum, /* String */ fw_module_version, /* String */ fw_module_checksum, + /* FixedValue */ energy_delivered_ch, + /* FixedValue */ energy_returned_ch, + /* FixedValue */ total_imported_energy_ch, + /* FixedValue */ total_exported_energy_ch, + /* FixedValue */ reactive_energy_q1_ch, + /* FixedValue */ reactive_energy_q1_tariff1_ch, + /* FixedValue */ reactive_energy_q1_tariff2_ch, + /* FixedValue */ reactive_energy_q2_ch, + /* FixedValue */ reactive_energy_q2_tariff1_ch, + /* FixedValue */ reactive_energy_q2_tariff2_ch, + /* FixedValue */ reactive_energy_q3_ch, + /* FixedValue */ reactive_energy_q3_tariff1_ch, + /* FixedValue */ reactive_energy_q3_tariff2_ch, + /* FixedValue */ reactive_energy_q4_ch, + /* FixedValue */ reactive_energy_q4_tariff1_ch, + /* FixedValue */ reactive_energy_q4_tariff2_ch, + /* FixedValue */ power_delivered_l1_ch, + /* FixedValue */ power_delivered_l2_ch, + /* FixedValue */ power_delivered_l3_ch, + /* FixedValue */ power_returned_l1_ch, + /* FixedValue */ power_returned_l2_ch, + /* FixedValue */ power_returned_l3_ch, + /* FixedValue */ reactive_power_delivered_l1_ch, + /* FixedValue */ reactive_power_delivered_l2_ch, + /* FixedValue */ reactive_power_delivered_l3_ch, + /* FixedValue */ reactive_power_returned_l1_ch, + /* FixedValue */ reactive_power_returned_l2_ch, + /* FixedValue */ reactive_power_returned_l3_ch, + /* TimestampedFixedValue */ maximum_power_delivered_ch, + /* TimestampedFixedValue */ maximum_power_returned_ch, /* FixedValue */ active_demand_net, /* FixedValue */ power_factor, /* FixedValue */ power_factor_l1, @@ -194,6 +254,38 @@ TEST_CASE_FIXTURE(LogFixture, "Should parse all fields in the DSMR message corre REQUIRE(data.fw_core_checksum == "1.0.smth smth-123"); REQUIRE(data.fw_module_version == "(ER12"); REQUIRE(data.fw_module_checksum == "ER13)"); + REQUIRE(data.energy_delivered_ch == 1234.567f); // 1234567 Wh = 1234.567 kWh + REQUIRE(data.energy_returned_ch == 12.345f); + REQUIRE(data.total_imported_energy_ch == 456.789f); + REQUIRE(data.total_exported_energy_ch == 0.0f); + REQUIRE(data.reactive_energy_q1_ch == 100.0f); + REQUIRE(data.reactive_energy_q1_tariff1_ch == 60.0f); + REQUIRE(data.reactive_energy_q1_tariff2_ch == 40.0f); + REQUIRE(data.reactive_energy_q2_ch == 10.0f); + REQUIRE(data.reactive_energy_q2_tariff1_ch == 5.0f); + REQUIRE(data.reactive_energy_q2_tariff2_ch == 5.0f); + REQUIRE(data.reactive_energy_q3_ch == 0.0f); + REQUIRE(data.reactive_energy_q3_tariff1_ch == 0.0f); + REQUIRE(data.reactive_energy_q3_tariff2_ch == 0.0f); + REQUIRE(data.reactive_energy_q4_ch == 2.5f); + REQUIRE(data.reactive_energy_q4_tariff1_ch == 1.0f); + REQUIRE(data.reactive_energy_q4_tariff2_ch == 1.5f); + REQUIRE(data.power_delivered_l1_ch == 0.332f); + REQUIRE(data.power_delivered_l2_ch == 0.430f); + REQUIRE(data.power_delivered_l3_ch == 0.0f); + REQUIRE(data.power_returned_l1_ch == 0.0f); + REQUIRE(data.power_returned_l2_ch == 0.100f); + REQUIRE(data.power_returned_l3_ch == 0.050f); + REQUIRE(data.reactive_power_delivered_l1_ch == 0.120f); + REQUIRE(data.reactive_power_delivered_l2_ch == 0.080f); + REQUIRE(data.reactive_power_delivered_l3_ch == 0.0f); + REQUIRE(data.reactive_power_returned_l1_ch == 0.0f); + REQUIRE(data.reactive_power_returned_l2_ch == 0.010f); + REQUIRE(data.reactive_power_returned_l3_ch == 0.005f); + REQUIRE(data.maximum_power_delivered_ch == 1.234f); + REQUIRE(data.maximum_power_delivered_ch.timestamp == "250601000000W"); + REQUIRE(data.maximum_power_returned_ch == 0.0f); + REQUIRE(data.maximum_power_returned_ch.timestamp == "250601120000W"); REQUIRE(data.active_demand_net == -3.618f); REQUIRE(data.power_factor == 0.998f); REQUIRE(data.power_factor_l1 == 0.975f);