forked from airgradienthq/arduino
Handle correction configuration for atmp and rhum
From local and cloud
This commit is contained in:
@ -33,6 +33,13 @@ const char *PM_CORRECTION_ALGORITHM_NAMES[] = {
|
|||||||
[SLR_PMS5003_20240104] = "slr_PMS5003_20240104",
|
[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_NAME(name) jprop_##name
|
||||||
#define JSON_PROP_DEF(name) const char *JSON_PROP_NAME(name) = #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(offlineMode);
|
||||||
JSON_PROP_DEF(monitorDisplayCompensatedValues);
|
JSON_PROP_DEF(monitorDisplayCompensatedValues);
|
||||||
JSON_PROP_DEF(corrections);
|
JSON_PROP_DEF(corrections);
|
||||||
|
JSON_PROP_DEF(atmp);
|
||||||
|
JSON_PROP_DEF(rhum);
|
||||||
|
|
||||||
#define jprop_model_default ""
|
#define jprop_model_default ""
|
||||||
#define jprop_country_default "TH"
|
#define jprop_country_default "TH"
|
||||||
@ -117,6 +126,21 @@ PMCorrectionAlgorithm Configuration::matchPmAlgorithm(String algorithm) {
|
|||||||
return result;
|
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) {
|
bool Configuration::updatePmCorrection(JSONVar &json) {
|
||||||
if (!json.hasOwnProperty("corrections")) {
|
if (!json.hasOwnProperty("corrections")) {
|
||||||
// TODO: need to response message?
|
// TODO: need to response message?
|
||||||
@ -205,6 +229,89 @@ bool Configuration::updatePmCorrection(JSONVar &json) {
|
|||||||
return true;
|
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)
|
* @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)) {
|
if (updatePmCorrection(root)) {
|
||||||
changed = true;
|
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) {
|
if (changed) {
|
||||||
updated = true;
|
updated = true;
|
||||||
saveConfig();
|
saveConfig();
|
||||||
@ -1248,15 +1365,31 @@ void Configuration::toConfig(const char *buf) {
|
|||||||
jprop_monitorDisplayCompensatedValues_default;
|
jprop_monitorDisplayCompensatedValues_default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PM2.5 correction
|
||||||
// Set default first before parsing local config
|
/// Set default first before parsing local config
|
||||||
pmCorrection.algorithm = PMCorrectionAlgorithm::None;
|
pmCorrection.algorithm = PMCorrectionAlgorithm::None;
|
||||||
pmCorrection.intercept = 0;
|
pmCorrection.intercept = 0;
|
||||||
pmCorrection.scalingFactor = 0;
|
pmCorrection.scalingFactor = 0;
|
||||||
pmCorrection.useEPA = false;
|
pmCorrection.useEPA = false;
|
||||||
// Load correction from saved config
|
/// Load correction from saved config
|
||||||
updatePmCorrection(jconfig);
|
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) {
|
if (changed) {
|
||||||
saveConfig();
|
saveConfig();
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,13 @@ public:
|
|||||||
bool changed;
|
bool changed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TempHumCorrection {
|
||||||
|
TempHumCorrectionAlgorithm algorithm;
|
||||||
|
float intercept;
|
||||||
|
float scalingFactor;
|
||||||
|
bool changed;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool co2CalibrationRequested;
|
bool co2CalibrationRequested;
|
||||||
bool ledBarTestRequested;
|
bool ledBarTestRequested;
|
||||||
@ -30,12 +37,17 @@ private:
|
|||||||
bool _offlineMode = false;
|
bool _offlineMode = false;
|
||||||
bool _ledBarModeChanged = false;
|
bool _ledBarModeChanged = false;
|
||||||
PMCorrection pmCorrection;
|
PMCorrection pmCorrection;
|
||||||
|
TempHumCorrection tempCorrection;
|
||||||
|
TempHumCorrection rhumCorrection;
|
||||||
|
|
||||||
AirGradient* ag;
|
AirGradient* ag;
|
||||||
|
|
||||||
String getLedBarModeName(LedBarMode mode);
|
String getLedBarModeName(LedBarMode mode);
|
||||||
PMCorrectionAlgorithm matchPmAlgorithm(String algorithm);
|
PMCorrectionAlgorithm matchPmAlgorithm(String algorithm);
|
||||||
|
TempHumCorrectionAlgorithm matchTempHumAlgorithm(String algorithm);
|
||||||
bool updatePmCorrection(JSONVar &json);
|
bool updatePmCorrection(JSONVar &json);
|
||||||
|
bool updateTempHumCorrection(JSONVar &json, TempHumCorrection &target,
|
||||||
|
const char *correctionName);
|
||||||
void saveConfig(void);
|
void saveConfig(void);
|
||||||
void loadConfig(void);
|
void loadConfig(void);
|
||||||
void defaultConfig(void);
|
void defaultConfig(void);
|
||||||
@ -46,7 +58,7 @@ private:
|
|||||||
void configLogInfo(String name, String fromValue, String toValue);
|
void configLogInfo(String name, String fromValue, String toValue);
|
||||||
String getPMStandardString(bool usaqi);
|
String getPMStandardString(bool usaqi);
|
||||||
String getAbcDayString(int value);
|
String getAbcDayString(int value);
|
||||||
void toConfig(const char* buf);
|
void toConfig(const char *buf);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Configuration(Stream &debugLog);
|
Configuration(Stream &debugLog);
|
||||||
|
@ -106,6 +106,14 @@ enum PMCorrectionAlgorithm {
|
|||||||
SLR_PMS5003_20240104,
|
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 {
|
enum AgFirmwareMode {
|
||||||
FW_MODE_I_9PSL, /** ONE_INDOOR */
|
FW_MODE_I_9PSL, /** ONE_INDOOR */
|
||||||
FW_MODE_O_1PST, /** PMS5003T, S8 and SGP41 */
|
FW_MODE_O_1PST, /** PMS5003T, S8 and SGP41 */
|
||||||
|
Reference in New Issue
Block a user