From 16c932962a60c72296af04c1b9642d304359cc9c Mon Sep 17 00:00:00 2001 From: samuelbles07 Date: Sat, 2 Nov 2024 00:10:08 +0700 Subject: [PATCH] Handle pm correction algorithm from ag server config --- src/AgConfigure.cpp | 114 ++++++++++++++++++++++++++++++++++++++++++++ src/AgConfigure.h | 13 +++++ src/App/AppDef.h | 12 +++++ 3 files changed, 139 insertions(+) diff --git a/src/AgConfigure.cpp b/src/AgConfigure.cpp index 1446d1a..5e438af 100644 --- a/src/AgConfigure.cpp +++ b/src/AgConfigure.cpp @@ -22,6 +22,18 @@ const char *LED_BAR_MODE_NAMES[] = { [LedBarModeCO2] = "co2", }; +const char *PM_CORRECTION_ALGORITHM_NAMES[] = { + [Unknown] = "-", // This is only to pass "non-trivial designated initializers" error + [None] = "none", + [EPA_2021] = "epa_2021", + [SLR_PMS5003_20220802] = "slr_PMS5003_20220802", + [SLR_PMS5003_20220803] = "slr_PMS5003_20220803", + [SLR_PMS5003_20220824] = "slr_PMS5003_20220824", + [SLR_PMS5003_20231030] = "slr_PMS5003_20231030", + [SLR_PMS5003_20231218] = "slr_PMS5003_20231218", + [SLR_PMS5003_20240104] = "slr_PMS5003_20240104", +}; + #define JSON_PROP_NAME(name) jprop_##name #define JSON_PROP_DEF(name) const char *JSON_PROP_NAME(name) = #name @@ -87,6 +99,96 @@ String Configuration::getLedBarModeName(LedBarMode mode) { return String("unknown"); } +PMCorrectionAlgorithm Configuration::matchPmAlgorithm(String algorithm) { + // Loop through all algorithm names in the PM_CORRECTION_ALGORITHM_NAMES array + // If the input string matches an algorithm name, return the corresponding enum value + // Else return Unknown + for (int idx = 0; + idx < sizeof(PM_CORRECTION_ALGORITHM_NAMES) / sizeof(PM_CORRECTION_ALGORITHM_NAMES[0]); + idx++) { + if (algorithm == PM_CORRECTION_ALGORITHM_NAMES[idx]) { + return (PMCorrectionAlgorithm)idx; + } + } + + return Unknown; +} + +bool Configuration::parsePmCorrection(JSONVar &json) { + if (!json.hasOwnProperty("corrections")) { + // TODO: need to response message? + Serial.println("corrections not found"); + return false; + } + + JSONVar corrections = json["corrections"]; + if (!corrections.hasOwnProperty("pm02")) { + Serial.println("pm02 not found"); + return false; + } + + JSONVar pm02 = corrections["pm02"]; + if (!pm02.hasOwnProperty("correctionAlgorithm")) { + Serial.println("correctionAlgorithm not found"); + return false; + } + + // Check algorithm + const char *algorithm = (const char *)pm02["correctionAlgorithm"]; + PMCorrectionAlgorithm algo = matchPmAlgorithm(algorithm); + if (algo == Unknown) { + Serial.println("Unknown algorithm"); + return false; + } + Serial.printf("Correction algorithm: %s\n", algorithm); + + // If algo is None or EPA_2021, no need to check slr + // But first check if pmCorrection different from algo + if (algo == None || algo == EPA_2021) { + if (pmCorrection.algorithm != algo) { + pmCorrection.algorithm = algo; + pmCorrection.changed = true; + Serial.println("PM2.5 correction updated"); + return true; + } + + return false; + } + + // Check if pm02 has slr object + if (!pm02.hasOwnProperty("slr")) { + Serial.println("slr not found"); + return false; + } + + JSONVar slr = pm02["slr"]; + + // Validate required slr properties exist + if (!slr.hasOwnProperty("intercept") || !slr.hasOwnProperty("scalingFactor") || + !slr.hasOwnProperty("useEpa2021")) { + Serial.println("Missing required slr properties"); + return false; + } + + // Compare with current pmCorrection + if (pmCorrection.algorithm == algo && pmCorrection.intercept == (double)slr["intercept"] && + pmCorrection.scalingFactor == (double)slr["scalingFactor"] && + pmCorrection.useEPA == (bool)slr["useEpa2021"]) { + return false; // No changes needed + } + + // Update pmCorrection with new values + pmCorrection.algorithm = algo; + pmCorrection.intercept = (double)slr["intercept"]; + pmCorrection.scalingFactor = (double)slr["scalingFactor"]; + pmCorrection.useEPA = (bool)slr["useEpa2021"]; + pmCorrection.changed = true; + + // Correction values were updated + Serial.println("PM2.5 correction updated"); + return true; +} + /** * @brief Save configure to device storage (EEPROM) * @@ -171,6 +273,13 @@ void Configuration::defaultConfig(void) { jconfig[jprop_offlineMode] = jprop_offlineMode_default; jconfig[jprop_monitorDisplayCompensatedValues] = jprop_monitorDisplayCompensatedValues_default; + // PM2.5 correction + pmCorrection.algorithm = None; + pmCorrection.changed = false; + pmCorrection.intercept = -1; + pmCorrection.scalingFactor = -1; + pmCorrection.useEPA = false; + saveConfig(); } @@ -667,6 +776,11 @@ bool Configuration::parse(String data, bool isLocal) { } } + // Corrections + if (parsePmCorrection(root)) { + changed = true; + } + if (changed) { udpated = true; saveConfig(); diff --git a/src/AgConfigure.h b/src/AgConfigure.h index a899b64..3a7be13 100644 --- a/src/AgConfigure.h +++ b/src/AgConfigure.h @@ -5,8 +5,18 @@ #include "Main/PrintLog.h" #include "AirGradient.h" #include +#include "Libraries/Arduino_JSON/src/Arduino_JSON.h" class Configuration : public PrintLog { +public: + struct PMCorrection { + PMCorrectionAlgorithm algorithm; + int intercept; + int scalingFactor; + bool useEPA; // EPA 2021 + bool changed; + }; + private: bool co2CalibrationRequested; bool ledBarTestRequested; @@ -19,10 +29,13 @@ private: String otaNewFirmwareVersion; bool _offlineMode = false; bool _ledBarModeChanged = false; + PMCorrection pmCorrection; AirGradient* ag; String getLedBarModeName(LedBarMode mode); + PMCorrectionAlgorithm matchPmAlgorithm(String algorithm); + bool parsePmCorrection(JSONVar &json); void saveConfig(void); void loadConfig(void); void defaultConfig(void); diff --git a/src/App/AppDef.h b/src/App/AppDef.h index 3bb9320..1e114e7 100644 --- a/src/App/AppDef.h +++ b/src/App/AppDef.h @@ -94,6 +94,18 @@ enum ConfigurationControl { ConfigurationControlBoth }; +enum PMCorrectionAlgorithm { + Unknown, // Unknown algorithm + None, // No PM correction + EPA_2021, + SLR_PMS5003_20220802, + SLR_PMS5003_20220803, + SLR_PMS5003_20220824, + SLR_PMS5003_20231030, + SLR_PMS5003_20231218, + SLR_PMS5003_20240104, +}; + enum AgFirmwareMode { FW_MODE_I_9PSL, /** ONE_INDOOR */ FW_MODE_O_1PST, /** PMS5003T, S8 and SGP41 */