#include "AmsData.h" #include "Kaifa.h" #include "Aidon.h" #include "Kamstrup.h" #include "Omnipower.h" AmsData::AmsData() {} AmsData::AmsData(uint8_t meterType, bool substituteMissing, HanReader& hanReader) { lastUpdateMillis = millis(); packageTimestamp = hanReader.getPackageTime(true, true); int listSize = hanReader.getListSize(); switch(meterType) { case METER_TYPE_KAIFA: extractFromKaifa(hanReader, listSize); break; case METER_TYPE_AIDON: extractFromAidon(hanReader, listSize, substituteMissing); break; case METER_TYPE_KAMSTRUP: extractFromKamstrup(hanReader, listSize, substituteMissing); break; case METER_TYPE_OMNIPOWER: extractFromOmnipower(hanReader, listSize); break; } } void AmsData::extractFromKaifa(HanReader& hanReader, uint8_t listSize) { switch(listSize) { case (uint8_t)Kaifa::List1: listType = 1; break; case (uint8_t)Kaifa::List3PhaseShort: threePhase = true; case (uint8_t)Kaifa::List1PhaseShort: listType = 2; break; case (uint8_t)Kaifa::List3PhaseLong: threePhase = true; case (uint8_t)Kaifa::List1PhaseLong: listType = 3; break; } if(listSize == (uint8_t)Kaifa::List1) { activeImportPower = hanReader.getInt((int)Kaifa_List1::ActivePowerImported); } else { switch(listSize) { case (uint8_t)Kaifa::List3PhaseLong: meterTimestamp = hanReader.getTime( (int)Kaifa_List3Phase::MeterClock, false, false); activeImportCounter = ((float) hanReader.getUint((int)Kaifa_List3Phase::CumulativeActiveImportEnergy)) / 1000; activeExportCounter = ((float) hanReader.getUint((int)Kaifa_List3Phase::CumulativeActiveExportEnergy)) / 1000; reactiveImportCounter = ((float) hanReader.getUint((int)Kaifa_List3Phase::CumulativeReactiveImportEnergy)) / 1000; reactiveExportCounter = ((float) hanReader.getUint((int)Kaifa_List3Phase::CumulativeReactiveExportEnergy)) / 1000; case (uint8_t)Kaifa::List3PhaseShort: listId = hanReader.getString( (int)Kaifa_List3Phase::ListVersionIdentifier); meterId = hanReader.getString( (int)Kaifa_List3Phase::MeterID); meterModel = hanReader.getString( (int)Kaifa_List3Phase::MeterType); activeImportPower = hanReader.getUint( (int)Kaifa_List3Phase::ActiveImportPower); reactiveImportPower = hanReader.getUint( (int)Kaifa_List3Phase::ReactiveImportPower); activeExportPower = hanReader.getUint( (int)Kaifa_List3Phase::ActiveExportPower); reactiveExportPower = hanReader.getUint( (int)Kaifa_List3Phase::ReactiveExportPower); l1current = ((float) hanReader.getInt( (int)Kaifa_List3Phase::CurrentL1)) / 1000; l2current = ((float) hanReader.getInt( (int)Kaifa_List3Phase::CurrentL2)) / 1000; l3current = ((float) hanReader.getInt( (int)Kaifa_List3Phase::CurrentL3)) / 1000; l1voltage = ((float) hanReader.getInt( (int)Kaifa_List3Phase::VoltageL1)) / 10; l2voltage = ((float) hanReader.getInt( (int)Kaifa_List3Phase::VoltageL2)) / 10; l3voltage = ((float) hanReader.getInt( (int)Kaifa_List3Phase::VoltageL3)) / 10; break; case (uint8_t)Kaifa::List1PhaseLong: meterTimestamp = hanReader.getTime( (int)Kaifa_List1Phase::MeterClock, false, false); activeImportCounter = ((float) hanReader.getUint((int)Kaifa_List1Phase::CumulativeActiveImportEnergy)); activeExportCounter = ((float) hanReader.getUint((int)Kaifa_List1Phase::CumulativeActiveExportEnergy)); reactiveImportCounter = ((float) hanReader.getUint((int)Kaifa_List1Phase::CumulativeReactiveImportEnergy)); reactiveExportCounter = ((float) hanReader.getUint((int)Kaifa_List1Phase::CumulativeReactiveExportEnergy)); case (uint8_t)Kaifa::List1PhaseShort: listId = hanReader.getString( (int)Kaifa_List1Phase::ListVersionIdentifier); meterId = hanReader.getString( (int)Kaifa_List1Phase::MeterID); meterModel = hanReader.getString( (int)Kaifa_List1Phase::MeterType); activeImportPower = hanReader.getUint( (int)Kaifa_List1Phase::ActiveImportPower); reactiveImportPower = hanReader.getUint( (int)Kaifa_List1Phase::ReactiveImportPower); activeExportPower = hanReader.getUint( (int)Kaifa_List1Phase::ActiveExportPower); reactiveExportPower = hanReader.getUint( (int)Kaifa_List1Phase::ReactiveExportPower); l1current = ((float) hanReader.getInt( (int)Kaifa_List1Phase::CurrentL1)) / 1000; l1voltage = ((float) hanReader.getInt( (int)Kaifa_List1Phase::VoltageL1)) / 10; break; } } } void AmsData::extractFromAidon(HanReader& hanReader, uint8_t listSize, bool substituteMissing) { switch(listSize) { case (uint8_t)Aidon::List1: listType = 1; break; case (uint8_t)Aidon::List3PhaseITShort: case (uint8_t)Aidon::List3PhaseShort: threePhase = true; case (uint8_t)Aidon::List1PhaseShort: listType = 2; break; case (uint8_t)Aidon::List3PhaseITLong: case (uint8_t)Aidon::List3PhaseLong: threePhase = true; case (uint8_t)Aidon::List1PhaseLong: listType = 3; break; } if(listSize == (uint8_t)Aidon::List1) { activeImportPower = hanReader.getUint((uint8_t)Aidon_List1::ActiveImportPower); } else { switch(listSize) { case (uint8_t)Aidon::List3PhaseLong: meterTimestamp = hanReader.getTime( (uint8_t)Aidon_List3Phase::Timestamp, false, false); activeImportCounter = ((float) hanReader.getUint( (uint8_t)Aidon_List3Phase::CumulativeActiveImportEnergy)) / 100; activeExportCounter = ((float) hanReader.getUint( (uint8_t)Aidon_List3Phase::CumulativeActiveExportEnergy)) / 100; reactiveImportCounter = ((float) hanReader.getUint( (uint8_t)Aidon_List3Phase::CumulativeReactiveImportEnergy)) / 100; reactiveExportCounter = ((float) hanReader.getUint( (uint8_t)Aidon_List3Phase::CumulativeReactiveExportEnergy)) / 100; case (uint8_t)Aidon::List3PhaseShort: listId = hanReader.getString( (uint8_t)Aidon_List3Phase::ListVersionIdentifier); meterId = hanReader.getString( (uint8_t)Aidon_List3Phase::MeterID); meterModel = hanReader.getString( (uint8_t)Aidon_List3Phase::MeterType); activeImportPower = hanReader.getUint( (uint8_t)Aidon_List3Phase::ActiveImportPower); reactiveImportPower = hanReader.getUint( (uint8_t)Aidon_List3Phase::ReactiveImportPower); activeExportPower = hanReader.getUint( (uint8_t)Aidon_List3Phase::ActiveExportPower); reactiveExportPower = hanReader.getUint( (uint8_t)Aidon_List3Phase::ReactiveExportPower); l1current = ((float) hanReader.getInt( (uint8_t)Aidon_List3Phase::CurrentL1)) / 10; l2current = ((float) hanReader.getInt( (uint8_t)Aidon_List3Phase::CurrentL2)) / 10; l3current = ((float) hanReader.getInt( (uint8_t)Aidon_List3Phase::CurrentL3)) / 10; l1voltage = ((float) hanReader.getInt( (uint8_t)Aidon_List3Phase::VoltageL1)) / 10; l2voltage = ((float) hanReader.getInt( (uint8_t)Aidon_List3Phase::VoltageL2)) / 10; l3voltage = ((float) hanReader.getInt( (uint8_t)Aidon_List3Phase::VoltageL3)) / 10; break; case (uint8_t)Aidon::List1PhaseLong: meterTimestamp = hanReader.getTime( (uint8_t)Aidon_List1Phase::Timestamp, false, false); activeImportCounter = ((float) hanReader.getUint( (uint8_t)Aidon_List1Phase::CumulativeActiveImportEnergy)) / 100; activeExportCounter = ((float) hanReader.getUint( (uint8_t)Aidon_List1Phase::CumulativeActiveExportEnergy)) / 100; reactiveImportCounter = ((float) hanReader.getUint( (uint8_t)Aidon_List1Phase::CumulativeReactiveImportEnergy)) / 100; reactiveExportCounter = ((float) hanReader.getUint( (uint8_t)Aidon_List1Phase::CumulativeReactiveExportEnergy)) / 100; case (uint8_t)Aidon::List1PhaseShort: listId = hanReader.getString( (uint8_t)Aidon_List1Phase::ListVersionIdentifier); meterId = hanReader.getString( (uint8_t)Aidon_List1Phase::MeterID); meterModel = hanReader.getString( (uint8_t)Aidon_List1Phase::MeterType); activeImportPower = hanReader.getUint( (uint8_t)Aidon_List1Phase::ActiveImportPower); reactiveImportPower = hanReader.getUint( (uint8_t)Aidon_List1Phase::ReactiveImportPower); activeExportPower = hanReader.getUint( (uint8_t)Aidon_List1Phase::ActiveExportPower); reactiveExportPower = hanReader.getUint( (uint8_t)Aidon_List1Phase::ReactiveExportPower); l1current = ((float) hanReader.getInt( (uint8_t)Aidon_List1Phase::CurrentL1)) / 10; l1voltage = ((float) hanReader.getInt( (uint8_t)Aidon_List1Phase::VoltageL1)) / 10; break; case (uint8_t)Aidon::List3PhaseITLong: meterTimestamp = hanReader.getTime( (uint8_t)Aidon_List3PhaseIT::Timestamp, false, false); activeImportCounter = ((float) hanReader.getUint( (uint8_t)Aidon_List3PhaseIT::CumulativeActiveImportEnergy)) / 100; activeExportCounter = ((float) hanReader.getUint( (uint8_t)Aidon_List3PhaseIT::CumulativeActiveExportEnergy)) / 100; reactiveImportCounter = ((float) hanReader.getUint( (uint8_t)Aidon_List3PhaseIT::CumulativeReactiveImportEnergy)) / 100; reactiveExportCounter = ((float) hanReader.getUint( (uint8_t)Aidon_List3PhaseIT::CumulativeReactiveExportEnergy)) / 100; case (uint8_t)Aidon::List3PhaseITShort: listId = hanReader.getString( (uint8_t)Aidon_List3PhaseIT::ListVersionIdentifier); meterId = hanReader.getString( (uint8_t)Aidon_List3PhaseIT::MeterID); meterModel = hanReader.getString( (uint8_t)Aidon_List3PhaseIT::MeterType); activeImportPower = hanReader.getUint( (uint8_t)Aidon_List3PhaseIT::ActiveImportPower); reactiveImportPower = hanReader.getUint( (uint8_t)Aidon_List3PhaseIT::ReactiveImportPower); activeExportPower = hanReader.getUint( (uint8_t)Aidon_List3PhaseIT::ActiveExportPower); reactiveExportPower = hanReader.getUint( (uint8_t)Aidon_List3PhaseIT::ReactiveExportPower); l1current = ((float) hanReader.getInt( (uint8_t)Aidon_List3PhaseIT::CurrentL1)) / 10; l2current = 0; l3current = ((float) hanReader.getInt( (uint8_t)Aidon_List3PhaseIT::CurrentL3)) / 10; l1voltage = ((float) hanReader.getInt( (uint8_t)Aidon_List3PhaseIT::VoltageL1)) / 10; l2voltage = ((float) hanReader.getInt( (uint8_t)Aidon_List3PhaseIT::VoltageL2)) / 10; l3voltage = ((float) hanReader.getInt( (uint8_t)Aidon_List3PhaseIT::VoltageL3)) / 10; if(substituteMissing) { l2current = (((activeImportPower - activeExportPower) * sqrt(3)) - (l1voltage * l1current) - (l3voltage * l3current)) / l2voltage; } break; } } } void AmsData::extractFromKamstrup(HanReader& hanReader, uint8_t listSize, bool substituteMissing) { switch(listSize) { case (uint8_t)Kamstrup::List3PhaseITShort: case (uint8_t)Kamstrup::List3PhaseShort: threePhase = true; case (uint8_t)Kamstrup::List1PhaseShort: listType = 2; break; case (uint8_t)Kamstrup::List3PhaseITLong: case (uint8_t)Kamstrup::List3PhaseLong: threePhase = true; case (uint8_t)Kamstrup::List1PhaseLong: listType = 3; break; } switch(listSize) { case (uint8_t)Kamstrup::List1PhaseLong: meterTimestamp = hanReader.getTime( (uint8_t)Kamstrup_List1Phase::MeterClock, true, true); activeImportCounter = ((float) hanReader.getInt((uint8_t)Kamstrup_List1Phase::CumulativeActiveImportEnergy)) / 100; activeExportCounter = ((float) hanReader.getInt((uint8_t)Kamstrup_List1Phase::CumulativeActiveExportEnergy)) / 100; reactiveImportCounter = ((float) hanReader.getInt((uint8_t)Kamstrup_List1Phase::CumulativeReactiveImportEnergy)) / 100; reactiveExportCounter = ((float) hanReader.getInt((uint8_t)Kamstrup_List1Phase::CumulativeReactiveExportEnergy)) / 100; case (uint8_t)Kamstrup::List1PhaseShort: listId = hanReader.getString( (uint8_t)Kamstrup_List1Phase::ListVersionIdentifier); meterId = hanReader.getString( (uint8_t)Kamstrup_List1Phase::MeterID); meterModel = hanReader.getString( (uint8_t)Kamstrup_List1Phase::MeterType); activeImportPower = hanReader.getInt( (uint8_t)Kamstrup_List1Phase::ActiveImportPower); reactiveImportPower = hanReader.getInt( (uint8_t)Kamstrup_List1Phase::ReactiveImportPower); activeExportPower = hanReader.getInt( (uint8_t)Kamstrup_List1Phase::ActiveExportPower); reactiveExportPower = hanReader.getInt( (uint8_t)Kamstrup_List1Phase::ReactiveExportPower); l1current = ((float) hanReader.getInt((uint8_t)Kamstrup_List1Phase::CurrentL1)) / 100; l1voltage = hanReader.getInt( (uint8_t)Kamstrup_List1Phase::VoltageL1); break; case (uint8_t)Kamstrup::List3PhaseLong: meterTimestamp = hanReader.getTime( (uint8_t)Kamstrup_List3Phase::MeterClock, true, true); activeImportCounter = ((float) hanReader.getInt((uint8_t)Kamstrup_List3Phase::CumulativeActiveImportEnergy)) / 100; activeExportCounter = ((float) hanReader.getInt((uint8_t)Kamstrup_List3Phase::CumulativeActiveExportEnergy)) / 100; reactiveImportCounter = ((float) hanReader.getInt((uint8_t)Kamstrup_List3Phase::CumulativeReactiveImportEnergy)) / 100; reactiveExportCounter = ((float) hanReader.getInt((uint8_t)Kamstrup_List3Phase::CumulativeReactiveExportEnergy)) / 100; case (uint8_t)Kamstrup::List3PhaseShort: listId = hanReader.getString( (uint8_t)Kamstrup_List3Phase::ListVersionIdentifier); meterId = hanReader.getString( (uint8_t)Kamstrup_List3Phase::MeterID); meterModel = hanReader.getString( (uint8_t)Kamstrup_List3Phase::MeterType); activeImportPower = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::ActiveImportPower); reactiveImportPower = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::ReactiveImportPower); activeExportPower = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::ActiveExportPower); reactiveExportPower = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::ReactiveExportPower); l1current = ((float) hanReader.getInt((uint8_t)Kamstrup_List3Phase::CurrentL1)) / 100; l2current = ((float) hanReader.getInt((uint8_t)Kamstrup_List3Phase::CurrentL2)) / 100; l3current = ((float) hanReader.getInt((uint8_t)Kamstrup_List3Phase::CurrentL3)) / 100; l1voltage = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::VoltageL1); l2voltage = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::VoltageL2); l3voltage = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::VoltageL3); break; case (uint8_t)Kamstrup::List3PhaseITLong: meterTimestamp = hanReader.getTime( (uint8_t)Kamstrup_List3Phase::MeterClock, true, true); activeImportCounter = ((float) hanReader.getInt((uint8_t)Kamstrup_List3Phase::CumulativeActiveImportEnergy)) / 100; activeExportCounter = ((float) hanReader.getInt((uint8_t)Kamstrup_List3Phase::CumulativeActiveExportEnergy)) / 100; reactiveImportCounter = ((float) hanReader.getInt((uint8_t)Kamstrup_List3Phase::CumulativeReactiveImportEnergy)) / 100; reactiveExportCounter = ((float) hanReader.getInt((uint8_t)Kamstrup_List3Phase::CumulativeReactiveExportEnergy)) / 100; case (uint8_t)Kamstrup::List3PhaseITShort: listId = hanReader.getString( (uint8_t)Kamstrup_List3Phase::ListVersionIdentifier); meterId = hanReader.getString( (uint8_t)Kamstrup_List3Phase::MeterID); meterModel = hanReader.getString( (uint8_t)Kamstrup_List3Phase::MeterType); activeImportPower = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::ActiveImportPower); reactiveImportPower = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::ReactiveImportPower); activeExportPower = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::ActiveExportPower); reactiveExportPower = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::ReactiveExportPower); l1current = ((float) hanReader.getInt((uint8_t)Kamstrup_List3Phase::CurrentL1)) / 100; l2current = 0; l3current = ((float) hanReader.getInt((uint8_t)Kamstrup_List3Phase::CurrentL3)) / 100; l1voltage = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::VoltageL1); l2voltage = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::VoltageL2); l3voltage = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::VoltageL3); if(substituteMissing) { l2current = (((activeImportPower - activeExportPower) * sqrt(3)) - (l1voltage * l1current) - (l3voltage * l3current)) / l2voltage; } break; } } void AmsData::extractFromOmnipower(HanReader& hanReader, uint8_t listSize) { switch(listSize) { case (uint8_t)Omnipower::DLMS: meterTimestamp = hanReader.getTime( (uint8_t)Omnipower_DLMS::MeterClock, true, true); activeImportCounter = ((float) hanReader.getInt((uint8_t)Omnipower_DLMS::CumulativeActiveImportEnergy)) / 100; activeExportCounter = ((float) hanReader.getInt((uint8_t)Omnipower_DLMS::CumulativeActiveExportEnergy)) / 100; reactiveImportCounter = ((float) hanReader.getInt((uint8_t)Omnipower_DLMS::CumulativeReactiveImportEnergy)) / 100; reactiveExportCounter = ((float) hanReader.getInt((uint8_t)Omnipower_DLMS::CumulativeReactiveExportEnergy)) / 100; listId = hanReader.getString( (uint8_t)Omnipower_DLMS::ListVersionIdentifier); activeImportPower = hanReader.getInt( (uint8_t)Omnipower_DLMS::ActiveImportPower); reactiveImportPower = hanReader.getInt( (uint8_t)Omnipower_DLMS::ReactiveImportPower); activeExportPower = hanReader.getInt( (uint8_t)Omnipower_DLMS::ActiveExportPower); reactiveExportPower = hanReader.getInt( (uint8_t)Omnipower_DLMS::ReactiveExportPower); l1current = ((float) hanReader.getInt((uint8_t)Omnipower_DLMS::CurrentL1)) / 100; l2current = ((float) hanReader.getInt((uint8_t)Omnipower_DLMS::CurrentL2)) / 100; l3current = ((float) hanReader.getInt((uint8_t)Omnipower_DLMS::CurrentL3)) / 100; l1voltage = hanReader.getInt( (uint8_t)Omnipower_DLMS::VoltageL1); l2voltage = hanReader.getInt( (uint8_t)Omnipower_DLMS::VoltageL2); l3voltage = hanReader.getInt( (uint8_t)Omnipower_DLMS::VoltageL3); listType = 3; break; } threePhase = l3voltage != 0; } void AmsData::apply(AmsData& other) { if(other.getListType() < 3) { unsigned long ms = this->lastUpdateMillis > other.getLastUpdateMillis() ? 0 : other.getLastUpdateMillis() - this->lastUpdateMillis; if(ms > 0) { if(other.getActiveImportPower() > 0) activeImportCounter += (((float) ms) * other.getActiveImportPower()) / 3600000000; if(other.getListType() > 1) { if(other.getActiveExportPower() > 0) activeExportCounter += (((float) ms*2) * other.getActiveExportPower()) / 3600000000; if(other.getReactiveImportPower() > 0) reactiveImportCounter += (((float) ms*2) * other.getReactiveImportPower()) / 3600000000; if(other.getReactiveExportPower() > 0) reactiveExportCounter += (((float) ms*2) * other.getReactiveExportPower()) / 3600000000; } counterEstimated = true; } } this->lastUpdateMillis = other.getLastUpdateMillis(); this->packageTimestamp = other.getPackageTimestamp(); if(other.getListType() > this->listType) this->listType = other.getListType(); switch(other.getListType()) { case 3: this->meterTimestamp = other.getMeterTimestamp(); this->activeImportCounter = other.getActiveImportCounter(); this->activeExportCounter = other.getActiveExportCounter(); this->reactiveImportCounter = other.getReactiveImportCounter(); this->reactiveExportCounter = other.getReactiveExportCounter(); this->counterEstimated = false; case 2: this->listId = other.getListId(); this->meterId = other.getMeterId(); this->meterModel = other.getMeterModel(); this->reactiveImportPower = other.getReactiveImportPower(); this->activeExportPower = other.getActiveExportPower(); this->reactiveExportPower = other.getReactiveExportPower(); this->l1current = other.getL1Current(); this->l2current = other.getL2Current(); this->l3current = other.getL3Current(); this->l1voltage = other.getL1Voltage(); this->l2voltage = other.getL2Voltage(); this->l3voltage = other.getL3Voltage(); this->threePhase = other.isThreePhase(); case 1: this->activeImportPower = other.getActiveImportPower(); } } unsigned long AmsData::getLastUpdateMillis() { return this->lastUpdateMillis; } time_t AmsData::getPackageTimestamp() { return this->packageTimestamp; } uint8_t AmsData::getListType() { return this->listType; } String AmsData::getListId() { return this->listId; } String AmsData::getMeterId() { return this->meterId; } String AmsData::getMeterModel() { return this->meterModel; } time_t AmsData::getMeterTimestamp() { return this->meterTimestamp; } uint16_t AmsData::getActiveImportPower() { return this->activeImportPower; } uint16_t AmsData::getReactiveImportPower() { return this->reactiveImportPower; } uint16_t AmsData::getActiveExportPower() { return this->activeExportPower; } uint16_t AmsData::getReactiveExportPower() { return this->reactiveExportPower; } float AmsData::getL1Voltage() { return this->l1voltage; } float AmsData::getL2Voltage() { return this->l2voltage; } float AmsData::getL3Voltage() { return this->l3voltage; } float AmsData::getL1Current() { return this->l1current; } float AmsData::getL2Current() { return this->l2current; } float AmsData::getL3Current() { return this->l3current; } float AmsData::getActiveImportCounter() { return this->activeImportCounter; } float AmsData::getReactiveImportCounter() { return this->reactiveImportCounter; } float AmsData::getActiveExportCounter() { return this->activeExportCounter; } float AmsData::getReactiveExportCounter() { return this->reactiveExportCounter; } bool AmsData::isThreePhase() { return this->threePhase; }