Cleanup aventieshca, aventieswm, microclima and qwater.

pull/780/head
Fredrik Öhrström 2022-12-31 16:02:46 +01:00
rodzic c2e1127caa
commit c6bf8a114e
9 zmienionych plików z 486 dodań i 668 usunięć

Wyświetl plik

@ -1,3 +1,11 @@
ATTENTION! The microclima driver has been refactored. The field device_date_time has been renamed
to meter_datetime. Also two fields related to tariffs do not occur in the actual telegrams so these
fields have been removed. The fields output has therefore been drastically changed. Use --selectfields=
to reset your setup. Historical data is now decoded and added to the json.
ATTENTION! The qwater driver has been refactored. The field device_date_time has been renamed
to meter_datetime also the due 17 date fields have been renamed. The error_code field has
disappeared since it was broken anyway and replaced with status.
ATTENTION! The sharky774 driver had a bug that triggered when the meter used Joules instead of kWh.
Also the calculated temperature difference had to be removed. You can re-add the temperature difference

Wyświetl plik

@ -285,8 +285,8 @@ telegram=|19442423850798160018A2410100133EBBD44081053F243A82A3|
# Test Aventies Water Meter
telegram=76442104710007612507727100076121042507B5006005E2E95A3C2A1279A5415E6732679B43369FD5FDDDD783EEEBB48236D34E7C94AF0A18A5FDA5F7D64111EB42D4D891622139F2952F9D12A20088DFA4CF8123871123EE1F6C1DCEA414879DDB4E05E508F1826D7EFBA6964DF804C9261EA23BBF03
{"media":"water","meter":"aventieswm","name":"Votten","id":"61070071","total_m3":466.472,"consumption_at_set_date_1_m3":465.96,"consumption_at_set_date_2_m3":458.88,"consumption_at_set_date_3_m3":449.65,"consumption_at_set_date_4_m3":442.35,"consumption_at_set_date_5_m3":431.07,"consumption_at_set_date_6_m3":423.98,"consumption_at_set_date_7_m3":415.23,"consumption_at_set_date_8_m3":409.03,"consumption_at_set_date_9_m3":400.79,"consumption_at_set_date_10_m3":393.2,"consumption_at_set_date_11_m3":388.63,"consumption_at_set_date_12_m3":379.26,"consumption_at_set_date_13_m3":371.26,"consumption_at_set_date_14_m3":357.84,"error_flags":"","timestamp":"1111-11-11T11:11:11Z"}
|Votten;61070071;466.472000;;1111-11-11 11:11.11
{"media":"water","meter":"aventieswm","name":"Votten","id":"61070071","status":"OK","total_m3":466.472,"consumption_at_set_date_1_m3":465.96,"consumption_at_set_date_2_m3":458.88,"consumption_at_set_date_3_m3":449.65,"consumption_at_set_date_4_m3":442.35,"consumption_at_set_date_5_m3":431.07,"consumption_at_set_date_6_m3":423.98,"consumption_at_set_date_7_m3":415.23,"consumption_at_set_date_8_m3":409.03,"consumption_at_set_date_9_m3":400.79,"consumption_at_set_date_10_m3":393.2,"consumption_at_set_date_11_m3":388.63,"consumption_at_set_date_12_m3":379.26,"consumption_at_set_date_13_m3":371.26,"consumption_at_set_date_14_m3":357.84,"error_flags":"","timestamp":"1111-11-11T11:11:11Z"}
|Votten;61070071;466.472;;1111-11-11 11:11.11
# Test Unismart Gas Meter
telegram=|6044B8059430040001037A1D005085E2B670BCF1A5C87E0C1A51DA18924EF984613DA2A9CD39D8F4C7208326C76D42DBEADF80D574192B71BD7C4F56A7F1513151768A9DB804883B28CB085CA2D0F7438C361CB9E2734712ED9BFBB2A14EF55208|

Wyświetl plik

@ -17,116 +17,118 @@
#include"meters_common_implementation.h"
struct MeterAventiesHCA : public virtual MeterCommonImplementation
namespace
{
MeterAventiesHCA(MeterInfo &mi, DriverInfo &di);
private:
double current_consumption_hca_ {};
double consumption_at_set_date_hca_[17] {}; // storagenr 1 to 17 are stored in index 0 to 16
string error_flags_;
};
static bool ok = registerDriver([](DriverInfo&di)
{
di.setName("aventieshca");
di.setMeterType(MeterType::HeatCostAllocationMeter);
di.addLinkMode(LinkMode::T1);
di.addDetection(MANUFACTURER_AAA, 0x08, 0x55);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new MeterAventiesHCA(mi, di)); });
});
MeterAventiesHCA::MeterAventiesHCA(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addNumericFieldWithExtractor(
"current_consumption",
Quantity::HCA,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::HeatCostAllocation,
StorageNr(0),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT,
"The current heat cost allocation.",
SET_FUNC(current_consumption_hca_, Unit::HCA),
GET_FUNC(current_consumption_hca_, Unit::HCA));
addNumericFieldWithExtractor(
"consumption_at_set_date",
Quantity::HCA,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::HeatCostAllocation,
StorageNr(1),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON,
"Heat cost allocation at the most recent billing period date.",
SET_FUNC(consumption_at_set_date_hca_[0], Unit::HCA),
GET_FUNC(consumption_at_set_date_hca_[0], Unit::HCA));
for (int i=2; i<=17; ++i)
struct Driver : public virtual MeterCommonImplementation
{
string key, info;
strprintf(&key, "consumption_at_set_date_%d", i);
strprintf(&info, "Heat cost allocation at the %d billing period date.", i);
Driver(MeterInfo &mi, DriverInfo &di);
};
static bool ok = registerDriver([](DriverInfo&di)
{
di.setName("aventieshca");
di.setDefaultFields("name,id,current_consumption_hca,error_flags,timestamp");
di.setMeterType(MeterType::HeatCostAllocationMeter);
di.addLinkMode(LinkMode::T1);
di.addDetection(MANUFACTURER_AAA, 0x08, 0x55);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
});
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addStringFieldWithExtractorAndLookup(
"status",
"Meter status from error flags and tpl status field.",
PrintProperty::JSON | PrintProperty::IMPORTANT |
PrintProperty::STATUS | PrintProperty::JOIN_TPL_STATUS,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ErrorFlags),
Translate::Lookup(
{
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
{ 0x01, "MEASUREMENT", TestBit::Set },
{ 0x02, "SABOTAGE" },
{ 0x04, "BATTERY" },
{ 0x08, "CS" },
{ 0x10, "HF" },
{ 0x20, "RESET" }
}
},
},
}));
addStringFieldWithExtractorAndLookup(
"error_flags",
"Deprecated.",
PrintProperty::JSON | PrintProperty::DEPRECATED,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ErrorFlags),
Translate::Lookup(
{
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"",
{
{ 0x01, "MEASUREMENT", TestBit::Set },
{ 0x02, "SABOTAGE" },
{ 0x04, "BATTERY" },
{ 0x08, "CS" },
{ 0x10, "HF" },
{ 0x20, "RESET" }
}
},
},
}));
addNumericFieldWithExtractor(
key,
"current_consumption",
"The current heat cost allocation.",
PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT,
Quantity::HCA,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::HeatCostAllocation,
StorageNr(i),
TariffNr(0),
IndexNr(1),
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
);
addNumericFieldWithExtractor(
"consumption_at_set_date",
"Heat cost allocation at the most recent billing period date.",
PrintProperty::JSON,
info,
SET_FUNC(consumption_at_set_date_hca_[i-1], Unit::HCA),
GET_FUNC(consumption_at_set_date_hca_[i-1], Unit::HCA));
Quantity::HCA,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
.set(StorageNr(1))
);
addNumericFieldWithExtractor(
"consumption_at_set_date_{storage_counter}",
"The heat cost allocation at set date #.",
PrintProperty::JSON,
Quantity::HCA,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
.set(StorageNr(2),StorageNr(17))
);
}
addStringFieldWithExtractorAndLookup(
"error_flags",
Quantity::Text,
DifVifKey("02FD17"),
MeasurementType::Instantaneous,
VIFRange::Any,
AnyStorageNr,
AnyTariffNr,
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD,
"Error flags.",
SET_STRING_FUNC(error_flags_),
GET_STRING_FUNC(error_flags_),
{
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"",
{
{ 0x01, "MEASUREMENT", TestBit::Set },
{ 0x02, "SABOTAGE" },
{ 0x04, "BATTERY" },
{ 0x08, "CS" },
{ 0x10, "HF" },
{ 0x20, "RESET" }
}
},
},
}
);
}
// Test: HCA aventieshca 60900126 NOKEY
// telegram=|76442104260190605508722601906021045508060060052F2F#0B6E660100426EA60082016EA600C2016E9E0082026E7E00C2026E5B0082036E4200C2036E770182046E5B01C2046E4C0182056E4701C2056E3E0182066E3B01C2066E3B0182076E3B01C2076E3B0182086E1301C2086E9C0002FD170000|
// {"media":"heat cost allocation","meter":"aventieshca","name":"HCA","id":"60900126","current_consumption_hca":166,"consumption_at_set_date_hca":166,"consumption_at_set_date_2_hca":166,"consumption_at_set_date_3_hca":158,"consumption_at_set_date_4_hca":126,"consumption_at_set_date_5_hca":91,"consumption_at_set_date_6_hca":66,"consumption_at_set_date_7_hca":375,"consumption_at_set_date_8_hca":347,"consumption_at_set_date_9_hca":332,"consumption_at_set_date_10_hca":327,"consumption_at_set_date_11_hca":318,"consumption_at_set_date_12_hca":315,"consumption_at_set_date_13_hca":315,"consumption_at_set_date_14_hca":315,"consumption_at_set_date_15_hca":315,"consumption_at_set_date_16_hca":275,"consumption_at_set_date_17_hca":156,"error_flags":"","timestamp":"1111-11-11T11:11:11Z"}
// |HCA;60900126;166.000000;;1111-11-11 11:11.11
// {"media":"heat cost allocation","meter":"aventieshca","name":"HCA","id":"60900126","status":"OK","current_consumption_hca":166,"consumption_at_set_date_hca":166,"consumption_at_set_date_2_hca":166,"consumption_at_set_date_3_hca":158,"consumption_at_set_date_4_hca":126,"consumption_at_set_date_5_hca":91,"consumption_at_set_date_6_hca":66,"consumption_at_set_date_7_hca":375,"consumption_at_set_date_8_hca":347,"consumption_at_set_date_9_hca":332,"consumption_at_set_date_10_hca":327,"consumption_at_set_date_11_hca":318,"consumption_at_set_date_12_hca":315,"consumption_at_set_date_13_hca":315,"consumption_at_set_date_14_hca":315,"consumption_at_set_date_15_hca":315,"consumption_at_set_date_16_hca":275,"consumption_at_set_date_17_hca":156,"error_flags":"","timestamp":"1111-11-11T11:11:11Z"}
// |HCA;60900126;166;;1111-11-11 11:11.11

Wyświetl plik

@ -17,107 +17,114 @@
#include"meters_common_implementation.h"
using namespace std;
struct MeterAventiesWM : public virtual MeterCommonImplementation
namespace
{
MeterAventiesWM(MeterInfo &mi, DriverInfo &di);
private:
double total_water_consumption_m3_ {};
double consumption_at_set_date_m3_[14];
string error_flags_;
};
static bool ok = registerDriver([](DriverInfo&di)
{
di.setName("aventieswm");
di.setMeterType(MeterType::WaterMeter);
di.addLinkMode(LinkMode::T1);
di.addDetection(MANUFACTURER_AAA, 0x07, 0x25);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new MeterAventiesWM(mi, di)); });
});
MeterAventiesWM::MeterAventiesWM(MeterInfo &mi, DriverInfo &di) :
MeterCommonImplementation(mi, di)
{
addNumericFieldWithExtractor(
"total",
Quantity::Volume,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::Volume,
StorageNr(0),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT,
"The total water consumption recorded by this meter.",
SET_FUNC(total_water_consumption_m3_, Unit::M3),
GET_FUNC(total_water_consumption_m3_, Unit::M3));
for (int i=1; i<=14; ++i)
struct Driver : public virtual MeterCommonImplementation
{
string msg, info;
strprintf(&msg, "consumption_at_set_date_%d", i);
strprintf(&info, "Water consumption at the %d billing period date.", i);
addNumericFieldWithExtractor(
msg,
Quantity::Volume,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::Volume,
StorageNr(i),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON,
info,
SET_FUNC(consumption_at_set_date_m3_[i-1], Unit::M3),
GET_FUNC(consumption_at_set_date_m3_[i-1], Unit::M3));
}
Driver(MeterInfo &mi, DriverInfo &di);
};
addStringFieldWithExtractorAndLookup(
"error_flags",
Quantity::Text,
DifVifKey("02FD17"),
MeasurementType::Instantaneous,
VIFRange::Any,
AnyStorageNr,
AnyTariffNr,
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD,
"Error flags.",
SET_STRING_FUNC(error_flags_),
GET_STRING_FUNC(error_flags_),
{
{
static bool ok = registerDriver([](DriverInfo&di)
{
di.setName("aventieswm");
di.setDefaultFields("name,id,total_m3,error_flags,timestamp");
di.setMeterType(MeterType::WaterMeter);
di.addLinkMode(LinkMode::T1);
di.addDetection(MANUFACTURER_AAA, 0x07, 0x25);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
});
Driver::Driver(MeterInfo &mi, DriverInfo &di) :
MeterCommonImplementation(mi, di)
{
addStringFieldWithExtractorAndLookup(
"status",
"Meter status from error flags and tpl status field.",
PrintProperty::JSON | PrintProperty::IMPORTANT |
PrintProperty::STATUS | PrintProperty::JOIN_TPL_STATUS,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ErrorFlags),
Translate::Lookup(
{
"ERROR_FLAGS",
Translate::Type::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"",
{
{ 0x01, "MEASUREMENT" },
{ 0x02, "SABOTAGE" },
{ 0x04, "BATTERY" },
{ 0x08, "CS" },
{ 0x10, "HF" },
{ 0x20, "RESET" }
}
},
},
});
{
"ERROR_FLAGS",
Translate::Type::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
{ 0x01, "MEASUREMENT", TestBit::Set },
{ 0x02, "SABOTAGE" },
{ 0x04, "BATTERY" },
{ 0x08, "CS" },
{ 0x10, "HF" },
{ 0x20, "RESET" }
}
},
},
}));
addNumericFieldWithExtractor(
"total",
"The total water consumption recorded by this meter.",
PrintProperty::JSON | PrintProperty::IMPORTANT,
Quantity::Volume,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
);
addNumericFieldWithExtractor(
"consumption_at_set_date_{storage_counter}",
"Water consumption at the # billing period date.",
PrintProperty::JSON,
Quantity::Volume,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
.set(StorageNr(1),StorageNr(14))
);
addStringFieldWithExtractorAndLookup(
"error_flags",
"Deprecated.",
PrintProperty::JSON | PrintProperty::DEPRECATED,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ErrorFlags),
Translate::Lookup(
{
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"",
{
{ 0x01, "MEASUREMENT", TestBit::Set },
{ 0x02, "SABOTAGE" },
{ 0x04, "BATTERY" },
{ 0x08, "CS" },
{ 0x10, "HF" },
{ 0x20, "RESET" }
}
},
},
}));
}
}
// Test: Votten aventieswm 61070071 A004EB23329A477F1DD2D7820B56EB3D
// telegram=76442104710007612507727100076121042507B5006005E2E95A3C2A1279A5415E6732679B43369FD5FDDDD783EEEBB48236D34E7C94AF0A18A5FDA5F7D64111EB42D4D891622139F2952F9D12A20088DFA4CF8123871123EE1F6C1DCEA414879DDB4E05E508F1826D7EFBA6964DF804C9261EA23BBF03
// {"media":"water","meter":"aventieswm","name":"Votten","id":"61070071","total_m3":466.472,"consumption_at_set_date_1_m3":465.96,"consumption_at_set_date_2_m3":458.88,"consumption_at_set_date_3_m3":449.65,"consumption_at_set_date_4_m3":442.35,"consumption_at_set_date_5_m3":431.07,"consumption_at_set_date_6_m3":423.98,"consumption_at_set_date_7_m3":415.23,"consumption_at_set_date_8_m3":409.03,"consumption_at_set_date_9_m3":400.79,"consumption_at_set_date_10_m3":393.2,"consumption_at_set_date_11_m3":388.63,"consumption_at_set_date_12_m3":379.26,"consumption_at_set_date_13_m3":371.26,"consumption_at_set_date_14_m3":357.84,"error_flags":"","timestamp":"1111-11-11T11:11:11Z"}
// |Votten;61070071;466.472000;;1111-11-11 11:11.11
// {"media":"water","meter":"aventieswm","name":"Votten","id":"61070071","total_m3":466.472,"consumption_at_set_date_1_m3":465.96,"consumption_at_set_date_2_m3":458.88,"consumption_at_set_date_3_m3":449.65,"consumption_at_set_date_4_m3":442.35,"consumption_at_set_date_5_m3":431.07,"consumption_at_set_date_6_m3":423.98,"consumption_at_set_date_7_m3":415.23,"consumption_at_set_date_8_m3":409.03,"consumption_at_set_date_9_m3":400.79,"consumption_at_set_date_10_m3":393.2,"consumption_at_set_date_11_m3":388.63,"consumption_at_set_date_12_m3":379.26,"consumption_at_set_date_13_m3":371.26,"consumption_at_set_date_14_m3":357.84,"status":"OK","error_flags":"","timestamp":"1111-11-11T11:11:11Z"}
// |Votten;61070071;466.472;;1111-11-11 11:11.11
// Test: Vatten aventieswm 61070072 NOKEY
// telegram=76442104720007612507727200076121042507B50060052F2F0413281E0700431404B60083011440B300C30114A5AF00830214CBAC00C3021463A8008303149EA500C3031433A200830414C79F00C304148F9C00830514989900C30514CF9700830614269400C30614069100830714C88B0002FD171111
// {"media":"water","meter":"aventieswm","name":"Vatten","id":"61070072","total_m3":466.472,"consumption_at_set_date_1_m3":465.96,"consumption_at_set_date_2_m3":458.88,"consumption_at_set_date_3_m3":449.65,"consumption_at_set_date_4_m3":442.35,"consumption_at_set_date_5_m3":431.07,"consumption_at_set_date_6_m3":423.98,"consumption_at_set_date_7_m3":415.23,"consumption_at_set_date_8_m3":409.03,"consumption_at_set_date_9_m3":400.79,"consumption_at_set_date_10_m3":393.2,"consumption_at_set_date_11_m3":388.63,"consumption_at_set_date_12_m3":379.26,"consumption_at_set_date_13_m3":371.26,"consumption_at_set_date_14_m3":357.84,"error_flags":"ERROR_FLAGS_1100 HF MEASUREMENT","timestamp":"1111-11-11T11:11:11Z"}
// |Vatten;61070072;466.472000;ERROR_FLAGS_1100 HF MEASUREMENT;1111-11-11 11:11.11
// {"media":"water","meter":"aventieswm","name":"Vatten","id":"61070072","total_m3":466.472,"consumption_at_set_date_1_m3":465.96,"consumption_at_set_date_2_m3":458.88,"consumption_at_set_date_3_m3":449.65,"consumption_at_set_date_4_m3":442.35,"consumption_at_set_date_5_m3":431.07,"consumption_at_set_date_6_m3":423.98,"consumption_at_set_date_7_m3":415.23,"consumption_at_set_date_8_m3":409.03,"consumption_at_set_date_9_m3":400.79,"consumption_at_set_date_10_m3":393.2,"consumption_at_set_date_11_m3":388.63,"consumption_at_set_date_12_m3":379.26,"consumption_at_set_date_13_m3":371.26,"consumption_at_set_date_14_m3":357.84,"status":"ERROR_FLAGS_1100 HF MEASUREMENT","error_flags":"ERROR_FLAGS_1100 HF MEASUREMENT","timestamp":"1111-11-11T11:11:11Z"}
// |Vatten;61070072;466.472;ERROR_FLAGS_1100 HF MEASUREMENT;1111-11-11 11:11.11

Wyświetl plik

@ -17,224 +17,157 @@
#include"meters_common_implementation.h"
struct MeterMicroClima : public virtual MeterCommonImplementation
namespace
{
MeterMicroClima(MeterInfo &mi, DriverInfo &di);
struct Driver : public virtual MeterCommonImplementation
{
Driver(MeterInfo &mi, DriverInfo &di);
};
private:
double total_energy_kwh_ {};
double total_energy_tariff1_kwh_ {};
double total_volume_m3_ {};
double total_volume_tariff2_m3_ {};
double volume_flow_m3h_ {};
double power_kw_ {};
double flow_temperature_c_ {};
double return_temperature_c_ {};
double temperature_difference_k_ {};
string status_;
string device_date_time_;
};
static bool ok = registerDriver([](DriverInfo&di)
{
di.setName("microclima");
di.setDefaultFields("name,id,status,total_energy_consumption_kwh,total_volume_m3,timestamp");
di.setMeterType(MeterType::HeatMeter);
di.addLinkMode(LinkMode::T1);
di.addDetection(MANUFACTURER_MAD, 0x04, 0x00);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
});
static bool ok = registerDriver([](DriverInfo&di)
{
di.setName("microclima");
di.setMeterType(MeterType::HeatMeter);
di.addLinkMode(LinkMode::T1);
di.addDetection(MANUFACTURER_MAD, 0x04, 0x00);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new MeterMicroClima(mi, di)); });
});
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addOptionalCommonFields("meter_datetime,model_version,parameter_set");
addOptionalFlowRelatedFields("flow_temperature_c,return_temperature_c");
MeterMicroClima::MeterMicroClima(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addNumericFieldWithExtractor(
"total_energy_consumption",
Quantity::Energy,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::EnergyWh,
StorageNr(0),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT,
"The total heat energy consumption recorded by this meter.",
SET_FUNC(total_energy_kwh_, Unit::KWH),
GET_FUNC(total_energy_kwh_, Unit::KWH));
addNumericFieldWithExtractor(
"total_energy_consumption_tariff1",
Quantity::Energy,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::EnergyWh,
StorageNr(0),
TariffNr(1),
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD,
"The total heat energy consumption recorded by this meter on tariff 1.",
SET_FUNC(total_energy_tariff1_kwh_, Unit::KWH),
GET_FUNC(total_energy_tariff1_kwh_, Unit::KWH));
addNumericFieldWithExtractor(
"total_volume",
Quantity::Volume,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::Volume,
StorageNr(0),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD,
"The total heating media volume recorded by this meter.",
SET_FUNC(total_volume_m3_, Unit::M3),
GET_FUNC(total_volume_m3_, Unit::M3));
addNumericFieldWithExtractor(
"total_volume_tariff2",
Quantity::Volume,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::Volume,
StorageNr(0),
TariffNr(2),
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD,
"The total heating media volume recorded by this meter on tariff 2.",
SET_FUNC(total_volume_tariff2_m3_, Unit::M3),
GET_FUNC(total_volume_tariff2_m3_, Unit::M3));
addNumericFieldWithExtractor(
"volume_flow",
Quantity::Flow,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::VolumeFlow,
StorageNr(0),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD,
"The current heat media volume flow.",
SET_FUNC(volume_flow_m3h_, Unit::M3H),
GET_FUNC(volume_flow_m3h_, Unit::M3H));
addNumericFieldWithExtractor(
"power",
Quantity::Power,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::PowerW,
StorageNr(0),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD,
"The current power consumption.",
SET_FUNC(power_kw_, Unit::KW),
GET_FUNC(power_kw_, Unit::KW));
addNumericFieldWithExtractor(
"flow_temperature",
Quantity::Temperature,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::FlowTemperature,
StorageNr(0),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD,
"The current forward heat media temperature.",
SET_FUNC(flow_temperature_c_, Unit::C),
GET_FUNC(flow_temperature_c_, Unit::C));
addNumericFieldWithExtractor(
"return_temperature",
Quantity::Temperature,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::ReturnTemperature,
StorageNr(0),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD,
"The current return heat media temperature.",
SET_FUNC(return_temperature_c_, Unit::C),
GET_FUNC(return_temperature_c_, Unit::C));
addNumericFieldWithExtractor(
"temperature_difference",
Quantity::Temperature,
NoDifVifKey,
VifScaling::AutoSigned,
MeasurementType::Instantaneous,
VIFRange::TemperatureDifference,
StorageNr(0),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD,
"The current return heat media temperature.",
SET_FUNC(temperature_difference_k_, Unit::K),
GET_FUNC(temperature_difference_k_, Unit::K));
addStringFieldWithExtractorAndLookup(
"status",
Quantity::Text,
DifVifKey("01FD17"),
MeasurementType::Instantaneous,
VIFRange::Any,
AnyStorageNr,
AnyTariffNr,
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD,
"Error flags.",
SET_STRING_FUNC(status_),
GET_STRING_FUNC(status_),
{
{
addStringFieldWithExtractorAndLookup(
"status",
"Meter status from error flags and tpl status field.",
PrintProperty::JSON | PrintProperty::IMPORTANT |
PrintProperty::STATUS | PrintProperty::JOIN_TPL_STATUS,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ErrorFlags),
Translate::Lookup(
{
"ERROR_FLAGS",
Translate::Type::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
{ 0x01, "?" },
}
},
},
});
{
"ERROR_FLAGS",
Translate::Type::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
}
},
},
}));
addStringFieldWithExtractor(
"device_date_time",
Quantity::Text,
NoDifVifKey,
MeasurementType::Instantaneous,
VIFRange::DateTime,
StorageNr(0),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON,
"Device date time.",
SET_STRING_FUNC(device_date_time_),
GET_STRING_FUNC(device_date_time_));
addNumericFieldWithExtractor(
"total_energy_consumption",
"The total heat energy consumption recorded by this meter.",
PrintProperty::JSON | PrintProperty::IMPORTANT,
Quantity::Energy,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
);
addNumericFieldWithExtractor(
"total_volume",
"The total heating media volume recorded by this meter.",
PrintProperty::JSON,
Quantity::Volume,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
);
addNumericFieldWithExtractor(
"volume_flow",
"The current heat media volume flow.",
PrintProperty::JSON | PrintProperty::OPTIONAL,
Quantity::Flow,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow)
);
addNumericFieldWithExtractor(
"power",
"The current power consumption.",
PrintProperty::JSON | PrintProperty::OPTIONAL,
Quantity::Power,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::PowerW)
);
addNumericFieldWithExtractor(
"temperature_difference",
"The difference between flow and return media temperatures.",
PrintProperty::JSON | PrintProperty::OPTIONAL,
Quantity::Temperature,
VifScaling::AutoSigned,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::TemperatureDifference)
);
addNumericFieldWithExtractor(
"set",
"The most recent billing period date.",
PrintProperty::JSON | PrintProperty::OPTIONAL | PrintProperty::HIDE,
Quantity::PointInTime,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Date)
.set(StorageNr(1)),
Unit::DateLT
);
addNumericFieldWithExtractor(
"consumption_at_set_date_{storage_counter}",
"The total water consumption at the historic date.",
PrintProperty::JSON | PrintProperty::OPTIONAL,
Quantity::Energy,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
.set(StorageNr(1),StorageNr(31))
);
addNumericFieldWithCalculatorAndMatcher(
"set_date_{storage_counter}",
"Unclear! What is the date really?",
PrintProperty::JSON | PrintProperty::OPTIONAL,
Quantity::PointInTime,
"set_date - ((storage_counter-1counter) * 1 month)",
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
.set(StorageNr(1),StorageNr(31)),
Unit::DateLT
);
}
}
// The meter sends two types of telegrams a shorter with current values.
// Test: Heat microclima 93572431 NOKEY
// telegram=|494424343124579300047a5a0000202f2f046d2720b62c04060d07000001fd170004130a8c0400043b00000000042b00000000025b1500025f15000261d0ff03fd0c05000002fd0b1011|
// {"media":"heat","meter":"microclima","name":"Heat","id":"93572431","total_energy_consumption_kwh":1805,"total_energy_consumption_tariff1_kwh":0,"total_volume_m3":297.994,"total_volume_tariff2_m3":0,"volume_flow_m3h":0,"power_kw":0,"flow_temperature_c":21,"return_temperature_c":21,"temperature_difference_c":-0.48,"status":"OK","device_date_time":"2021-12-22 00:39","timestamp":"1111-11-11T11:11:11Z"}
// |Heat;93572431;1805.000000;0.000000;297.994000;0.000000;0.000000;0.000000;21.000000;21.000000;-0.480000;OK;1111-11-11 11:11.11
// {"flow_temperature_c":21,"id":"93572431","media":"heat","meter":"microclima","meter_datetime":"2021-12-22 00:39","model_version":"000005","name":"Heat","parameter_set":"1110","power_kw":0,"return_temperature_c":21,"status":"OK","temperature_difference_c":-0.48,"timestamp":"1111-11-11T11:11:11Z","total_energy_consumption_kwh":1805,"total_volume_m3":297.994,"volume_flow_m3h":0}
// |Heat;93572431;OK;1805;297.994;1111-11-11 11:11.11
// And a longer with historical values. This telegram is not yet properly decoded.
// Test: Heat microclima 93573086 NOKEY
// telegram=|A44424348630579300047ADD0000202F2F046D0721B62C04064708000004135DB0030001FD1700426C9F2C4406C6040000C40106C0070000C4020637070000C4030611070000C404060B070000C405060B070000C406060B070000C407060B070000C40806A5060000C40906F7050000C40A067A050000C40B060F050000C40C06C6040000C40D063F040000C40E06BB030000C40F06A502000003FD0C05000002FD0B1111|
// {"media":"heat","meter":"microclima","name":"Heat","id":"93573086","total_energy_consumption_kwh":2119,"total_energy_consumption_tariff1_kwh":0,"total_volume_m3":241.757,"total_volume_tariff2_m3":0,"volume_flow_m3h":0,"power_kw":0,"flow_temperature_c":0,"return_temperature_c":0,"temperature_difference_c":-273.15,"status":"OK","device_date_time":"2021-12-22 01:07","timestamp":"1111-11-11T11:11:11Z"}
// |Heat;93573086;2119.000000;0.000000;241.757000;0.000000;0.000000;0.000000;0.000000;0.000000;-273.150000;OK;1111-11-11 11:11.11
// {"consumption_at_set_date_11_kwh":1803,"consumption_at_set_date_13_kwh":1803,"consumption_at_set_date_15_kwh":1803,"consumption_at_set_date_17_kwh":1701,"consumption_at_set_date_19_kwh":1527,"consumption_at_set_date_1_kwh":1222,"consumption_at_set_date_21_kwh":1402,"consumption_at_set_date_23_kwh":1295,"consumption_at_set_date_25_kwh":1222,"consumption_at_set_date_27_kwh":1087,"consumption_at_set_date_29_kwh":955,"consumption_at_set_date_31_kwh":677,"consumption_at_set_date_3_kwh":1984,"consumption_at_set_date_5_kwh":1847,"consumption_at_set_date_7_kwh":1809,"consumption_at_set_date_9_kwh":1803,"id":"93573086","media":"heat","meter":"microclima","meter_datetime":"2021-12-22 01:07","model_version":"000005","name":"Heat","parameter_set":"1111","set_date_11_date":"2020-02-29","set_date_13_date":"2019-12-31","set_date_15_date":"2019-10-31","set_date_17_date":"2019-08-31","set_date_19_date":"2019-06-30","set_date_1_date":"2020-12-31","set_date_21_date":"2019-04-30","set_date_23_date":"2019-02-28","set_date_25_date":"2018-12-31","set_date_27_date":"2018-10-31","set_date_29_date":"2018-08-31","set_date_31_date":"2018-06-30","set_date_3_date":"2020-10-31","set_date_5_date":"2020-08-31","set_date_7_date":"2020-06-30","set_date_9_date":"2020-04-30","status":"OK","timestamp":"1111-11-11T11:11:11Z","total_energy_consumption_kwh":2119,"total_volume_m3":241.757}
// |Heat;93573086;OK;2119;241.757;1111-11-11 11:11.11

Wyświetl plik

@ -17,193 +17,140 @@
#include"meters_common_implementation.h"
using namespace std;
struct MeterQWater : public virtual MeterCommonImplementation
namespace
{
MeterQWater(MeterInfo &mi, DriverInfo &di);
struct Driver : public virtual MeterCommonImplementation
{
Driver(MeterInfo &mi, DriverInfo &di);
};
double total_water_consumption_m3_ {};
static bool ok = registerDriver([](DriverInfo&di)
{
di.setName("qwater");
di.setDefaultFields("name,id,total_m3,"
"due_date_m3,"
"due_date,"
"status,"
"timestamp");
di.setMeterType(MeterType::WaterMeter);
di.addLinkMode(LinkMode::S1);
di.addDetection(MANUFACTURER_QDS, 0x37, 0x33);
di.addDetection(MANUFACTURER_QDS, 0x06, 0x18);
di.addDetection(MANUFACTURER_QDS, 0x07, 0x18);
di.addDetection(MANUFACTURER_QDS, 0x06, 0x35);
di.addDetection(MANUFACTURER_QDS, 0x07, 0x35);
double due_date_water_consumption_m3_ {};
string due_date_ {};
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
});
double due_date_17_water_consumption_m3_ {};
string due_date_17_ {};
Driver::Driver(MeterInfo &mi, DriverInfo &di) :
MeterCommonImplementation(mi, di)
{
addOptionalCommonFields("meter_datetime");
addOptionalFlowRelatedFields("total_m3");
string error_code_ {};
string error_date_ {};
addStringField(
"status",
"Meter status tpl status field.",
PrintProperty::JSON | PrintProperty::IMPORTANT | PrintProperty::STATUS | PrintProperty::JOIN_TPL_STATUS);
string device_date_time_ {};
};
addNumericFieldWithExtractor(
"due_date",
"The water consumption at the due date.",
PrintProperty::JSON | PrintProperty::OPTIONAL,
Quantity::Volume,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
.set(StorageNr(1))
);
static bool ok = registerDriver([](DriverInfo&di)
{
di.setName("qwater");
di.setMeterType(MeterType::WaterMeter);
di.addLinkMode(LinkMode::S1);
di.addDetection(MANUFACTURER_QDS, 0x37, 0x33);
di.addDetection(MANUFACTURER_QDS, 0x06, 0x18);
di.addDetection(MANUFACTURER_QDS, 0x07, 0x18);
di.addDetection(MANUFACTURER_QDS, 0x06, 0x35);
di.addDetection(MANUFACTURER_QDS, 0x07, 0x35);
addNumericFieldWithExtractor(
"due",
"The due date for billing date.",
PrintProperty::JSON | PrintProperty::OPTIONAL,
Quantity::PointInTime,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Date)
.set(StorageNr(1)),
Unit::DateLT
);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new MeterQWater(mi, di)); });
});
addNumericFieldWithExtractor(
"due_17_date",
"The water consumption at the 17 due date.",
PrintProperty::JSON | PrintProperty::OPTIONAL,
Quantity::Volume,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
.set(StorageNr(17))
);
MeterQWater::MeterQWater(MeterInfo &mi, DriverInfo &di) :
MeterCommonImplementation(mi, di)
{
addNumericFieldWithExtractor(
"total",
Quantity::Volume,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::Volume,
StorageNr(0),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT,
"The total water consumption recorded by this meter.",
SET_FUNC(total_water_consumption_m3_, Unit::M3),
GET_FUNC(total_water_consumption_m3_, Unit::M3));
addNumericFieldWithExtractor(
"due_17",
"The due date for billing date.",
PrintProperty::JSON | PrintProperty::OPTIONAL,
Quantity::PointInTime,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Date)
.set(StorageNr(17)),
Unit::DateLT
);
addNumericFieldWithExtractor(
"due_date",
Quantity::Volume,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::Volume,
StorageNr(1),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD | PrintProperty::IMPORTANT,
"The water consumption at the due date.",
SET_FUNC(due_date_water_consumption_m3_, Unit::M3),
GET_FUNC(due_date_water_consumption_m3_, Unit::M3));
addNumericFieldWithExtractor(
"volume_flow",
"Media volume flow when duration exceeds lower last.",
PrintProperty::JSON | PrintProperty::OPTIONAL,
Quantity::Flow,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow)
.add(VIFCombinable::DurationExceedsLowerLast)
);
addStringFieldWithExtractor(
"due_date",
Quantity::Text,
NoDifVifKey,
MeasurementType::Instantaneous,
VIFRange::Date,
StorageNr(1),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD,
"The due date configured on the meter.",
SET_STRING_FUNC(due_date_),
GET_STRING_FUNC(due_date_));
addNumericFieldWithExtractor(
"due_date_17",
Quantity::Volume,
NoDifVifKey,
VifScaling::Auto,
MeasurementType::Instantaneous,
VIFRange::Volume,
StorageNr(17),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON,
"The water consumption at the 17th historical due date.",
SET_FUNC(due_date_17_water_consumption_m3_, Unit::M3),
GET_FUNC(due_date_17_water_consumption_m3_, Unit::M3));
addStringFieldWithExtractor(
"due_date_17",
Quantity::Text,
NoDifVifKey,
MeasurementType::Instantaneous,
VIFRange::Date,
StorageNr(17),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON,
"The due date configured for the 17th historical value.",
SET_STRING_FUNC(due_date_17_),
GET_STRING_FUNC(due_date_17_));
addStringFieldWithExtractorAndLookup(
"error_code",
Quantity::Text,
DifVifKey("02BB56"),
MeasurementType::Instantaneous,
VIFRange::Any,
AnyStorageNr,
AnyTariffNr,
IndexNr(1),
PrintProperty::JSON | PrintProperty::FIELD,
"Error code of the Meter, 0 means no error.",
SET_STRING_FUNC(error_code_),
GET_STRING_FUNC(error_code_),
{
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
{ 0x01, "?" },
}
},
},
});
addStringFieldWithExtractor(
"error_date",
Quantity::Text,
NoDifVifKey,
MeasurementType::AtError,
VIFRange::Date,
StorageNr(0),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON,
"The date the error occured at. If no error, reads 2127-15-31 (FFFF).",
SET_STRING_FUNC(error_date_),
GET_STRING_FUNC(error_date_));
addStringFieldWithExtractor(
"device_date_time",
Quantity::Text,
NoDifVifKey,
MeasurementType::Instantaneous,
VIFRange::DateTime,
StorageNr(0),
TariffNr(0),
IndexNr(1),
PrintProperty::JSON,
"Date when measurement was recorded.",
SET_STRING_FUNC(device_date_time_),
GET_STRING_FUNC(device_date_time_));
addNumericFieldWithExtractor(
"error",
"The date the error occured at. If no error, reads 2127-15-31 (FFFF).",
PrintProperty::JSON | PrintProperty::OPTIONAL,
Quantity::PointInTime,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::AtError)
.set(VIFRange::Date),
Unit::DateLT
);
}
}
// Test: MyQWater qwater 12353648 NOKEY
// telegram=|374493444836351218067ac70000200c13911900004c1391170000426cbf2ccc081391170000c2086cbf2c02bb560000326cffff046d1e02de21fed0|
// {"media":"warm water","meter":"qwater","name":"MyQWater","id":"12353648","total_m3":1.991,"due_date_m3":1.791,"due_date":"2021-12-31","due_date_17_m3":1.791,"due_date_17":"2021-12-31","error_code":"OK","error_date":"2127-15-31","device_date_time":"2022-01-30 02:30","timestamp":"1111-11-11T11:11:11Z"}
// |MyQWater;12353648;1.991000;1.791000;2021-12-31;OK;1111-11-11 11:11.11
// {"media":"warm water","meter":"qwater","name":"MyQWater","id":"12353648","status":"OK","total_m3":1.991,"due_date_m3":1.791,"due_date":"2021-12-31","due_17_date_m3":1.791,"due_17_date":"2021-12-31","error_date":"2128-03-31","volume_flow_m3h":0,"meter_datetime":"2022-01-30 02:30","timestamp":"1111-11-11T11:11:11Z"}
// |MyQWater;12353648;1.991;1.791;2021-12-31;OK;1111-11-11 11:11.11
// And a second telegram that only updates the device date time.
// telegram=|47449344483635121806780dff5f350082da0000600107c113ffff48200000bf2c91170000df2120200000008001000000060019001000160018000d001300350017002f046d370cc422c759|
// {"media":"warm water","meter":"qwater","name":"MyQWater","id":"12353648","total_m3":1.991,"due_date_m3":1.791,"due_date":"2021-12-31","due_date_17_m3":1.791,"due_date_17":"2021-12-31","error_code":"OK","error_date":"2127-15-31","device_date_time":"2022-02-04 12:55","timestamp":"1111-11-11T11:11:11Z"}
// |MyQWater;12353648;1.991000;1.791000;2021-12-31;OK;1111-11-11 11:11.11
// {"media":"warm water","meter":"qwater","name":"MyQWater","id":"12353648","status":"OK","total_m3":1.991,"due_date_m3":1.791,"due_date":"2021-12-31","due_17_date_m3":1.791,"due_17_date":"2021-12-31","error_date":"2128-03-31","volume_flow_m3h":0,"meter_datetime":"2022-02-04 12:55","timestamp":"1111-11-11T11:11:11Z"}
// |MyQWater;12353648;1.991;1.791;2021-12-31;OK;1111-11-11 11:11.11
// Test: AnotherQWater qwater 66666666 NOKEY
// telegram=3C449344682268363537726666666693443507720000200C13670512004C1361100300426CBF2CCC081344501100C2086CDF28326CFFFF046D0813CF29
// {"media":"water","meter":"qwater","name":"AnotherQWater","id":"66666666","total_m3":120.567,"due_date_m3":31.061,"due_date":"2021-12-31","due_date_17_m3":115.044,"due_date_17":"2022-08-31","error_code":"","error_date":"2127-15-31","device_date_time":"2022-09-15 19:08","timestamp":"1111-11-11T11:11:11Z"}
// |AnotherQWater;66666666;120.567000;31.061000;2021-12-31;;1111-11-11 11:11.11
// telegram=|3C449344682268363537726666666693443507720000200C13670512004C1361100300426CBF2CCC081344501100C2086CDF28326CFFFF046D0813CF29|
// {"media":"water","meter":"qwater","name":"AnotherQWater","id":"66666666","status":"OK","total_m3":120.567,"due_date_m3":31.061,"due_date":"2021-12-31","due_17_date_m3":115.044,"due_17_date":"2022-08-31","error_date":"2128-03-31","meter_datetime":"2022-09-15 19:08","timestamp":"1111-11-11T11:11:11Z"}
// |AnotherQWater;66666666;120.567;31.061;2021-12-31;OK;1111-11-11 11:11.11
// Test: YetAnoter qwater 33333333 NOKEY
// telegram=3C449344333333333537723333333393443506B8000020_0C13350000004C1300000000426CBF2CCC081300000000C2086CDF25326CFFFF046D0516CE26
// {"media":"warm water","meter":"qwater","name":"YetAnoter","id":"33333333","total_m3":0.035,"due_date_m3":0,"due_date":"2021-12-31","due_date_17_m3":0,"due_date_17":"2022-05-31","error_code":"","error_date":"2127-15-31","device_date_time":"2022-06-14 22:05","timestamp":"1111-11-11T11:11:11Z"}
// |YetAnoter;33333333;0.035000;0.000000;2021-12-31;;1111-11-11 11:11.11
// telegram=|3C449344333333333537723333333393443506B8000020_0C13350000004C1300000000426CBF2CCC081300000000C2086CDF25326CFFFF046D0516CE26|
// {"media":"warm water","meter":"qwater","name":"YetAnoter","id":"33333333","status":"OK","total_m3":0.035,"due_date_m3":0,"due_date":"2021-12-31","due_17_date_m3":0,"due_17_date":"2022-05-31","error_date":"2128-03-31","meter_datetime":"2022-06-14 22:05","timestamp":"1111-11-11T11:11:11Z"}
// |YetAnoter;33333333;0.035;0;2021-12-31;OK;1111-11-11 11:11.11
// Test: QWater-7-18 qwater 12230094 NOKEY
// telegram=394493449400231218077ad30000200c13536712004c1307920500426cBf2ccc081373621200c2086cde2B02BB560000326cffff046d3714c32c
// {"media":"water","meter":"qwater","name":"QWater-7-18","id":"12230094","total_m3":126.753,"due_date_m3":59.207,"due_date":"2021-12-31","due_date_17_m3":126.273,"due_date_17":"2022-11-30","error_code":"OK","error_date":"2127-15-31","device_date_time":"2022-12-03 20:55","timestamp":"1111-11-11T11:11:11Z"}
// |QWater-7-18;12230094;126.753000;59.207000;2021-12-31;OK;1111-11-11 11:11.11
// telegram=|394493449400231218077ad30000200c13536712004c1307920500426cBf2ccc081373621200c2086cde2B02BB560000326cffff046d3714c32c|
// {"media":"water","meter":"qwater","name":"QWater-7-18","id":"12230094","status":"OK","total_m3":126.753,"due_date_m3":59.207,"due_date":"2021-12-31","due_17_date_m3":126.273,"due_17_date":"2022-11-30","error_date":"2128-03-31","volume_flow_m3h":0,"meter_datetime":"2022-12-03 20:55","timestamp":"1111-11-11T11:11:11Z"}
// |QWater-7-18;12230094;126.753;59.207;2021-12-31;OK;1111-11-11 11:11.11

Wyświetl plik

@ -366,39 +366,6 @@ void MeterCommonImplementation::addPrint(string vname, Quantity vquantity,
));
}
void MeterCommonImplementation::addNumericFieldWithExtractor(
string vname,
Quantity vquantity,
DifVifKey dif_vif_key,
VifScaling vif_scaling,
MeasurementType mt,
VIFRange vi,
StorageNr s,
TariffNr t,
IndexNr i,
PrintProperties print_properties,
string help,
function<void(Unit,double)> setValueFunc,
function<double(Unit)> getValueFunc)
{
field_infos_.emplace_back(
FieldInfo(field_infos_.size(),
vname,
vquantity,
defaultUnitForQuantity(vquantity),
vif_scaling,
FieldMatcher::build().set(dif_vif_key).set(mt).set(vi).set(s).set(t).set(i),
help,
print_properties,
getValueFunc,
NULL,
setValueFunc,
NULL,
NoLookup, /* Lookup table */
NULL /* Formula */
));
}
void MeterCommonImplementation::addNumericFieldWithExtractor(string vname,
string help,
PrintProperties print_properties,
@ -553,38 +520,6 @@ void MeterCommonImplementation::addNumericField(
));
}
void MeterCommonImplementation::addStringFieldWithExtractor(
string vname,
Quantity vquantity,
DifVifKey dif_vif_key,
MeasurementType mt,
VIFRange vi,
StorageNr s,
TariffNr t,
IndexNr i,
PrintProperties print_properties,
string help,
function<void(string)> setValueFunc,
function<string()> getValueFunc)
{
field_infos_.emplace_back(
FieldInfo(field_infos_.size(),
vname,
vquantity,
defaultUnitForQuantity(vquantity),
VifScaling::None,
FieldMatcher::build().set(dif_vif_key).set(mt).set(vi).set(s).set(t).set(i),
help,
print_properties,
NULL,
getValueFunc,
NULL,
setValueFunc,
NoLookup, /* Lookup table */
NULL /* Formula */
));
}
void MeterCommonImplementation::addStringFieldWithExtractor(string vname,
string help,
PrintProperties print_properties,
@ -1104,44 +1039,44 @@ string findField(string key, vector<string> *extra_constant_fields)
}
// Is the desired field one of the fields common to all meters and telegrams?
bool checkCommonField(string *buf, string field, Meter *m, Telegram *t, char c, bool human_readable)
bool checkCommonField(string *buf, string desired_field, Meter *m, Telegram *t, char c, bool human_readable)
{
if (field == "name")
if (desired_field == "name")
{
*buf += m->name() + c;
return true;
}
if (field == "id")
if (desired_field == "id")
{
*buf += t->ids.back() + c;
return true;
}
if (field == "timestamp")
if (desired_field == "timestamp")
{
*buf += m->datetimeOfUpdateHumanReadable() + c;
return true;
}
if (field == "timestamp_lt")
if (desired_field == "timestamp_lt")
{
*buf += m->datetimeOfUpdateHumanReadable() + c;
return true;
}
if (field == "timestamp_utc")
if (desired_field == "timestamp_utc")
{
*buf += m->datetimeOfUpdateRobot() + c;
return true;
}
if (field == "timestamp_ut")
if (desired_field == "timestamp_ut")
{
*buf += m->unixTimestampOfUpdate() + c;
return true;
}
if (field == "device")
if (desired_field == "device")
{
*buf += t->about.device + c;
return true;
}
if (field == "rssi_dbm")
if (desired_field == "rssi_dbm")
{
*buf += to_string(t->about.rssi_dbm) + c;
return true;
@ -1151,7 +1086,7 @@ bool checkCommonField(string *buf, string field, Meter *m, Telegram *t, char c,
}
// Is the desired field one of the meter printable fields?
bool checkPrintableField(string *buf, string desired_field_name, Meter *m, Telegram *t, char c,
bool checkPrintableField(string *buf, string desired_field, Meter *m, Telegram *t, char c,
vector<FieldInfo> &fields, bool human_readable)
{
@ -1160,7 +1095,7 @@ bool checkPrintableField(string *buf, string desired_field_name, Meter *m, Teleg
if (fi.xuantity() == Quantity::Text)
{
// Strings are simply just print them.
if (desired_field_name == fi.vname())
if (desired_field == fi.vname())
{
*buf += m->getStringValue(&fi) + c;
return true;
@ -1170,7 +1105,7 @@ bool checkPrintableField(string *buf, string desired_field_name, Meter *m, Teleg
{
string display_unit_s = unitToStringLowerCase(fi.displayUnit());
string var = fi.vname()+"_"+display_unit_s;
if (desired_field_name != var) continue;
if (desired_field != var) continue;
// We have the correc field.
if (fi.displayUnit() == Unit::DateLT)
@ -2729,6 +2664,18 @@ void MeterCommonImplementation::addOptionalCommonFields(string field_names)
);
}
if (checkIf(fields,"parameter_set"))
{
addStringFieldWithExtractor(
"parameter_set",
"Parameter set for this meter.",
PrintProperty::JSON | PrintProperty::OPTIONAL,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ParameterSet)
);
}
if (checkIf(fields,"customer"))
{
addStringFieldWithExtractor(

Wyświetl plik

@ -123,21 +123,6 @@ protected:
#define FIND_SFIELD_ST(TYPE,INFO,STORAGE,TARIFF) NoDifVifKey,TYPE,INFO,STORAGE,TARIFF,IndexNr(1)
#define FIND_SFIELD_STI(TYPE,INFO,STORAGE,TARIFF,INDEX) NoDifVifKey,TYPE,INFO,STORAGE,TARIFF,INDEX
void addNumericFieldWithExtractor(
string vname, // Name of value without unit, eg total
Quantity vquantity, // Value belongs to this quantity.
DifVifKey dif_vif_key, // You can hardocde a dif vif header here or use NoDifVifKey
VifScaling vif_scaling,
MeasurementType mt, // If not using a hardcoded key, search for mt,vi,s,t and i instead.
VIFRange vi,
StorageNr s,
TariffNr t,
IndexNr i,
PrintProperties print_properties, // Should this be printed by default in fields,json and hr.
string help,
function<void(Unit,double)> setValueFunc, // Use the SET macro above.
function<double(Unit)> getValueFunc); // Use the GET macro above.
void addNumericFieldWithExtractor(
string vname, // Name of value without unit, eg "total" "total_month{storagenr}"
string help, // Information about this field.
@ -182,20 +167,6 @@ protected:
#define SET_STRING_FUNC(varname) {[=](string s){varname = s;}}
#define GET_STRING_FUNC(varname) {[=](){return varname; }}
void addStringFieldWithExtractor(
string vname, // Name of value without unit, eg total
Quantity vquantity, // Value belongs to this quantity.
DifVifKey dif_vif_key, // You can hardocde a dif vif header here or use NoDifVifKey
MeasurementType mt, // If not using a hardcoded key, search for mt,vi,s,t and i instead.
VIFRange vi,
StorageNr s,
TariffNr t,
IndexNr i,
PrintProperties print_properties, // Should this be printed by default in fields,json and hr.
string help,
function<void(string)> setValueFunc, // Use the SET_STRING macro above.
function<string()> getValueFunc); // Use the GET_STRING macro above.
void addStringFieldWithExtractor(
string vname,
string help,

Wyświetl plik

@ -43,6 +43,7 @@ cat > $TEST/test_expected.txt <<EOF
"set_28_fromdhmsz_datetime":"2023-01-22 12:12",
"set_29_fromdhmsz_datetime":"2023-01-22 11:12",
"set_30_from_setdate_datetime":"2022-06-30 00:00",
"set_31_from_setdate2_datetime":"2022-07-31 07:33",
EOF
# TZ=UTC+1 date --date 2022-12-22T12:12:12Z +%s --> 1671711132 # UTC time
@ -87,8 +88,10 @@ TZ=UTC+1 $PROG --format=json --ppjson \
--calculate_set_28_fromdhmsz_datetime="'2022-12-22T12:12:12Z' + 1 month" \
--calculate_set_29_fromdhmsz_datetime='1671711132 ut + 1 month'\
--calculate_set_30_from_setdate_datetime='set_date + 1 month'\
\
--calculate_set_31_from_setdate2_datetime="set_30_from_setdate_datetime + 1 month + 7 h + '00:33'"\
"$HEX" \
GURKA sharky774 71942539 NOKEY | grep \"set_ > $TEST/test_output.txt
Moo sharky774 71942539 NOKEY | grep \"set_ > $TEST/test_output.txt
if [ "$?" = "0" ]
then