Added support for the esyswm electricity meter addon.

pull/70/head
weetmuts 2020-01-29 07:42:24 +01:00
rodzic e944f3c13f
commit 67a9d70b7a
24 zmienionych plików z 345 dodań i 68 usunięć

Wyświetl plik

@ -113,6 +113,7 @@ METER_OBJS:=\
$(BUILD)/meter_cma12w.o \
$(BUILD)/meter_q400.o \
$(BUILD)/meter_ehzp.o \
$(BUILD)/meter_esyswm.o \
$(BUILD)/printer.o \
$(BUILD)/serial.o \
$(BUILD)/shell.o \

Wyświetl plik

@ -212,6 +212,7 @@ Elvaco CMa12w Thermometer (cma12w)
Supported electricity meters:
Tauron Amiplus (amiplus) (includes vendor apator and echelon)
EMH Metering (ehzp)
Easy Meter ESYS-WM20 (esyswm)
Work in progress:
Electricity meter Kamstrup Omnipower (omnipower)

Wyświetl plik

@ -301,7 +301,7 @@ bool hasKey(std::map<std::string,std::pair<int,DVEntry>> *values, std::string ke
return values->count(key) > 0;
}
bool findKey(MeasurementType mit, ValueInformation vif, int storagenr,
bool findKey(MeasurementType mit, ValueInformation vif, int storagenr, int tariffnr,
std::string *key, std::map<std::string,std::pair<int,DVEntry>> *values)
{
int low, hi;
@ -316,13 +316,15 @@ bool findKey(MeasurementType mit, ValueInformation vif, int storagenr,
MeasurementType ty = v.second.second.type;
int vi = v.second.second.value_information;
int sn = v.second.second.storagenr;
int tn = v.second.second.tariff;
debug("(dvparser) match? %s type=%s vif=%02x (%s) and storagenr=%d\n",
v.first.c_str(),
measurementTypeName(ty).c_str(), vi, toString(toValueInformation(vi)), storagenr, sn);
if (vi >= low && vi <= hi
&& (mit == MeasurementType::Unknown || mit == ty)
&& (storagenr == ANY_STORAGENR || storagenr == sn))
&& (storagenr == ANY_STORAGENR || storagenr == sn)
&& (tariffnr == ANY_TARIFFNR || tariffnr == tn))
{
*key = v.first;
debug("(dvparser) found key %s for type=%s vif=%02x (%s) storagenr=%d\n",

Wyświetl plik

@ -64,8 +64,11 @@ bool parseDV(Telegram *t,
// find an existing difvif entry in the values based on the desired value information type.
// Like: Volume, VolumeFlow, FlowTemperature, ExternalTemperature etc
// in combination with the storagenr. (Later I will add tariff/subunit)
bool findKey(MeasurementType mt, ValueInformation vi, int storagenr, std::string *key, std::map<std::string,std::pair<int,DVEntry>> *values);
bool findKey(MeasurementType mt, ValueInformation vi, int storagenr, int tariffnr,
std::string *key, std::map<std::string,std::pair<int,DVEntry>> *values);
#define ANY_STORAGENR -1
#define ANY_TARIFFNR -1
bool hasKey(std::map<std::string,std::pair<int,DVEntry>> *values, std::string key);

Wyświetl plik

@ -302,7 +302,7 @@ LIST_OF_METERS
t.parserNoWarnings(); // Try a best effort parse, do not print any warnings.
t.parse(frame, &mk);
t.print();
t.explainParse("",0);
t.explainParse("(wmbus)",0);
logTelegram("(wmbus)", t.frame, 0, 0);
return true;
});

Wyświetl plik

@ -120,12 +120,12 @@ void MeterAmiplus::processContent(Telegram *t)
int offset;
string key;
if (findKey(MeasurementType::Unknown, ValueInformation::EnergyWh, 0, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::EnergyWh, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &total_energy_kwh_);
t->addMoreExplanation(offset, " total energy (%f kwh)", total_energy_kwh_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::PowerW, 0, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::PowerW, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &current_power_kw_);
t->addMoreExplanation(offset, " current power (%f kw)", current_power_kw_);
}
@ -136,7 +136,7 @@ void MeterAmiplus::processContent(Telegram *t)
extractDVdouble(&t->values, "0BAB3C", &offset, &current_power_returned_kw_);
t->addMoreExplanation(offset, " current power returned (%f kw)", current_power_returned_kw_);
if (findKey(MeasurementType::Unknown, ValueInformation::DateTime, 0, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::DateTime, 0, 0, &key, &t->values)) {
struct tm datetime;
extractDVdate(&t->values, key, &offset, &datetime);
device_date_time_ = strdatetime(&datetime);

Wyświetl plik

@ -118,7 +118,7 @@ void MeterApator162::processContent(Telegram *t)
vendor_values["0413"] = { 25, DVEntry(MeasurementType::Instantaneous, 0x13, 0, 0, 0, total) };
int offset;
string key;
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 0, &key, &vendor_values))
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 0, 0, &key, &vendor_values))
{
extractDVdouble(&vendor_values, key, &offset, &total_water_consumption_m3_);
//Adding explanation have to wait since it assumes that the dvparser could do something, but it could not here.

Wyświetl plik

@ -99,13 +99,13 @@ void MeterCMa12w::processContent(Telegram *t)
int offset;
string key;
if (findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, 0, &key, &t->values))
if (findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, 0, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &current_temperature_c_);
t->addMoreExplanation(offset, " current temperature (%f C)", current_temperature_c_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, 1, &key, &t->values))
if (findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, 1, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &average_temperature_1h_c_);
t->addMoreExplanation(offset, " average temperature 1h (%f C))", average_temperature_1h_c_);

Wyświetl plik

@ -22,7 +22,8 @@
#include"wmbus_utils.h"
#include"util.h"
struct MeterEHZP : public virtual ElectricityMeter, public virtual MeterCommonImplementation {
struct MeterEHZP : public virtual ElectricityMeter, public virtual MeterCommonImplementation
{
MeterEHZP(WMBus *bus, MeterInfo &mi);
double totalEnergyConsumption(Unit u);
@ -44,18 +45,10 @@ private:
MeterEHZP::MeterEHZP(WMBus *bus, MeterInfo &mi) :
MeterCommonImplementation(bus, mi, MeterType::EHZP, MANUFACTURER_EMH)
{
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_NO_IV);
// This is one manufacturer of EHZP compatible meters.
addManufacturer(MANUFACTURER_APA);
addMedia(0x02); // Electricity meter
// This is another manufacturer
addManufacturer(MANUFACTURER_DEV);
// Oddly, this device has not been configured to send as a electricity meter,
// but instead a device/media type that is used for gateway or relays or something?
addMedia(0x37); // Radio converter (meter side)
addLinkMode(LinkMode::T1);
setExpectedVersion(0x02);
@ -113,16 +106,31 @@ double MeterEHZP::currentPowerProduction(Unit 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::Unknown, ValueInformation::EnergyWh, 0, &key, &t->values))
if (findKey(MeasurementType::Unknown, ValueInformation::EnergyWh, 0, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &total_energy_kwh_);
t->addMoreExplanation(offset, " total energy (%f kwh)", total_energy_kwh_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::PowerW, 0, &key, &t->values))
if (findKey(MeasurementType::Unknown, ValueInformation::PowerW, 0, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &current_power_kw_);
t->addMoreExplanation(offset, " current power (%f kw)", current_power_kw_);

249
src/meter_esyswm.cc 100644
Wyświetl plik

@ -0,0 +1,249 @@
/*
Copyright (C) 2020 Fredrik Öhrström
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 <http://www.gnu.org/licenses/>.
*/
#include"dvparser.h"
#include"meters.h"
#include"meters_common_implementation.h"
#include"wmbus.h"
#include"wmbus_utils.h"
#include"util.h"
struct MeterESYSWM : public virtual ElectricityMeter, public virtual MeterCommonImplementation
{
MeterESYSWM(WMBus *bus, MeterInfo &mi);
double totalEnergyConsumption(Unit u);
double totalEnergyConsumptionTariff1(Unit u);
double totalEnergyConsumptionTariff2(Unit u);
double currentPowerConsumption(Unit u);
double currentPowerConsumptionPhase1(Unit u);
double currentPowerConsumptionPhase2(Unit u);
double currentPowerConsumptionPhase3(Unit u);
double totalEnergyProduction(Unit u);
double currentPowerProduction(Unit u);
private:
void processContent(Telegram *t);
double total_energy_kwh_ {};
double total_energy_tariff1_kwh_ {};
double total_energy_tariff2_kwh_ {};
double current_power_kw_ {};
double current_power_phase1_kw_ {};
double current_power_phase2_kw_ {};
double current_power_phase3_kw_ {};
double total_energy_returned_kwh_ {};
double current_power_returned_kw_ {};
string device_date_time_;
};
MeterESYSWM::MeterESYSWM(WMBus *bus, MeterInfo &mi) :
MeterCommonImplementation(bus, mi, MeterType::ESYSWM, 0)
{
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_NO_IV);
addManufacturer(MANUFACTURER_EMH);
// The ESYS-WM-20 and ESYS-WM15 are addons to the electricity meters.
addMedia(0x37); // Radio converter (meter side)
addLinkMode(LinkMode::T1);
setExpectedVersion(0x30);
addPrint("total_energy_consumption", Quantity::Energy,
[&](Unit u){ return totalEnergyConsumption(u); },
"The total energy consumption recorded by this meter.",
true, true);
addPrint("current_power_consumption", Quantity::Power,
[&](Unit u){ return currentPowerConsumption(u); },
"Current power consumption.",
true, true);
addPrint("total_energy_production", Quantity::Energy,
[&](Unit u){ return totalEnergyProduction(u); },
"The total energy production recorded by this meter.",
true, true);
addPrint("total_energy_consumption_tariff1", Quantity::Energy,
[&](Unit u){ return totalEnergyConsumptionTariff1(u); },
"The total energy consumption recorded by this meter on tariff 1.",
false, true);
addPrint("total_energy_consumption_tariff2", Quantity::Energy,
[&](Unit u){ return totalEnergyConsumptionTariff2(u); },
"The total energy consumption recorded by this meter on tariff 2.",
false, true);
addPrint("current_power_consumption_phase1", Quantity::Power,
[&](Unit u){ return currentPowerConsumptionPhase1(u); },
"Current power consumption phase 1.",
false, true);
addPrint("current_power_consumption_phase2", Quantity::Power,
[&](Unit u){ return currentPowerConsumptionPhase2(u); },
"Current power consumption phase 2.",
false, true);
addPrint("current_power_consumption_phase3", Quantity::Power,
[&](Unit u){ return currentPowerConsumptionPhase3(u); },
"Current power consumption phase 3.",
false, true);
}
unique_ptr<ElectricityMeter> createESYSWM(WMBus *bus, MeterInfo &mi)
{
return unique_ptr<ElectricityMeter>(new MeterESYSWM(bus, mi));
}
double MeterESYSWM::totalEnergyConsumption(Unit u)
{
assertQuantity(u, Quantity::Energy);
return convert(total_energy_kwh_, Unit::KWH, u);
}
double MeterESYSWM::totalEnergyConsumptionTariff1(Unit u)
{
assertQuantity(u, Quantity::Energy);
return convert(total_energy_tariff1_kwh_, Unit::KWH, u);
}
double MeterESYSWM::totalEnergyConsumptionTariff2(Unit u)
{
assertQuantity(u, Quantity::Energy);
return convert(total_energy_tariff2_kwh_, Unit::KWH, u);
}
double MeterESYSWM::currentPowerConsumption(Unit u)
{
assertQuantity(u, Quantity::Power);
return convert(current_power_kw_, Unit::KW, u);
}
double MeterESYSWM::currentPowerConsumptionPhase1(Unit u)
{
assertQuantity(u, Quantity::Power);
return convert(current_power_phase1_kw_, Unit::KW, u);
}
double MeterESYSWM::currentPowerConsumptionPhase2(Unit u)
{
assertQuantity(u, Quantity::Power);
return convert(current_power_phase2_kw_, Unit::KW, u);
}
double MeterESYSWM::currentPowerConsumptionPhase3(Unit u)
{
assertQuantity(u, Quantity::Power);
return convert(current_power_phase3_kw_, Unit::KW, u);
}
double MeterESYSWM::totalEnergyProduction(Unit u)
{
assertQuantity(u, Quantity::Energy);
return convert(total_energy_returned_kwh_, Unit::KWH, u);
}
double MeterESYSWM::currentPowerProduction(Unit u)
{
assertQuantity(u, Quantity::Power);
return convert(current_power_returned_kw_, Unit::KW, u);
}
void MeterESYSWM::processContent(Telegram *t)
{
/*
(esyswm) 2e: 07 dif (64 Bit Integer/Binary Instantaneous value)
(esyswm) 2f: 02 vif (Energy 10¹ Wh)
(esyswm) 30: * F5C3FA0000000000 total energy (1643.416500 kwh)
(esyswm) 38: 07 dif (64 Bit Integer/Binary Instantaneous value)
(esyswm) 39: 82 vif (Energy 10¹ Wh)
(esyswm) 3a: 3C vife (backward flow)
(esyswm) 3b: * 5407000000000000 total energy returned (0.187600 kwh)
(esyswm) 43: 84 dif (32 Bit Integer/Binary Instantaneous value)
(esyswm) 44: 10 dife (subunit=0 tariff=1 storagenr=0)
(esyswm) 45: 04 vif (Energy 10¹ Wh)
(esyswm) 46: * E0810200 total energy tariff 1 (1643.200000 kwh)
(esyswm) 4a: 84 dif (32 Bit Integer/Binary Instantaneous value)
(esyswm) 4b: 20 dife (subunit=0 tariff=2 storagenr=0)
(esyswm) 4c: 04 vif (Energy 10¹ Wh)
(esyswm) 4d: * 15000000 total energy tariff 2 (0.210000 kwh)
(esyswm) 51: 04 dif (32 Bit Integer/Binary Instantaneous value)
(esyswm) 52: 29 vif (Power 10² W)
(esyswm) 53: * 38AB0000 current power (0.438320 kw)
(esyswm) 57: 04 dif (32 Bit Integer/Binary Instantaneous value)
(esyswm) 58: A9 vif (Power 10² W)
(esyswm) 59: FF vife (additive correction constant: unit of VIF * 10^0)
(esyswm) 5a: 01 vife (?)
(esyswm) 5b: FA0A0000
(esyswm) 5f: 04 dif (32 Bit Integer/Binary Instantaneous value)
(esyswm) 60: A9 vif (Power 10² W)
(esyswm) 61: FF vife (additive correction constant: unit of VIF * 10^0)
(esyswm) 62: 02 vife (?)
(esyswm) 63: 050A0000
(esyswm) 67: 04 dif (32 Bit Integer/Binary Instantaneous value)
(esyswm) 68: A9 vif (Power 10² W)
(esyswm) 69: FF vife (additive correction constant: unit of VIF * 10^0)
(esyswm) 6a: 03 vife (?)
(esyswm) 6b: 38960000
*/
int offset;
string key;
if (findKey(MeasurementType::Unknown, ValueInformation::EnergyWh, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &total_energy_kwh_);
t->addMoreExplanation(offset, " total energy (%f kwh)", total_energy_kwh_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::EnergyWh, 0, 1, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &total_energy_tariff1_kwh_);
t->addMoreExplanation(offset, " total energy tariff 1 (%f kwh)", total_energy_tariff1_kwh_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::EnergyWh, 0, 2, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &total_energy_tariff2_kwh_);
t->addMoreExplanation(offset, " total energy tariff 2 (%f kwh)", total_energy_tariff2_kwh_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::PowerW, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &current_power_kw_);
t->addMoreExplanation(offset, " current power (%f kw)", current_power_kw_);
}
extractDVdouble(&t->values, "07823C", &offset, &total_energy_returned_kwh_);
t->addMoreExplanation(offset, " total energy returned (%f kwh)", total_energy_returned_kwh_);
extractDVdouble(&t->values, "04A9FF01", &offset, &current_power_phase1_kw_);
t->addMoreExplanation(offset, " current power phase 1 (%f kwh)", current_power_phase1_kw_);
extractDVdouble(&t->values, "04A9FF02", &offset, &current_power_phase1_kw_);
t->addMoreExplanation(offset, " current power phase 2 (%f kwh)", current_power_phase2_kw_);
extractDVdouble(&t->values, "04A9FF03", &offset, &current_power_phase1_kw_);
t->addMoreExplanation(offset, " current power phase 3 (%f kwh)", current_power_phase3_kw_);
}

Wyświetl plik

@ -212,13 +212,13 @@ void MeterEurisII::processContent(Telegram *t)
int offset;
string key;
if (findKey(MeasurementType::Unknown, ValueInformation::HeatCostAllocation, 0, &key, &t->values))
if (findKey(MeasurementType::Unknown, ValueInformation::HeatCostAllocation, 0, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &current_consumption_hca_);
t->addMoreExplanation(offset, " current consumption (%f hca)", current_consumption_hca_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::Date, 1, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::Date, 1, 0, &key, &t->values)) {
struct tm date;
extractDVdate(&t->values, key, &offset, &date);
set_date_ = strdate(&date);
@ -227,7 +227,7 @@ void MeterEurisII::processContent(Telegram *t)
for (int i=1; i<=17; ++i)
{
if (findKey(MeasurementType::Unknown, ValueInformation::HeatCostAllocation, i, &key, &t->values))
if (findKey(MeasurementType::Unknown, ValueInformation::HeatCostAllocation, i, 0, &key, &t->values))
{
string info;
strprintf(info, " consumption at set date %d (%%f hca)", i);

Wyświetl plik

@ -68,12 +68,12 @@ void MeterHydrodigit::processContent(Telegram *t)
int offset;
string key;
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 0, &key, &t->values)) {
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &total_water_consumption_m3_);
t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_m3_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::DateTime, 0, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::DateTime, 0, 0, &key, &t->values)) {
struct tm datetime;
extractDVdate(&t->values, key, &offset, &datetime);
meter_datetime_ = strdatetime(&datetime);

Wyświetl plik

@ -134,27 +134,27 @@ void MeterHydrus::processContent(Telegram *t)
int offset;
string key;
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 0, &key, &t->values)) {
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &total_water_consumption_m3_);
t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_m3_);
}
if(findKey(MeasurementType::Unknown, ValueInformation::VolumeFlow, 0, &key, &t->values)) {
if(findKey(MeasurementType::Unknown, ValueInformation::VolumeFlow, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &max_flow_m3h_);
t->addMoreExplanation(offset, " max flow (%f m3/h)", max_flow_m3h_);
}
if(findKey(MeasurementType::Unknown, ValueInformation::FlowTemperature, 0, &key, &t->values)) {
if(findKey(MeasurementType::Unknown, ValueInformation::FlowTemperature, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &flow_temperature_c_);
t->addMoreExplanation(offset, " flow temperature (%f °C)", flow_temperature_c_);
}
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 3, &key, &t->values)) {
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 3, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &total_water_consumption_at_date_m3_);
t->addMoreExplanation(offset, " total consumption at date (%f m3)", total_water_consumption_at_date_m3_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::DateTime, 3, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::DateTime, 3, 0, &key, &t->values)) {
struct tm datetime;
extractDVdate(&t->values, key, &offset, &datetime);
at_date_ = strdatetime(&datetime);

Wyświetl plik

@ -73,12 +73,12 @@ void MeterIperl::processContent(Telegram *t)
int offset;
string key;
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 0, &key, &t->values)) {
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &total_water_consumption_m3_);
t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_m3_);
}
if(findKey(MeasurementType::Unknown, ValueInformation::VolumeFlow, ANY_STORAGENR, &key, &t->values)) {
if(findKey(MeasurementType::Unknown, ValueInformation::VolumeFlow, ANY_STORAGENR, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &max_flow_m3h_);
t->addMoreExplanation(offset, " max flow (%f m3/h)", max_flow_m3h_);
}

Wyświetl plik

@ -131,19 +131,19 @@ void MeterLansenTH::processContent(Telegram *t)
int offset;
string key;
if (findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, 0, &key, &t->values))
if (findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, 0, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &current_temperature_c_);
t->addMoreExplanation(offset, " current temperature (%f C)", current_temperature_c_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, 1, &key, &t->values))
if (findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, 1, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &average_temperature_1h_c_);
t->addMoreExplanation(offset, " average temperature 1h (%f C))", average_temperature_1h_c_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, 2, &key, &t->values))
if (findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, 2, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &average_temperature_24h_c_);
t->addMoreExplanation(offset, " average temperature 24h (%f C))", average_temperature_24h_c_);

Wyświetl plik

@ -307,30 +307,30 @@ void MeterMultical21::processContent(Telegram *t)
extractDVuint16(&t->values, "02FF20", &offset, &info_codes_);
t->addMoreExplanation(offset, " info codes (%s)", statusHumanReadable().c_str());
if(findKey(MeasurementType::Instantaneous, ValueInformation::Volume, 0, &key, &t->values)) {
if(findKey(MeasurementType::Instantaneous, ValueInformation::Volume, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &total_water_consumption_m3_);
has_total_water_consumption_ = true;
t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_m3_);
}
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 1, &key, &t->values)) {
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 1, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &target_water_consumption_m3_);
has_target_water_consumption_ = true;
t->addMoreExplanation(offset, " target consumption (%f m3)", target_water_consumption_m3_);
}
if(findKey(MeasurementType::Unknown, ValueInformation::VolumeFlow, ANY_STORAGENR, &key, &t->values)) {
if(findKey(MeasurementType::Unknown, ValueInformation::VolumeFlow, ANY_STORAGENR, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &max_flow_m3h_);
has_max_flow_ = true;
t->addMoreExplanation(offset, " max flow (%f m3/h)", max_flow_m3h_);
}
if(findKey(MeasurementType::Unknown, ValueInformation::FlowTemperature, ANY_STORAGENR, &key, &t->values)) {
if(findKey(MeasurementType::Unknown, ValueInformation::FlowTemperature, ANY_STORAGENR, 0, &key, &t->values)) {
has_flow_temperature_ = extractDVdouble(&t->values, key, &offset, &flow_temperature_c_);
t->addMoreExplanation(offset, " flow temperature (%f °C)", flow_temperature_c_);
}
if(findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, ANY_STORAGENR, &key, &t->values)) {
if(findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, ANY_STORAGENR, 0, &key, &t->values)) {
has_external_temperature_ = extractDVdouble(&t->values, key, &offset, &external_temperature_c_);
t->addMoreExplanation(offset, " external temperature (%f °C)", external_temperature_c_);
}

Wyświetl plik

@ -151,27 +151,27 @@ void MeterMultical302::processContent(Telegram *t)
extractDVuint8(&t->values, "01FF21", &offset, &info_codes_);
t->addMoreExplanation(offset, " info codes (%s)", status().c_str());
if(findKey(MeasurementType::Instantaneous, ValueInformation::EnergyWh, 0, &key, &t->values)) {
if(findKey(MeasurementType::Instantaneous, ValueInformation::EnergyWh, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &total_energy_kwh_);
t->addMoreExplanation(offset, " total energy consumption (%f kWh)", total_energy_kwh_);
}
if(findKey(MeasurementType::Instantaneous, ValueInformation::Volume, 0, &key, &t->values)) {
if(findKey(MeasurementType::Instantaneous, ValueInformation::Volume, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &total_volume_m3_);
t->addMoreExplanation(offset, " total volume (%f m3)", total_volume_m3_);
}
if(findKey(MeasurementType::Instantaneous, ValueInformation::EnergyWh, 1, &key, &t->values)) {
if(findKey(MeasurementType::Instantaneous, ValueInformation::EnergyWh, 1, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &target_energy_kwh_);
t->addMoreExplanation(offset, " target energy consumption (%f kWh)", target_energy_kwh_);
}
if(findKey(MeasurementType::Instantaneous, ValueInformation::PowerW, 0, &key, &t->values)) {
if(findKey(MeasurementType::Instantaneous, ValueInformation::PowerW, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &current_power_kw_);
t->addMoreExplanation(offset, " current power consumption (%f kW)", current_power_kw_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::Date, 1, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::Date, 1, 0, &key, &t->values)) {
struct tm datetime;
extractDVdate(&t->values, key, &offset, &datetime);
target_date_ = strdatetime(&datetime);

Wyświetl plik

@ -100,17 +100,17 @@ void MeterQ400::processContent(Telegram *t)
int offset;
string key;
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 0, &key, &t->values)) {
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &total_water_consumption_m3_);
t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_m3_);
}
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 1, &key, &t->values)) {
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 1, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &consumption_at_set_date_m3_);
t->addMoreExplanation(offset, " consumption at set date (%f m3)", consumption_at_set_date_m3_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::DateTime, 1, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::DateTime, 1, 0, &key, &t->values)) {
struct tm date;
extractDVdate(&t->values, key, &offset, &date);
set_date_ = strdate(&date);

Wyświetl plik

@ -169,29 +169,29 @@ void MeterQCaloric::processContent(Telegram *t)
int offset;
string key;
if (findKey(MeasurementType::Unknown, ValueInformation::HeatCostAllocation, 0, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::HeatCostAllocation, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &current_consumption_hca_);
t->addMoreExplanation(offset, " current consumption (%f hca)", current_consumption_hca_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::Date, 1, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::Date, 1, 0, &key, &t->values)) {
struct tm date;
extractDVdate(&t->values, key, &offset, &date);
set_date_ = strdate(&date);
t->addMoreExplanation(offset, " set date (%s)", set_date_.c_str());
}
if (findKey(MeasurementType::Unknown, ValueInformation::HeatCostAllocation, 1, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::HeatCostAllocation, 1, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &consumption_at_set_date_hca_);
t->addMoreExplanation(offset, " consumption at set date (%f hca)", consumption_at_set_date_hca_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::HeatCostAllocation, 17, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::HeatCostAllocation, 17, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &consumption_at_set_date_17_hca_);
t->addMoreExplanation(offset, " consumption at set date 17 (%f hca)", consumption_at_set_date_17_hca_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::Date, 17, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::Date, 17, 0, &key, &t->values)) {
struct tm date;
extractDVdate(&t->values, key, &offset, &date);
set_date_17_ = strdate(&date);
@ -206,7 +206,7 @@ void MeterQCaloric::processContent(Telegram *t)
t->addMoreExplanation(offset, " error date (%s)", error_date_.c_str());
}
if (findKey(MeasurementType::Unknown, ValueInformation::DateTime, 0, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::DateTime, 0, 0, &key, &t->values)) {
struct tm datetime;
extractDVdate(&t->values, key, &offset, &datetime);
device_date_time_ = strdatetime(&datetime);

Wyświetl plik

@ -266,45 +266,45 @@ void MeterRfmAmb::processContent(Telegram *t)
int offset;
string key;
if (findKey(MeasurementType::Instantaneous, ValueInformation::ExternalTemperature, 0, &key, &t->values))
if (findKey(MeasurementType::Instantaneous, ValueInformation::ExternalTemperature, 0, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &current_temperature_c_);
t->addMoreExplanation(offset, " current temperature (%f C)", current_temperature_c_);
}
if (findKey(MeasurementType::Maximum, ValueInformation::ExternalTemperature, 0, &key, &t->values))
if (findKey(MeasurementType::Maximum, ValueInformation::ExternalTemperature, 0, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &maximum_temperature_1h_c_);
t->addMoreExplanation(offset, " maximum temperature 1h (%f C)", maximum_temperature_1h_c_);
}
if (findKey(MeasurementType::Minimum, ValueInformation::ExternalTemperature, 0, &key, &t->values))
if (findKey(MeasurementType::Minimum, ValueInformation::ExternalTemperature, 0, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &minimum_temperature_1h_c_);
t->addMoreExplanation(offset, " minimum temperature 1h (%f C)", minimum_temperature_1h_c_);
}
if (findKey(MeasurementType::Maximum, ValueInformation::ExternalTemperature, 1, &key, &t->values))
if (findKey(MeasurementType::Maximum, ValueInformation::ExternalTemperature, 1, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &maximum_temperature_24h_c_);
t->addMoreExplanation(offset, " maximum temperature 24h (%f C)",
maximum_temperature_24h_c_);
}
if (findKey(MeasurementType::Minimum, ValueInformation::ExternalTemperature, 1, &key, &t->values))
if (findKey(MeasurementType::Minimum, ValueInformation::ExternalTemperature, 1, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &minimum_temperature_24h_c_);
t->addMoreExplanation(offset, " minimum temperature 24h (%f C)",
minimum_temperature_24h_c_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, 1, &key, &t->values))
if (findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, 1, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &average_temperature_1h_c_);
t->addMoreExplanation(offset, " average temperature 1h (%f C)", average_temperature_1h_c_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, 2, &key, &t->values))
if (findKey(MeasurementType::Unknown, ValueInformation::ExternalTemperature, 2, 0, &key, &t->values))
{
extractDVdouble(&t->values, key, &offset, &average_temperature_24h_c_);
t->addMoreExplanation(offset, " average temperature 24h (%f C)", average_temperature_24h_c_);
@ -369,7 +369,7 @@ void MeterRfmAmb::processContent(Telegram *t)
t->addMoreExplanation(offset, " relative humidity 24h (%f RH)", average_relative_humidity_24h_rh_);
}
if (findKey(MeasurementType::Unknown, ValueInformation::DateTime, 0, &key, &t->values)) {
if (findKey(MeasurementType::Unknown, ValueInformation::DateTime, 0, 0, &key, &t->values)) {
struct tm datetime;
extractDVdate(&t->values, key, &offset, &datetime);
device_date_time_ = strdatetime(&datetime);

Wyświetl plik

@ -66,7 +66,7 @@ void MeterSupercom587::processContent(Telegram *t)
int offset;
string key;
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 0, &key, &t->values)) {
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &total_water_consumption_m3_);
t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_m3_);
}

Wyświetl plik

@ -30,7 +30,8 @@
X(apator162, C1_bit|T1_bit, Water, APATOR162, Apator162) \
X(cma12w, C1_bit|T1_bit, TempHygro, CMA12W, CMa12w) \
X(eurisii, T1_bit, HeatCostAllocation, EURISII, EurisII) \
X(ehzp, T1_bit, Water, EHZP, EHZP) \
X(ehzp, T1_bit, Electricity, EHZP, EHZP) \
X(esyswm, T1_bit, Electricity, ESYSWM, ESYSWM) \
X(flowiq3100, C1_bit, Water, FLOWIQ3100, Multical21) \
X(hydrus, T1_bit, Water, HYDRUS, Hydrus) \
X(hydrodigit, T1_bit, Water, HYDRODIGIT, Hydrodigit) \
@ -208,6 +209,7 @@ unique_ptr<TempHygroMeter> createLansenTH(WMBus *bus, MeterInfo &m);
unique_ptr<TempHygroMeter> createCMa12w(WMBus *bus, MeterInfo &m);
unique_ptr<TempHygroMeter> createRfmAmb(WMBus *bus, MeterInfo &m);
unique_ptr<ElectricityMeter> createEHZP(WMBus *bus, MeterInfo &m);
unique_ptr<ElectricityMeter> createESYSWM(WMBus *bus, MeterInfo &m);
GenericMeter *createGeneric(WMBus *bus, MeterInfo &m);
#endif

Wyświetl plik

@ -1305,7 +1305,15 @@ bool Telegram::parseTPLConfig(std::vector<uchar>::iterator &pos)
// If there is a tpl_counter, then use it, else use afl_counter.
input.insert(input.end(), afl_counter_b, afl_counter_b+4);
// If there is a tpl_id, then use it, else use ddl_id.
input.insert(input.end(), dll_id_b, dll_id_b+4);
if (tpl_id_found)
{
input.insert(input.end(), tpl_id_b, tpl_id_b+4);
}
else
{
input.insert(input.end(), dll_id_b, dll_id_b+4);
}
// Pad.
for (int i=0; i<7; ++i) input.insert(input.end(), 0x07);
@ -1342,6 +1350,7 @@ bool Telegram::parseShortTPL(std::vector<uchar>::iterator &pos)
bool Telegram::parseLongTPL(std::vector<uchar>::iterator &pos)
{
tpl_id_found = true;
tpl_id_b[0] = *(pos+0);
tpl_id_b[1] = *(pos+1);
tpl_id_b[2] = *(pos+2);
@ -1518,6 +1527,7 @@ bool Telegram::parseTPL(vector<uchar>::iterator &pos)
bool Telegram::parseHeader(vector<uchar> &input_frame)
{
bool ok;
explanations.clear();
frame = input_frame;
vector<uchar>::iterator pos = frame.begin();
// Parsed accumulates parsed bytes.
@ -1537,6 +1547,7 @@ bool Telegram::parseHeader(vector<uchar> &input_frame)
bool Telegram::parse(vector<uchar> &input_frame, MeterKeys *mk)
{
explanations.clear();
meter_keys = mk;
assert(meter_keys != NULL);
bool ok;
@ -1682,7 +1693,6 @@ bool Telegram::parse(vector<uchar> &input_frame, MeterKeys *mk)
void Telegram::explainParse(string intro, int from)
{
for (auto& p : explanations) {
if (p.first < from) continue;
debug("%s %02x: %s\n", intro.c_str(), p.first, p.second.c_str());
}
string hex = bin2hex(parsed);

Wyświetl plik

@ -283,6 +283,7 @@ struct Telegram
int tpl_kdf_selection {}; // 1 byte
vector<uchar> tpl_generated_key; // 16 bytes
bool tpl_id_found {}; // If set to true, then tpl_id_b contains valid values.
uchar tpl_id_b[4]; // 4 bytes
uchar tpl_mft_b[2]; // 2 bytes
uchar tpl_version; // 1 bytes