Handle correction configuration for atmp and rhum

From local and cloud
This commit is contained in:
samuelbles07
2025-01-22 01:53:55 +07:00
parent e9b27185b4
commit 88c2437907
3 changed files with 158 additions and 5 deletions

View File

@ -33,6 +33,13 @@ const char *PM_CORRECTION_ALGORITHM_NAMES[] = {
[SLR_PMS5003_20240104] = "slr_PMS5003_20240104",
};
const char *TEMP_HUM_CORRECTION_ALGORITHM_NAMES[] = {
[CA_TH_UNKNOWN] = "-", // This is only to pass "non-trivial designated initializers" error
[CA_TH_NONE] = "none",
[CA_TH_AG_PMS5003T_2024] = "ag_pms5003t_2024",
[CA_TH_SLR_CUSTOM] = "custom",
};
#define JSON_PROP_NAME(name) jprop_##name
#define JSON_PROP_DEF(name) const char *JSON_PROP_NAME(name) = #name
@ -54,6 +61,8 @@ JSON_PROP_DEF(ledBarTestRequested);
JSON_PROP_DEF(offlineMode);
JSON_PROP_DEF(monitorDisplayCompensatedValues);
JSON_PROP_DEF(corrections);
JSON_PROP_DEF(atmp);
JSON_PROP_DEF(rhum);
#define jprop_model_default ""
#define jprop_country_default "TH"
@ -117,6 +126,21 @@ PMCorrectionAlgorithm Configuration::matchPmAlgorithm(String algorithm) {
return result;
}
TempHumCorrectionAlgorithm Configuration::matchTempHumAlgorithm(String algorithm) {
// Get the actual size of the enum
const int enumSize = static_cast<int>(CA_TH_SLR_CUSTOM);
TempHumCorrectionAlgorithm result = CA_TH_UNKNOWN;
// Loop through enum values
for (size_t enumVal = 0; enumVal <= enumSize; enumVal++) {
if (algorithm == TEMP_HUM_CORRECTION_ALGORITHM_NAMES[enumVal]) {
result = static_cast<TempHumCorrectionAlgorithm>(enumVal);
}
}
return result;
}
bool Configuration::updatePmCorrection(JSONVar &json) {
if (!json.hasOwnProperty("corrections")) {
// TODO: need to response message?
@ -205,6 +229,89 @@ bool Configuration::updatePmCorrection(JSONVar &json) {
return true;
}
bool Configuration::updateTempHumCorrection(JSONVar &json, TempHumCorrection &target,
const char *correctionName) {
if (!json.hasOwnProperty(jprop_corrections)) {
// TODO: need to response message?
return false;
}
JSONVar corrections = json[jprop_corrections];
if (!corrections.hasOwnProperty(correctionName)) {
Serial.println("pm02 not found");
logWarning(String(correctionName) + " correction field not found on configuration");
return false;
}
JSONVar correctionTarget = corrections[correctionName];
if (!correctionTarget.hasOwnProperty("correctionAlgorithm")) {
Serial.println("correctionAlgorithm not found");
return false;
}
String algorithm = correctionTarget["correctionAlgorithm"];
TempHumCorrectionAlgorithm algo = matchTempHumAlgorithm(algorithm);
if (algo == CA_TH_UNKNOWN) {
logInfo("Uknown temp/hum algorithm");
return false;
}
logInfo(String(correctionName) + " correction algorithm: " + algorithm);
// If algo is None or Standard, then no need to check slr
// But first check if target correction different from algo
if (algo == CA_TH_NONE || algo == CA_TH_AG_PMS5003T_2024) {
if (target.algorithm != algo) {
// Deep copy corrections from root to jconfig, so it will be saved later
jconfig[jprop_corrections][correctionName]["correctionAlgorithm"] = algorithm;
jconfig[jprop_corrections][correctionName]["slr"] = JSON.parse("{}"); // Clear slr
// Update pmCorrection with new values
target.algorithm = algo;
target.changed = true;
logInfo(String(correctionName) + " correction updated");
return true;
}
return false;
}
// Check if correction.target (atmp or rhum) has slr object
if (!correctionTarget.hasOwnProperty("slr")) {
logWarning(String(correctionName) + " slr not found");
return false;
}
JSONVar slr = correctionTarget["slr"];
// Validate required slr properties exist
if (!slr.hasOwnProperty("intercept") || !slr.hasOwnProperty("scalingFactor")) {
Serial.println("Missing required slr properties");
return false;
}
// arduino_json doesn't support float type, need to cast to double first
float intercept = (float)((double)slr["intercept"]);
float scalingFactor = (float)((double)slr["scalingFactor"]);
// Compare with current target correciont
if (target.algorithm == algo && target.intercept == intercept &&
target.scalingFactor == scalingFactor) {
return false; // No changes needed
}
// Deep copy corrections from root to jconfig, so it will be saved later
jconfig[jprop_corrections] = corrections;
// Update target with new values
target.algorithm = algo;
target.intercept = intercept;
target.scalingFactor = scalingFactor;
target.changed = true;
// Correction values were updated
logInfo(String(correctionName) + " correction updated");
return true;
}
/**
* @brief Save configure to device storage (EEPROM)
*
@ -792,11 +899,21 @@ bool Configuration::parse(String data, bool isLocal) {
}
}
// Corrections
// PM2.5 Corrections
if (updatePmCorrection(root)) {
changed = true;
}
// Temperature correction
if (updateTempHumCorrection(root, tempCorrection, jprop_atmp)) {
changed = true;
}
// Relative humidity correction
if (updateTempHumCorrection(root, rhumCorrection, jprop_rhum)) {
changed = true;
}
if (changed) {
updated = true;
saveConfig();
@ -1248,15 +1365,31 @@ void Configuration::toConfig(const char *buf) {
jprop_monitorDisplayCompensatedValues_default;
}
// Set default first before parsing local config
// PM2.5 correction
/// Set default first before parsing local config
pmCorrection.algorithm = PMCorrectionAlgorithm::None;
pmCorrection.intercept = 0;
pmCorrection.scalingFactor = 0;
pmCorrection.useEPA = false;
// Load correction from saved config
/// Load correction from saved config
updatePmCorrection(jconfig);
// Temperature correction
/// Set default first before parsing local config
tempCorrection.algorithm = CA_TH_NONE;
tempCorrection.intercept = 0;
tempCorrection.scalingFactor = 0;
/// Load correction from saved config
updateTempHumCorrection(jconfig, tempCorrection, jprop_atmp);
// Relative humidity correction
/// Set default first before parsing local config
rhumCorrection.algorithm = CA_TH_NONE;
rhumCorrection.intercept = 0;
rhumCorrection.scalingFactor = 0;
/// Load correction from saved config
updateTempHumCorrection(jconfig, rhumCorrection, jprop_rhum);
if (changed) {
saveConfig();
}

View File

@ -17,6 +17,13 @@ public:
bool changed;
};
struct TempHumCorrection {
TempHumCorrectionAlgorithm algorithm;
float intercept;
float scalingFactor;
bool changed;
};
private:
bool co2CalibrationRequested;
bool ledBarTestRequested;
@ -30,12 +37,17 @@ private:
bool _offlineMode = false;
bool _ledBarModeChanged = false;
PMCorrection pmCorrection;
TempHumCorrection tempCorrection;
TempHumCorrection rhumCorrection;
AirGradient* ag;
String getLedBarModeName(LedBarMode mode);
PMCorrectionAlgorithm matchPmAlgorithm(String algorithm);
TempHumCorrectionAlgorithm matchTempHumAlgorithm(String algorithm);
bool updatePmCorrection(JSONVar &json);
bool updateTempHumCorrection(JSONVar &json, TempHumCorrection &target,
const char *correctionName);
void saveConfig(void);
void loadConfig(void);
void defaultConfig(void);
@ -46,7 +58,7 @@ private:
void configLogInfo(String name, String fromValue, String toValue);
String getPMStandardString(bool usaqi);
String getAbcDayString(int value);
void toConfig(const char* buf);
void toConfig(const char *buf);
public:
Configuration(Stream &debugLog);

View File

@ -106,6 +106,14 @@ enum PMCorrectionAlgorithm {
SLR_PMS5003_20240104,
};
// Don't change the order of the enum
enum TempHumCorrectionAlgorithm {
CA_TH_UNKNOWN, // Unknown algorithm
CA_TH_NONE, // No PM correction
CA_TH_AG_PMS5003T_2024,
CA_TH_SLR_CUSTOM
};
enum AgFirmwareMode {
FW_MODE_I_9PSL, /** ONE_INDOOR */
FW_MODE_O_1PST, /** PMS5003T, S8 and SGP41 */