kopia lustrzana https://github.com/weetmuts/wmbusmeters
593 wiersze
20 KiB
C++
593 wiersze
20 KiB
C++
/*
|
|
Copyright (C) 2018-2022 Fredrik Öhrström (gpl-3.0-or-later)
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef DVPARSER_H
|
|
#define DVPARSER_H
|
|
|
|
#include"util.h"
|
|
#include"units.h"
|
|
|
|
#include<map>
|
|
#include<set>
|
|
#include<cstdint>
|
|
#include<time.h>
|
|
#include<functional>
|
|
#include<vector>
|
|
|
|
#define LIST_OF_VIF_RANGES \
|
|
X(Volume,0x10,0x17,Quantity::Volume,Unit::M3) \
|
|
X(OnTime,0x20,0x23, Quantity::Time, Unit::Hour) \
|
|
X(OperatingTime,0x24,0x27, Quantity::Time, Unit::Hour) \
|
|
X(VolumeFlow,0x38,0x3F, Quantity::Flow, Unit::M3H) \
|
|
X(FlowTemperature,0x58,0x5B, Quantity::Temperature, Unit::C) \
|
|
X(ReturnTemperature,0x5C,0x5F, Quantity::Temperature, Unit::C) \
|
|
X(TemperatureDifference,0x60,0x63, Quantity::Temperature, Unit::C) \
|
|
X(ExternalTemperature,0x64,0x67, Quantity::Temperature, Unit::C) \
|
|
X(Pressure,0x68,0x6B, Quantity::Pressure, Unit::BAR) \
|
|
X(HeatCostAllocation,0x6E,0x6E, Quantity::HCA, Unit::HCA) \
|
|
X(Date,0x6C,0x6C, Quantity::PointInTime, Unit::DateTimeLT) \
|
|
X(DateTime,0x6D,0x6D, Quantity::PointInTime, Unit::DateTimeLT) \
|
|
X(EnergyMJ,0x08,0x0F, Quantity::Energy, Unit::MJ) \
|
|
X(EnergyWh,0x00,0x07, Quantity::Energy, Unit::KWH) \
|
|
X(PowerW,0x28,0x2f, Quantity::Power, Unit::KW) \
|
|
X(ActualityDuration,0x74,0x77, Quantity::Time, Unit::Hour) \
|
|
X(FabricationNo,0x78,0x78, Quantity::Text, Unit::TXT) \
|
|
X(EnhancedIdentification,0x79,0x79, Quantity::Text, Unit::TXT) \
|
|
X(EnergyMWh,0x7B00,0x7B01, Quantity::Energy, Unit::KWH) \
|
|
X(RelativeHumidity,0x7B1A,0x7B1B, Quantity::RH, Unit::RH) \
|
|
X(AccessNumber,0x7D08,0x7D08, Quantity::Counter, Unit::COUNTER) \
|
|
X(Medium,0x7D09,0x7D09, Quantity::Text, Unit::TXT) \
|
|
X(Manufacturer,0x7D0A,0x7D0A, Quantity::Text, Unit::TXT) \
|
|
X(ParameterSet,0x7D0B,0x7D0B, Quantity::Text, Unit::TXT) \
|
|
X(ModelVersion,0x7D0C,0x7D0C, Quantity::Text, Unit::TXT) \
|
|
X(HardwareVersion,0x7D0D,0x7D0D, Quantity::Text, Unit::TXT) \
|
|
X(FirmwareVersion,0x7D0E,0x7D0E, Quantity::Text, Unit::TXT) \
|
|
X(SoftwareVersion,0x7D0F,0x7D0F, Quantity::Text, Unit::TXT) \
|
|
X(Location,0x7D10,0x7D10, Quantity::Text, Unit::TXT) \
|
|
X(Customer,0x7D11,0x7D11, Quantity::Text, Unit::TXT) \
|
|
X(ErrorFlags,0x7D17,0x7D17, Quantity::Text, Unit::TXT) \
|
|
X(DigitalOutput,0x7D1A,0x7D1A, Quantity::Text, Unit::TXT) \
|
|
X(DigitalInput,0x7D1B,0x7D1B, Quantity::Text, Unit::TXT) \
|
|
X(DurationSinceReadout,0x7D2c,0x7D2f, Quantity::Time, Unit::Hour) \
|
|
X(DurationOfTariff,0x7D31,0x7D33, Quantity::Time, Unit::Hour) \
|
|
X(Dimensionless,0x7D3A,0x7D3A, Quantity::Counter, Unit::COUNTER) \
|
|
X(Voltage,0x7D40,0x7D4F, Quantity::Voltage, Unit::Volt) \
|
|
X(Amperage,0x7D50,0x7D5F, Quantity::Amperage, Unit::Ampere) \
|
|
X(ResetCounter,0x7D60,0x7D60, Quantity::Counter, Unit::COUNTER) \
|
|
X(CumulationCounter,0x7D61,0x7D61, Quantity::Counter, Unit::COUNTER) \
|
|
X(SpecialSupplierInformation,0x7D67,0x7D67, Quantity::Text, Unit::TXT) \
|
|
X(RemainingBattery,0x7D74,0x7D74, Quantity::Time, Unit::Day) \
|
|
X(AnyVolumeVIF,0x00,0x00, Quantity::Volume, Unit::Unknown) \
|
|
X(AnyEnergyVIF,0x00,0x00, Quantity::Energy, Unit::Unknown) \
|
|
X(AnyPowerVIF,0x00,0x00, Quantity::Power, Unit::Unknown)
|
|
|
|
|
|
enum class VIFRange
|
|
{
|
|
None,
|
|
Any,
|
|
#define X(name,from,to,quantity,unit) name,
|
|
LIST_OF_VIF_RANGES
|
|
#undef X
|
|
};
|
|
|
|
struct VIFRaw {
|
|
VIFRaw(uint16_t v) : value(v) {}
|
|
uint16_t value;
|
|
};
|
|
|
|
const char *toString(VIFRange v);
|
|
VIFRange toVIFRange(const char *s);
|
|
Unit toDefaultUnit(VIFRange v);
|
|
VIFRange toVIFRange(int i);
|
|
bool isInsideVIFRange(int i, VIFRange range);
|
|
|
|
#define LIST_OF_VIF_COMBINABLES \
|
|
X(Reserved,0x00,0x11) \
|
|
X(Average,0x12,0x12) \
|
|
X(InverseCompactProfile,0x13,0x13) \
|
|
X(RelativeDeviation,0x14,0x14) \
|
|
X(RecordErrorCodeMeterToController,0x15,0x1c) \
|
|
X(StandardConformantDataContent,0x1d,0x1d) \
|
|
X(CompactProfileWithRegister,0x1e,0x1e) \
|
|
X(CompactProfile,0x1f,0x1f) \
|
|
X(PerSecond,0x20,0x20) \
|
|
X(PerMinute,0x21,0x21) \
|
|
X(PerHour,0x22,0x22) \
|
|
X(PerDay,0x23,0x23) \
|
|
X(PerWeek,0x24,0x24) \
|
|
X(PerMonth,0x25,0x25) \
|
|
X(PerYear,0x26,0x26) \
|
|
X(PerRevolutionMeasurement,0x27,0x27) \
|
|
X(IncrPerInputPulseChannel0,0x28,0x28) \
|
|
X(IncrPerInputPulseChannel1,0x29,0x29) \
|
|
X(IncrPerOutputPulseChannel0,0x2a,0x2a) \
|
|
X(IncrPerOutputPulseChannel1,0x2b,0x2b) \
|
|
X(PerLitre,0x2c,0x2c) \
|
|
X(PerM3,0x2d,0x2d) \
|
|
X(PerKg,0x2e,0x2e) \
|
|
X(PerKelvin,0x2f,0x2f) \
|
|
X(PerKWh,0x30,0x30) \
|
|
X(PerGJ,0x31,0x31) \
|
|
X(PerKW,0x32,0x32) \
|
|
X(PerKelvinLitreW,0x33,0x33) \
|
|
X(PerVolt,0x34,0x34) \
|
|
X(PerAmpere,0x35,0x35) \
|
|
X(MultipliedByS,0x36,0x36) \
|
|
X(MultipliedBySDivV,0x37,0x37) \
|
|
X(MultipliedBySDivA,0x38,0x38) \
|
|
X(StartDateTimeOfAB,0x39,0x39) \
|
|
X(UncorrectedMeterUnit,0x3a,0x3a) \
|
|
X(ForwardFlow,0x3b,0x3b) \
|
|
X(BackwardFlow,0x3c,0x3c) \
|
|
X(ReservedNonMetric,0x3d,0x3d) \
|
|
X(ValueAtBaseCondC,0x3e,0x3e) \
|
|
X(ObisDeclaration,0x3f,0x3f) \
|
|
X(LowerLimit,0x40,0x40) \
|
|
X(ExceedsLowerLimit,0x41,0x41) \
|
|
X(DateTimeExceedsLowerFirstBegin, 0x42,0x42) \
|
|
X(DateTimeExceedsLowerFirstEnd, 0x43,0x43) \
|
|
X(DateTimeExceedsLowerLastBegin, 0x46,0x46) \
|
|
X(DateTimeExceedsLowerLastEnd, 0x47,0x47) \
|
|
X(UpperLimit,0x48,0x48) \
|
|
X(ExceedsUpperLimit,0x49,0x49) \
|
|
X(DateTimeExceedsUpperFirstBegin, 0x4a,0x4a) \
|
|
X(DateTimeExceedsUpperFirstEnd, 0x4b,0x4b) \
|
|
X(DateTimeExceedsUpperLastBegin, 0x4d,0x4d) \
|
|
X(DateTimeExceedsUpperLastEnd, 0x4e,0x4e) \
|
|
X(DurationExceedsLowerFirst,0x50,0x53) \
|
|
X(DurationExceedsLowerLast,0x54,0x57) \
|
|
X(DurationExceedsUpperFirst,0x58,0x5b) \
|
|
X(DurationExceedsUpperLast,0x5c,0x5f) \
|
|
X(DurationOfDFirst,0x60,0x63) \
|
|
X(DurationOfDLast,0x64,0x67) \
|
|
X(ValueDuringLowerLimitExceeded,0x68,0x68) \
|
|
X(LeakageValues,0x69,0x69) \
|
|
X(OverflowValues,0x6a,0x6a) \
|
|
X(ValueDuringUpperLimitExceeded,0x6c,0x6c) \
|
|
X(DateTimeOfDEFirstBegin,0x6a,0x6a) \
|
|
X(DateTimeOfDEFirstEnd,0x6b,0x6b) \
|
|
X(DateTimeOfDELastBegin,0x6e,0x6e) \
|
|
X(DateTimeOfDELastEnd,0x6f,0x6f) \
|
|
X(MultiplicativeCorrectionFactorForValue,0x70,0x77) \
|
|
X(AdditiveCorrectionConstant,0x78,0x7b) \
|
|
X(CombinableVIFExtension,0x7c,0x7c) \
|
|
X(MultiplicativeCorrectionFactorForValue103,0x7d,0x7d) \
|
|
X(FutureValue,0x7e,0x7e) \
|
|
X(MfctSpecific,0x7f,0x7f) \
|
|
X(AtPhase1,0x7c01,0x7c01) \
|
|
X(AtPhase2,0x7c02,0x7c02) \
|
|
X(AtPhase3,0x7c03,0x7c03) \
|
|
X(AtNeutral,0x7c04,0x7c04) \
|
|
X(BetweenPhaseL1AndL2,0x7c05,0x7c05) \
|
|
X(BetweenPhaseL2AndL3,0x7c06,0x7c06) \
|
|
X(BetweenPhaseL3AndL1,0x7c07,0x7c07) \
|
|
X(AtQuadrantQ1,0x7c08,0x7c08) \
|
|
X(AtQuadrantQ2,0x7c09,0x7c09) \
|
|
X(AtQuadrantQ3,0x7c0a,0x7c0a) \
|
|
X(AtQuadrantQ4,0x7c0b,0x7c0b) \
|
|
X(DeltaBetweenImportAndExport,0x7c0c,0x7c0c) \
|
|
X(AccumulationOfAbsoluteValue,0x7c10,0x7c10) \
|
|
X(DataPresentedWithTypeC,0x7c11,0x7c11) \
|
|
X(DataPresentedWithTypeD,0x7c12,0x7c12) \
|
|
X(Mfct00,0x7f00,0x7f00) \
|
|
X(Mfct01,0x7f01,0x7f01) \
|
|
X(Mfct02,0x7f02,0x7f02) \
|
|
X(Mfct03,0x7f03,0x7f03) \
|
|
X(Mfct04,0x7f04,0x7f04) \
|
|
X(Mfct05,0x7f05,0x7f05) \
|
|
X(Mfct06,0x7f06,0x7f06) \
|
|
X(Mfct07,0x7f07,0x7f07) \
|
|
X(Mfct21,0x7f21,0x7f21) \
|
|
|
|
enum class VIFCombinable
|
|
{
|
|
None,
|
|
Any,
|
|
#define X(name,from,to) name,
|
|
LIST_OF_VIF_COMBINABLES
|
|
#undef X
|
|
};
|
|
|
|
struct VIFCombinableRaw {
|
|
VIFCombinableRaw(uint16_t v) : value(v) {}
|
|
uint16_t value;
|
|
};
|
|
|
|
VIFCombinable toVIFCombinable(int i);
|
|
const char *toString(VIFCombinable v);
|
|
|
|
enum class MeasurementType
|
|
{
|
|
Any,
|
|
Instantaneous,
|
|
Minimum,
|
|
Maximum,
|
|
AtError,
|
|
Unknown
|
|
};
|
|
|
|
const char *toString(MeasurementType mt);
|
|
MeasurementType toMeasurementType(const char *s);
|
|
|
|
void extractDV(std::string &s, uchar *dif, int *vif, bool *has_difes, bool *has_vifes);
|
|
|
|
struct DifVifKey
|
|
{
|
|
DifVifKey(std::string key) : key_(key) {
|
|
extractDV(key, &dif_, &vif_, &has_difes_, &has_vifes_);
|
|
}
|
|
std::string str() { return key_; }
|
|
bool operator==(DifVifKey &dvk) { return key_ == dvk.key_; }
|
|
uchar dif() { return dif_; }
|
|
int vif() { return vif_; }
|
|
bool hasDifes() { return has_difes_; }
|
|
bool hasVifes() { return has_vifes_; }
|
|
|
|
private:
|
|
|
|
std::string key_;
|
|
uchar dif_;
|
|
int vif_;
|
|
bool has_difes_;
|
|
bool has_vifes_;
|
|
};
|
|
|
|
void extractDV(DifVifKey &s, uchar *dif, int *vif, bool *has_difes, bool *has_vifes);
|
|
|
|
static DifVifKey NoDifVifKey = DifVifKey("");
|
|
|
|
struct Vif
|
|
{
|
|
Vif(int n) : nr_(n) {}
|
|
int intValue() { return nr_; }
|
|
bool operator==(Vif s) { return nr_ == s.nr_; }
|
|
|
|
private:
|
|
int nr_;
|
|
};
|
|
|
|
Unit toDefaultUnit(Vif v);
|
|
|
|
enum class DVEntryCounterType
|
|
{
|
|
UNKNOWN,
|
|
STORAGE_COUNTER,
|
|
TARIFF_COUNTER,
|
|
SUBUNIT_COUNTER
|
|
};
|
|
|
|
DVEntryCounterType toDVEntryCounterType(const std::string &s);
|
|
const char *toString(DVEntryCounterType ct);
|
|
|
|
struct StorageNr
|
|
{
|
|
StorageNr(int n) : nr_(n) {}
|
|
int intValue() { return nr_; }
|
|
bool operator==(StorageNr s) { return nr_ == s.nr_; }
|
|
bool operator!=(StorageNr s) { return nr_ != s.nr_; }
|
|
bool operator>=(StorageNr s) { return nr_ >= s.nr_; }
|
|
bool operator<=(StorageNr s) { return nr_ <= s.nr_; }
|
|
|
|
private:
|
|
int nr_;
|
|
};
|
|
|
|
static StorageNr AnyStorageNr = StorageNr(-1);
|
|
|
|
struct TariffNr
|
|
{
|
|
TariffNr(int n) : nr_(n) {}
|
|
int intValue() { return nr_; }
|
|
bool operator==(TariffNr s) { return nr_ == s.nr_; }
|
|
bool operator!=(TariffNr s) { return nr_ != s.nr_; }
|
|
bool operator>=(TariffNr s) { return nr_ >= s.nr_; }
|
|
bool operator<=(TariffNr s) { return nr_ <= s.nr_; }
|
|
|
|
private:
|
|
int nr_;
|
|
};
|
|
|
|
static TariffNr AnyTariffNr = TariffNr(-1);
|
|
|
|
struct SubUnitNr
|
|
{
|
|
SubUnitNr(int n) : nr_(n) {}
|
|
int intValue() { return nr_; }
|
|
bool operator==(SubUnitNr s) { return nr_ == s.nr_; }
|
|
bool operator!=(SubUnitNr s) { return nr_ != s.nr_; }
|
|
bool operator>=(SubUnitNr s) { return nr_ >= s.nr_; }
|
|
bool operator<=(SubUnitNr s) { return nr_ <= s.nr_; }
|
|
|
|
private:
|
|
int nr_;
|
|
};
|
|
|
|
struct IndexNr
|
|
{
|
|
IndexNr(int n) : nr_(n) {}
|
|
int intValue() { return nr_; }
|
|
bool operator==(IndexNr s) { return nr_ == s.nr_; }
|
|
bool operator!=(IndexNr s) { return nr_ != s.nr_; }
|
|
|
|
private:
|
|
int nr_;
|
|
};
|
|
|
|
static IndexNr AnyIndexNr = IndexNr(-1);
|
|
|
|
struct FieldInfo;
|
|
|
|
struct DVEntry
|
|
{
|
|
int offset {}; // Where in the telegram this dventry was found.
|
|
DifVifKey dif_vif_key;
|
|
MeasurementType measurement_type;
|
|
Vif vif;
|
|
std::set<VIFCombinable> combinable_vifs;
|
|
std::set<uint16_t> combinable_vifs_raw;
|
|
StorageNr storage_nr;
|
|
TariffNr tariff_nr;
|
|
SubUnitNr subunit_nr;
|
|
std::string value;
|
|
|
|
DVEntry(int off,
|
|
DifVifKey dvk,
|
|
MeasurementType mt,
|
|
Vif vi,
|
|
std::set<VIFCombinable> vc,
|
|
std::set<uint16_t> vc_raw,
|
|
StorageNr st,
|
|
TariffNr ta,
|
|
SubUnitNr su,
|
|
std::string &val) :
|
|
offset(off),
|
|
dif_vif_key(dvk),
|
|
measurement_type(mt),
|
|
vif(vi),
|
|
combinable_vifs(vc),
|
|
combinable_vifs_raw(vc_raw),
|
|
storage_nr(st),
|
|
tariff_nr(ta),
|
|
subunit_nr(su),
|
|
value(val)
|
|
{
|
|
}
|
|
|
|
DVEntry() :
|
|
offset(999999),
|
|
dif_vif_key("????"),
|
|
measurement_type(MeasurementType::Instantaneous),
|
|
vif(0),
|
|
storage_nr(0),
|
|
tariff_nr(0),
|
|
subunit_nr(0),
|
|
value("x")
|
|
{
|
|
}
|
|
|
|
bool extractDouble(double *out, bool auto_scale, bool assume_signed);
|
|
bool extractLong(uint64_t *out);
|
|
bool extractDate(struct tm *out);
|
|
bool extractReadableString(std::string *out);
|
|
void addFieldInfo(FieldInfo *fi) { field_infos_.insert(fi); }
|
|
bool hasFieldInfo(FieldInfo *fi) { return field_infos_.count(fi) > 0; }
|
|
std::string str();
|
|
|
|
double getCounter(DVEntryCounterType ct);
|
|
|
|
private:
|
|
std::set<FieldInfo*> field_infos_; // The field infos selected to decode this entry.
|
|
};
|
|
|
|
struct FieldMatcher
|
|
{
|
|
// If not actually used, this remains false.
|
|
bool active = false;
|
|
|
|
// Exact difvif hex string matching all other checks are ignored.
|
|
bool match_dif_vif_key = false;
|
|
DifVifKey dif_vif_key { "" };
|
|
|
|
// Match the measurement_type.
|
|
bool match_measurement_type = false;
|
|
MeasurementType measurement_type { MeasurementType::Instantaneous };
|
|
|
|
// Match the value information range. See dvparser.h
|
|
bool match_vif_range = false;
|
|
VIFRange vif_range { VIFRange::Any };
|
|
|
|
// Match the vif exactly, used for manufacturer specific vifs.
|
|
bool match_vif_raw = false;
|
|
uint16_t vif_raw {};
|
|
|
|
// Match any vif combinables.
|
|
std::set<VIFCombinable> vif_combinables;
|
|
std::set<uint16_t> vif_combinables_raw;
|
|
|
|
// Match the storage nr. If no storage is specified, default to match only 0.
|
|
bool match_storage_nr = true;
|
|
StorageNr storage_nr_from { 0 };
|
|
StorageNr storage_nr_to { 0 };
|
|
|
|
// Match the tariff nr. If no tariff is specified, default to match only 0.
|
|
bool match_tariff_nr = true;
|
|
TariffNr tariff_nr_from { 0 };
|
|
TariffNr tariff_nr_to { 0 };
|
|
|
|
// Match the subunit. If no subunit is specified, default to match only 0.
|
|
bool match_subunit_nr = true;
|
|
SubUnitNr subunit_nr_from { 0 };
|
|
SubUnitNr subunit_nr_to { 0 };
|
|
|
|
// If the telegram has multiple identical difvif entries matching this field
|
|
// and you want to catch the second matching entry, then set the index nr to 2.
|
|
// The default is 1.
|
|
IndexNr index_nr { 1 };
|
|
|
|
FieldMatcher() : active(false) { }
|
|
FieldMatcher(bool act) : active(act) { }
|
|
static FieldMatcher build() { return FieldMatcher(true); }
|
|
static FieldMatcher noMatcher() { return FieldMatcher(false); }
|
|
FieldMatcher &set(DifVifKey k) {
|
|
dif_vif_key = k;
|
|
match_dif_vif_key = (k.str() != ""); return *this; }
|
|
FieldMatcher &set(MeasurementType mt) {
|
|
measurement_type = mt;
|
|
match_measurement_type = (mt != MeasurementType::Any);
|
|
return *this; }
|
|
FieldMatcher &set(VIFRange v) {
|
|
vif_range = v;
|
|
match_vif_range = (v != VIFRange::Any);
|
|
return *this; }
|
|
FieldMatcher &set(VIFRaw v) {
|
|
vif_raw = v.value;
|
|
match_vif_raw = true;
|
|
return *this; }
|
|
FieldMatcher &add(VIFCombinable v) {
|
|
vif_combinables.insert(v);
|
|
return *this; }
|
|
FieldMatcher &add(VIFCombinableRaw v) {
|
|
vif_combinables_raw.insert(v.value);
|
|
return *this; }
|
|
FieldMatcher &set(StorageNr s) {
|
|
storage_nr_from = storage_nr_to = s;
|
|
match_storage_nr = (s != AnyStorageNr);
|
|
return *this; }
|
|
FieldMatcher &set(StorageNr from, StorageNr to) {
|
|
storage_nr_from = from;
|
|
storage_nr_to = to;
|
|
match_storage_nr = true;
|
|
return *this; }
|
|
FieldMatcher &set(TariffNr s) {
|
|
tariff_nr_from = tariff_nr_to = s;
|
|
match_tariff_nr = (s != AnyTariffNr);
|
|
return *this; }
|
|
FieldMatcher &set(TariffNr from, TariffNr to) {
|
|
tariff_nr_from = from;
|
|
tariff_nr_to = to;
|
|
match_tariff_nr = true;
|
|
return *this; }
|
|
FieldMatcher &set(SubUnitNr s) {
|
|
subunit_nr_from = subunit_nr_to = s;
|
|
match_subunit_nr = true;
|
|
return *this; }
|
|
FieldMatcher &set(SubUnitNr from, SubUnitNr to) {
|
|
subunit_nr_from = from;
|
|
subunit_nr_to = to;
|
|
match_subunit_nr = true; return *this; }
|
|
|
|
FieldMatcher &set(IndexNr i) { index_nr = i; return *this; }
|
|
|
|
bool matches(DVEntry &dv_entry);
|
|
|
|
// Returns true of there is any range for storage, tariff, subunit nrs.
|
|
// I.e. this matcher is expected to match against multiple dv entries!
|
|
bool expectedToMatchAgainstMultipleEntries()
|
|
{
|
|
return (match_storage_nr && storage_nr_from != storage_nr_to)
|
|
|| (match_tariff_nr && tariff_nr_from != tariff_nr_to)
|
|
|| (match_subunit_nr && subunit_nr_from != subunit_nr_to);
|
|
}
|
|
|
|
std::string str();
|
|
};
|
|
|
|
bool loadFormatBytesFromSignature(uint16_t format_signature, std::vector<uchar> *format_bytes);
|
|
|
|
struct Telegram;
|
|
|
|
bool parseDV(Telegram *t,
|
|
std::vector<uchar> &databytes,
|
|
std::vector<uchar>::iterator data,
|
|
size_t data_len,
|
|
std::map<std::string,std::pair<int,DVEntry>> *dv_entries,
|
|
std::vector<uchar>::iterator *format = NULL,
|
|
size_t format_len = 0,
|
|
uint16_t *format_hash = NULL);
|
|
|
|
// Instead of using a hardcoded difvif as key in the extractDV... below,
|
|
// 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, VIFRange vi, StorageNr storagenr, TariffNr tariffnr,
|
|
std::string *key, std::map<std::string,std::pair<int,DVEntry>> *values);
|
|
// Some meters have multiple identical DIF/VIF values! Meh, they are not using storage nrs or tariff nrs.
|
|
// So here we can pick for example nr 2 of an identical set if DIF/VIF values.
|
|
// Nr 1 means the first found value.
|
|
bool findKeyWithNr(MeasurementType mt, VIFRange vi, StorageNr storagenr, TariffNr tariffnr, int indexnr,
|
|
std::string *key, std::map<std::string,std::pair<int,DVEntry>> *values);
|
|
|
|
bool hasKey(std::map<std::string,std::pair<int,DVEntry>> *values, std::string key);
|
|
|
|
bool extractDVuint8(std::map<std::string,std::pair<int,DVEntry>> *values,
|
|
std::string key,
|
|
int *offset,
|
|
uchar *value);
|
|
|
|
bool extractDVuint16(std::map<std::string,std::pair<int,DVEntry>> *values,
|
|
std::string key,
|
|
int *offset,
|
|
uint16_t *value);
|
|
|
|
bool extractDVuint24(std::map<std::string,std::pair<int,DVEntry>> *values,
|
|
std::string key,
|
|
int *offset,
|
|
uint32_t *value);
|
|
|
|
bool extractDVuint32(std::map<std::string,std::pair<int,DVEntry>> *values,
|
|
std::string key,
|
|
int *offset,
|
|
uint32_t *value);
|
|
|
|
// All values are scaled according to the vif and wmbusmeters scaling defaults.
|
|
bool extractDVdouble(std::map<std::string,std::pair<int,DVEntry>> *values,
|
|
std::string key,
|
|
int *offset,
|
|
double *value,
|
|
bool auto_scale = true,
|
|
bool assume_signed = false);
|
|
|
|
// Extract a value without scaling. Works for 8bits to 64 bits, binary and bcd.
|
|
bool extractDVlong(std::map<std::string,std::pair<int,DVEntry>> *values,
|
|
std::string key,
|
|
int *offset,
|
|
uint64_t *value);
|
|
|
|
// Just copy the raw hex data into the string, not reversed or anything.
|
|
bool extractDVHexString(std::map<std::string,std::pair<int,DVEntry>> *values,
|
|
std::string key,
|
|
int *offset,
|
|
std::string *value);
|
|
|
|
// Read the content and attempt to reverse and transform it into a readble string
|
|
// based on the dif information.
|
|
bool extractDVReadableString(std::map<std::string,std::pair<int,DVEntry>> *values,
|
|
std::string key,
|
|
int *offset,
|
|
std::string *value);
|
|
|
|
bool extractDVdate(std::map<std::string,std::pair<int,DVEntry>> *values,
|
|
std::string key,
|
|
int *offset,
|
|
struct tm *value);
|
|
|
|
|
|
const std::string &availableVIFRanges();
|
|
|
|
#endif
|