From 9c09b82efdd59082d0ae3f936d56d98dcd3622da Mon Sep 17 00:00:00 2001 From: samuelbles07 Date: Fri, 11 Oct 2024 20:54:05 +0700 Subject: [PATCH] The data structure and update value function --- src/AgValue.cpp | 178 +++++++++++++++++++++++++++++++++++++++++++++++- src/AgValue.h | 96 ++++++++++++++++---------- 2 files changed, 236 insertions(+), 38 deletions(-) diff --git a/src/AgValue.cpp b/src/AgValue.cpp index 867ee42..0b3cfbc 100644 --- a/src/AgValue.cpp +++ b/src/AgValue.cpp @@ -1,7 +1,6 @@ #include "AgValue.h" #include "AgConfigure.h" #include "AirGradient.h" -#include "Main/utils.h" #include "Libraries/Arduino_JSON/src/Arduino_JSON.h" #define json_prop_pmFirmware "firmware" @@ -37,6 +36,183 @@ String Measurements::pms5003FirmwareVersionBase(String prefix, int fwCode) { return prefix + String("-") + String(fwCode); } +String Measurements::agValueTypeStr(AgValueType type) { + String str; + switch (type) { + case AgValueType::Temperature: + str = "Temperature"; + break; + case AgValueType::Humidity: + str = "Humidity"; + break; + case AgValueType::CO2: + str = "CO2"; + break; + case AgValueType::TVOC: + str = "TVOC"; + break; + case AgValueType::TVOCRaw: + str = "TVOCRaw"; + break; + case AgValueType::NOx: + str = "NOx"; + break; + case AgValueType::NOxRaw: + str = "NOxRaw"; + break; + case AgValueType::PM25: + str = "PM25"; + break; + case AgValueType::PM01: + str = "PM01"; + break; + case AgValueType::PM10: + str = "PM10"; + break; + case AgValueType::PM03: + str = "PM03"; + break; + default: + break; + }; + + return str; +} + +void Measurements::updateValue(AgValueType type, int val) { + // Define data point source + IntegerValue *temporary = nullptr; + float invalidValue = 0; + switch (type) { + case AgValueType::CO2: + temporary = &_co2; + invalidValue = utils::getInvalidCO2(); + break; + case AgValueType::TVOC: + temporary = &_tvoc; + invalidValue = utils::getInvalidVOC(); + break; + case AgValueType::TVOCRaw: + temporary = &_tvoc_raw; + invalidValue = utils::getInvalidVOC(); + break; + case AgValueType::NOx: + temporary = &_nox; + invalidValue = utils::getInvalidNOx(); + break; + case AgValueType::NOxRaw: + temporary = &_nox_raw; + invalidValue = utils::getInvalidNOx(); + break; + case AgValueType::PM25: + temporary = &_pm_25; + invalidValue = utils::getInvalidPmValue(); + break; + case AgValueType::PM01: + temporary = &_pm_01; + invalidValue = utils::getInvalidPmValue(); + break; + case AgValueType::PM10: + temporary = &_pm_10; + invalidValue = utils::getInvalidPmValue(); + break; + case AgValueType::PM03: + temporary = &_pm_03_pc; + invalidValue = utils::getInvalidPmValue(); + break; + default: + break; + }; + + // Sanity check if agvaluetype is defined for integer data type or not + if (temporary == nullptr) { + Serial.printf("%s is not defined for integer data type\n", agValueTypeStr(type)); + // TODO: Just assert? + return; + } + + // Update new value when value provided is not the invalid one + if (val != invalidValue) { + temporary->lastValue = val; + temporary->sumValues = temporary->sumValues + val; + temporary->read.success = temporary->read.success + 1; + } + + // Increment read counter + temporary->read.counter = temporary->read.counter + 1; + + // Calculate value average when maximum set is reached + if (temporary->read.counter >= temporary->read.max) { + // Calculate the average + temporary->avg = temporary->sumValues / temporary->read.success; + + // This is just for notifying + int miss = temporary->read.max - temporary->read.success; + if (miss != 0) { + Serial.printf("%s reading miss %d out of %d update\n", agValueTypeStr(type), miss, + temporary->read.max); + } + + // Resets the sum data and read variables + temporary->sumValues = 0; + temporary->read.counter = 0; + temporary->read.success = 0; + } +} + +void Measurements::updateValue(AgValueType type, float val) { + // Define data point source + FloatValue *temporary = nullptr; + float invalidValue = 0; + switch (type) { + case AgValueType::Temperature: + temporary = &_temperature; + invalidValue = utils::getInvalidTemperature(); + break; + case AgValueType::Humidity: + temporary = &_humidity; + invalidValue = utils::getInvalidHumidity(); + break; + default: + break; + } + + // Sanity check if agvaluetype is defined for float data type or not + if (temporary == nullptr) { + Serial.printf("%s is not defined for float data type\n", agValueTypeStr(type)); + // TODO: Just assert? + return; + } + + // Update new value when value provided is not the invalid one + if (val != invalidValue) { + temporary->lastValue = val; + temporary->sumValues = temporary->sumValues + val; + temporary->read.success = temporary->read.success + 1; + } + + // Increment read counter + temporary->read.counter = temporary->read.counter + 1; + + // Calculate value average when maximum set is reached + if (temporary->read.counter >= temporary->read.max) { + // Calculate the average + temporary->avg = temporary->sumValues / temporary->read.success; + + // This is just for notifying + int miss = temporary->read.max - temporary->read.success; + if (miss != 0) { + Serial.printf("%s reading miss %d out of %d update\n", agValueTypeStr(type), miss, + temporary->read.max); + } + + // Resets the sum data and read variables + temporary->sumValues = 0; + temporary->read.counter = 0; + temporary->read.success = 0; + } +} + String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, void *_ag, void *_config) { AirGradient *ag = (AirGradient *)_ag; diff --git a/src/AgValue.h b/src/AgValue.h index c3432b3..b8476f4 100644 --- a/src/AgValue.h +++ b/src/AgValue.h @@ -1,14 +1,36 @@ #ifndef _AG_VALUE_H_ #define _AG_VALUE_H_ -#include #include "App/AppDef.h" +#include "Main/utils.h" +#include class Measurements { private: - String pms5003FirmwareVersion(int fwCode); - String pms5003TFirmwareVersion(int fwCode); - String pms5003FirmwareVersionBase(String prefix, int fwCode); + // Generic struct for reading indication for respective value + // TODO: Reading naming is confusing, because its not actually reading but updating with new value + struct Reading { + int counter; // How many reading attempts done + int success; // How many reading that success from each attempts + int max; // Maximum reading attempt + }; + + // Reading type for sensor value that outputs float + struct FloatValue { + float lastValue; // Last reading value + float sumValues; // Total value of each reading + float avg; // The last average calculation after maximum reading attempt reached + Reading read; + }; + + // Reading type for sensor value that outputs integer + struct IntegerValue { + int lastValue; // Last reading value + unsigned long sumValues; // Total value of each reading // TODO: explain why unsigned long + int avg; // The last average calculation after maximum reading attempt reached + Reading read; + }; + public: Measurements() { pm25_1 = -1; @@ -35,40 +57,22 @@ public: } ~Measurements() {} - // Generic struct for reading indication for respective value - struct Reading { - int counter; // How many reading attempts done - int success; // How many reading that success from each attempts - int max; // Maximum reading attempt + enum class AgValueType { + Temperature, + Humidity, + CO2, + TVOC, + TVOCRaw, + NOx, + NOxRaw, + PM25, + PM01, + PM10, + PM03, }; - // Reading type for sensor value that outputs float - struct FloatValue { - float lastValue; // Last reading value - float sumValues; // Total value of each reading - float avg; // The last average calculation after maximum reading attempt reached - Reading read; - }; - - // Reading type for sensor value that outputs integer - struct IntegerValue { - int lastValue; // Last reading value - unsigned long sumValues; // Total value of each reading - int avg; // The last average calculation after maximum reading attempt reached - Reading read; - }; - - FloatValue temperature; - FloatValue humidity; - IntegerValue co2; - IntegerValue tvoc; - IntegerValue tvoc_raw; - IntegerValue nox; - IntegerValue nox_raw; - IntegerValue pm_25; - IntegerValue pm_01; - IntegerValue pm_10; - IntegerValue pm_03_pc; + void updateValue(AgValueType type, int val); + void updateValue(AgValueType type, float val); float Temperature; int Humidity; @@ -108,7 +112,25 @@ public: const int targetCount = 20; int bootCount; - String toString(bool isLocal, AgFirmwareMode fwMode, int rssi, void* _ag, void* _config); + String toString(bool isLocal, AgFirmwareMode fwMode, int rssi, void *_ag, void *_config); + +private: + FloatValue _temperature; + FloatValue _humidity; + IntegerValue _co2; + IntegerValue _tvoc; + IntegerValue _tvoc_raw; + IntegerValue _nox; + IntegerValue _nox_raw; + IntegerValue _pm_25; + IntegerValue _pm_01; + IntegerValue _pm_10; + IntegerValue _pm_03_pc; // particle count 0.3 + + String pms5003FirmwareVersion(int fwCode); + String pms5003TFirmwareVersion(int fwCode); + String pms5003FirmwareVersionBase(String prefix, int fwCode); + String agValueTypeStr(AgValueType type); }; #endif /** _AG_VALUE_H_ */