From 556a6fbd6d5607f71b9c44bde0e01d3218cfdc76 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Sun, 21 Apr 2024 16:33:55 +0700 Subject: [PATCH 01/10] update mqtt publish data is locally --- examples/OneOpenAir/OneOpenAir.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/OneOpenAir/OneOpenAir.ino b/examples/OneOpenAir/OneOpenAir.ino index b6ac178..1fe7376 100644 --- a/examples/OneOpenAir/OneOpenAir.ino +++ b/examples/OneOpenAir/OneOpenAir.ino @@ -301,7 +301,7 @@ static void createMqttTask(void) { /** Send data */ if (mqttClient.isConnected()) { String payload = measurements.toString( - false, fwMode, wifiConnector.RSSI(), ag, &configuration); + true, fwMode, wifiConnector.RSSI(), ag, &configuration); String topic = "airgradient/readings/" + ag->deviceId(); if (mqttClient.publish(topic.c_str(), payload.c_str(), From 89802551a09157972ff90c71222e3db5e68d0d8c Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Sun, 21 Apr 2024 16:44:43 +0700 Subject: [PATCH 02/10] update `CO2CalibrationAbcDays` --- src/AgConfigure.cpp | 6 ++---- src/AgStateMachine.cpp | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/AgConfigure.cpp b/src/AgConfigure.cpp index 5425355..4469006 100644 --- a/src/AgConfigure.cpp +++ b/src/AgConfigure.cpp @@ -126,7 +126,7 @@ void Configuration::defaultConfig(void) { config.postDataToAirGradient = true; config.displayMode = true; config.useRGBLedBar = LedBarMode::LedBarModeCO2; - config.abcDays = 7; + config.abcDays = 8; config.tvocLearningOffset = 12; config.noxLearningOffset = 12; config.temperatureUnit = 'c'; @@ -382,9 +382,7 @@ bool Configuration::parse(String data, bool isLocal) { if (JSON.typeof_(root["abcDays"]) == "number") { int abcDays = root["abcDays"]; if (abcDays <= 0) { - failedMessage = jsonTypeInvalidMessage("abcDaysabcDays", String(abcDays)); - jsonInvalid(); - return false; + abcDays = 0; } if (abcDays != config.abcDays) { config.abcDays = abcDays; diff --git a/src/AgStateMachine.cpp b/src/AgStateMachine.cpp index b45c415..27c2ce1 100644 --- a/src/AgStateMachine.cpp +++ b/src/AgStateMachine.cpp @@ -276,7 +276,7 @@ void StateMachine::co2Calibration(void) { } } - if (config.getCO2CalibrationAbcDays() > 0 && config.hasSensorS8) { + if (config.getCO2CalibrationAbcDays() >= 0 && config.hasSensorS8) { int newHour = config.getCO2CalibrationAbcDays() * 24; logInfo("Requested abcDays setting: " + String(config.getCO2CalibrationAbcDays()) + "days (" + From a91f6c1fa0fdda2a830859d01b0f24f311a4c7db Mon Sep 17 00:00:00 2001 From: Achim Date: Sun, 21 Apr 2024 17:28:56 +0700 Subject: [PATCH 03/10] Added documentation for Open Metrics --- examples/OneOpenAir/OpenMetrics.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/OneOpenAir/OpenMetrics.cpp b/examples/OneOpenAir/OpenMetrics.cpp index 7d84057..12ad15c 100644 --- a/examples/OneOpenAir/OpenMetrics.cpp +++ b/examples/OneOpenAir/OpenMetrics.cpp @@ -179,7 +179,7 @@ String OpenMetrics::getPayload(void) { if (_temp > -1001) { add_metric("temperature", - "The ambient temperature as measured by the AirGradient SHT " + "The ambient temperature as measured by the AirGradient SHT / PMS " "sensor, in degrees Celsius", "gauge", "celsius"); add_metric_point("", String(_temp)); @@ -187,21 +187,22 @@ String OpenMetrics::getPayload(void) { if (atmpCompensated > -1001) { add_metric( "temperature_compensated", - "The ambient temperature as measured by the AirGradient SHT / PMS", + "The compensated ambient temperature as measured by the AirGradient SHT / PMS " + "sensor, in degrees Celsius", "gauge", "celsius"); add_metric_point("", String(atmpCompensated)); } if (_hum >= 0) { add_metric( "humidity", - "The relative humidity as measured by the AirGradient SHT sensor", + "The relative humidity as measured by the AirGradient SHT sensor" "gauge", "percent"); add_metric_point("", String(_hum)); } if (ahumCompensated >= 0) { add_metric( "humidity_compensated", - "The relative humidity as measured by the AirGradient SHT / PMS sensor", + "The compensated relative humidity as measured by the AirGradient SHT / PMS sensor", "gauge", "percent"); add_metric_point("", String(ahumCompensated)); } From d5fc35df2f62ace1be3b100286d8eb07ff2bbf40 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Sun, 21 Apr 2024 21:03:02 +0700 Subject: [PATCH 04/10] Add _compensated to log output --- examples/OneOpenAir/OneOpenAir.ino | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/examples/OneOpenAir/OneOpenAir.ino b/examples/OneOpenAir/OneOpenAir.ino index 1fe7376..aff6da7 100644 --- a/examples/OneOpenAir/OneOpenAir.ino +++ b/examples/OneOpenAir/OneOpenAir.ino @@ -787,6 +787,10 @@ static void updatePm(void) { Serial.printf("[1] PM3.0 Count: %d\r\n", measurements.pm03PCount_1); Serial.printf("[1] Temperature in C: %0.2f\r\n", measurements.temp_1); Serial.printf("[1] Relative Humidity: %d\r\n", measurements.hum_1); + Serial.printf("[1] Temperature compensated in C: %0.2f\r\n", + ag->pms5003t_1.temperatureCompensated(measurements.temp_1)); + Serial.printf("[1] Relative Humidity compensated: %d\r\n", + ag->pms5003t_1.humidityCompensated(measurements.hum_1)); } else { measurements.pm01_1 = -1; measurements.pm25_1 = -1; @@ -813,6 +817,10 @@ static void updatePm(void) { Serial.printf("[2] PM3.0 Count: %d\r\n", measurements.pm03PCount_2); Serial.printf("[2] Temperature in C: %0.2f\r\n", measurements.temp_2); Serial.printf("[2] Relative Humidity: %d\r\n", measurements.hum_2); + Serial.printf("[2] Temperature compensated in C: %0.2f\r\n", + ag->pms5003t_1.temperatureCompensated(measurements.temp_2)); + Serial.printf("[2] Relative Humidity compensated: %d\r\n", + ag->pms5003t_1.humidityCompensated(measurements.hum_2)); } else { measurements.pm01_2 = -1; measurements.pm25_2 = -1; @@ -939,6 +947,10 @@ static void tempHumUpdate(void) { Serial.printf("Temperature in C: %0.2f\r\n", measurements.Temperature); Serial.printf("Relative Humidity: %d\r\n", measurements.Humidity); + Serial.printf("Temperature compensated in C: %0.2f\r\n", + ag->pms5003t_1.temperatureCompensated(measurements.Temperature)); + Serial.printf("Relative Humidity compensated: %d\r\n", + ag->pms5003t_1.humidityCompensated(measurements.Temperature)); // Update compensation temperature and humidity for SGP41 if (configuration.hasSensorSGP) { From 7561017b3d641177900752c90ccb4031d24b008c Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Mon, 22 Apr 2024 06:27:57 +0700 Subject: [PATCH 05/10] update log message and fix `ledBarTestRequested`, `co2CalibrationRequested` not execute --- src/AgConfigure.cpp | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/AgConfigure.cpp b/src/AgConfigure.cpp index 4469006..7bd551c 100644 --- a/src/AgConfigure.cpp +++ b/src/AgConfigure.cpp @@ -178,6 +178,8 @@ bool Configuration::begin(void) { * @return false Failure */ bool Configuration::parse(String data, bool isLocal) { + logInfo("Parse configure: " + data); + JSONVar root = JSON.parse(data); failedMessage = ""; if (JSON.typeof_(root) == "undefined") { @@ -477,19 +479,21 @@ bool Configuration::parse(String data, bool isLocal) { logInfo("set temperatureUnit: " + String(temperatureUnit)); } - if (JSON.typeof_(root["postDataToAirGradient"]) == "boolean") { - bool post = root["postDataToAirGradient"]; - if (post != config.postDataToAirGradient) { - changed = true; - config.postDataToAirGradient = post; - logInfo("Set postDataToAirGradient: " + String(post)); - } - } else { - if (jsonTypeInvalid(root["postDataToAirGradient"], "boolean")) { - failedMessage = - jsonTypeInvalidMessage("postDataToAirGradient", "boolean"); - jsonInvalid(); - return false; + if (isLocal) { + if (JSON.typeof_(root["postDataToAirGradient"]) == "boolean") { + bool post = root["postDataToAirGradient"]; + if (post != config.postDataToAirGradient) { + changed = true; + config.postDataToAirGradient = post; + logInfo("Set postDataToAirGradient: " + String(post)); + } + } else { + if (jsonTypeInvalid(root["postDataToAirGradient"], "boolean")) { + failedMessage = + jsonTypeInvalidMessage("postDataToAirGradient", "boolean"); + jsonInvalid(); + return false; + } } } @@ -520,6 +524,10 @@ bool Configuration::parse(String data, bool isLocal) { if (changed) { udpated = true; saveConfig(); + } else { + if (ledBarTestRequested || co2CalibrationRequested) { + udpated = true; + } } printConfig(); return true; From 2d96fc28c5bd419ea3f4a32c82a41eccf50b3425 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Mon, 22 Apr 2024 14:24:01 +0700 Subject: [PATCH 06/10] fix `postDataToAirGradient` set `false` after device power up and connected to WiFi --- src/AgWiFiConnector.cpp | 14 +++++++++++--- src/AgWiFiConnector.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/AgWiFiConnector.cpp b/src/AgWiFiConnector.cpp index 7a94547..0e7f291 100644 --- a/src/AgWiFiConnector.cpp +++ b/src/AgWiFiConnector.cpp @@ -46,6 +46,7 @@ bool WifiConnector::connect(void) { } WIFI()->setConfigPortalBlocking(false); + WIFI()->setConnectTimeout(15); WIFI()->setTimeout(WIFI_CONNECT_COUNTDOWN_MAX); #ifdef ESP32 @@ -148,9 +149,15 @@ bool WifiConnector::connect(void) { hasConfig = true; logInfo("WiFi Connected: " + WiFi.SSID() + " IP: " + localIpStr()); - String result = String(postToAg.getValue()); - logInfo("Post to AirGradient Configure: " + result); - config.setPostToAirGradient(result != "T"); + if (hasPortalConfig) { + String result = String(postToAg.getValue()); + logInfo("Setting postToAirGradient set from " + + String(config.isPostDataToAirGradient() ? "True" : "False") + + String(" to ") + String(result != "T" ? "True" : "False") + + String(" successful")); + config.setPostToAirGradient(result != "T"); + } + hasPortalConfig = false; } #else _wifiProcess(); @@ -226,6 +233,7 @@ void WifiConnector::_wifiSaveParamCallback(void) { sm.ledAnimationInit(); sm.handleLeds(AgStateMachineWiFiManagerStaConnecting); sm.setDisplayState(AgStateMachineWiFiManagerStaConnecting); + hasPortalConfig = true; } /** diff --git a/src/AgWiFiConnector.h b/src/AgWiFiConnector.h index 9de182d..3856f62 100644 --- a/src/AgWiFiConnector.h +++ b/src/AgWiFiConnector.h @@ -23,6 +23,7 @@ private: void *wifi = NULL; bool hasConfig; uint32_t lastRetry; + bool hasPortalConfig = false; bool wifiClientConnected(void); From b91a3058fce9f950ae34b447ed2311960a30cdd8 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Mon, 22 Apr 2024 16:30:57 +0700 Subject: [PATCH 07/10] Move common function to separate file --- src/PMS/PMS5003T.cpp | 15 --------------- src/PMS/PMS5003T.h | 5 ++--- src/PMS/PMS5003TBase.cpp | 21 +++++++++++++++++++++ src/PMS/PMS5003TBase.h | 15 +++++++++++++++ 4 files changed, 38 insertions(+), 18 deletions(-) create mode 100644 src/PMS/PMS5003TBase.cpp create mode 100644 src/PMS/PMS5003TBase.h diff --git a/src/PMS/PMS5003T.cpp b/src/PMS/PMS5003T.cpp index 838ab7d..f0f9a1d 100644 --- a/src/PMS/PMS5003T.cpp +++ b/src/PMS/PMS5003T.cpp @@ -202,18 +202,3 @@ void PMS5003T::handle(void) { pms.handle(); } */ bool PMS5003T::isFailed(void) { return pms.isFailed(); } -float PMS5003T::temperatureCompensated(float temp) { - if (temp < 10.0f) { - return temp * 1.327f - 6.738f; - } - return temp * 1.181f - 5.113f; -} - -float PMS5003T::humidityCompensated(float hum) { - hum = hum * 1.259f + 7.34f; - - if (hum > 100.0f) { - hum = 100.0f; - } - return hum; -} diff --git a/src/PMS/PMS5003T.h b/src/PMS/PMS5003T.h index f3787a8..2c99b7e 100644 --- a/src/PMS/PMS5003T.h +++ b/src/PMS/PMS5003T.h @@ -3,13 +3,14 @@ #include "../Main/BoardDef.h" #include "PMS.h" +#include "PMS5003TBase.h" #include "Stream.h" #include /** * @brief The class define how to handle PMS5003T sensor bas on @ref PMS class */ -class PMS5003T { +class PMS5003T: public PMS5003TBase { public: PMS5003T(BoardType def); #if defined(ESP8266) @@ -28,8 +29,6 @@ public: int convertPm25ToUsAqi(int pm25); float getTemperature(void); float getRelativeHumidity(void); - float temperatureCompensated(float temp); - float humidityCompensated(float hum); private: bool _isBegin = false; diff --git a/src/PMS/PMS5003TBase.cpp b/src/PMS/PMS5003TBase.cpp new file mode 100644 index 0000000..7d7fdbe --- /dev/null +++ b/src/PMS/PMS5003TBase.cpp @@ -0,0 +1,21 @@ +#include "PMS5003TBase.h" + +PMS5003TBase::PMS5003TBase() {} + +PMS5003TBase::~PMS5003TBase() {} + +float PMS5003TBase::temperatureCompensated(float temp) { + if (temp < 10.0f) { + return temp * 1.327f - 6.738f; + } + return temp * 1.181f - 5.113f; +} + +float PMS5003TBase::humidityCompensated(float hum) { + hum = hum * 1.259f + 7.34f; + + if (hum > 100.0f) { + hum = 100.0f; + } + return hum; +} diff --git a/src/PMS/PMS5003TBase.h b/src/PMS/PMS5003TBase.h new file mode 100644 index 0000000..0b50449 --- /dev/null +++ b/src/PMS/PMS5003TBase.h @@ -0,0 +1,15 @@ +#ifndef _PMS5003T_BASE_H_ +#define _PMS5003T_BASE_H_ + +class PMS5003TBase +{ +private: + +public: + PMS5003TBase(); + ~PMS5003TBase(); + float temperatureCompensated(float temp); + float humidityCompensated(float hum); +}; + +#endif From 21d984c95aeb822b244540c287c49076ac5b233b Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Mon, 22 Apr 2024 16:31:21 +0700 Subject: [PATCH 08/10] add get nox/tvoc learning offset --- src/Sgp41/Sgp41.cpp | 4 ++++ src/Sgp41/Sgp41.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/Sgp41/Sgp41.cpp b/src/Sgp41/Sgp41.cpp index e160f11..b9801f5 100644 --- a/src/Sgp41/Sgp41.cpp +++ b/src/Sgp41/Sgp41.cpp @@ -293,3 +293,7 @@ void Sgp41::setNoxLearningOffset(int offset) { void Sgp41::setTvocLearningOffset(int offset) { tvocLearnOffset = offset; } + +int Sgp41::getNoxLearningOffset(void) { return noxLearnOffset; } + +int Sgp41::getTvocLearningOffset(void) { return tvocLearnOffset; } diff --git a/src/Sgp41/Sgp41.h b/src/Sgp41/Sgp41.h index f7c0f96..9e5674e 100644 --- a/src/Sgp41/Sgp41.h +++ b/src/Sgp41/Sgp41.h @@ -28,6 +28,8 @@ public: void setCompensationTemperatureHumidity(float temp, float hum); void setNoxLearningOffset(int offset); void setTvocLearningOffset(int offset); + int getNoxLearningOffset(void); + int getTvocLearningOffset(void); private: bool onConditioning = true; From 9feac035ebf5a535b56d43680c71c1d80aa8f3c4 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Mon, 22 Apr 2024 16:31:40 +0700 Subject: [PATCH 09/10] update message log and fix some bug --- examples/OneOpenAir/OneOpenAir.ino | 73 ++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/examples/OneOpenAir/OneOpenAir.ino b/examples/OneOpenAir/OneOpenAir.ino index aff6da7..363c319 100644 --- a/examples/OneOpenAir/OneOpenAir.ino +++ b/examples/OneOpenAir/OneOpenAir.ino @@ -78,7 +78,8 @@ static AirGradient *ag; static OledDisplay oledDisplay(configuration, measurements, Serial); static StateMachine stateMachine(oledDisplay, Serial, measurements, configuration); -static WifiConnector wifiConnector(oledDisplay, Serial, stateMachine, configuration); +static WifiConnector wifiConnector(oledDisplay, Serial, stateMachine, + configuration); static OpenMetrics openMetrics(measurements, configuration, wifiConnector, apiClient); static LocalServer localServer(Serial, openMetrics, measurements, configuration, @@ -109,6 +110,7 @@ static void initMqtt(void); static void factoryConfigReset(void); static void wdgFeedUpdate(void); static void ledBarEnabledUpdate(void); +static bool sgp41Init(void); AgSchedule dispLedSchedule(DISP_UPDATE_INTERVAL, oledDisplayLedBarSchedule); AgSchedule configSchedule(SERVER_CONFIG_UPDATE_INTERVAL, @@ -409,6 +411,20 @@ static void ledBarEnabledUpdate(void) { } } +static bool sgp41Init(void) { + ag->sgp41.setNoxLearningOffset(configuration.getNoxLearningOffset()); + ag->sgp41.setTvocLearningOffset(configuration.getTvocLearningOffset()); + if (ag->sgp41.begin(Wire)) { + Serial.println("Init SGP41 success"); + configuration.hasSensorSGP = true; + return true; + } else { + Serial.println("Init SGP41 failuire"); + configuration.hasSensorSGP = false; + } + return false; +} + static void sendDataToAg() { /** Change oledDisplay and led state */ if (ag->isOne()) { @@ -476,11 +492,7 @@ static void oneIndoorInit(void) { ag->watchdog.begin(); /** Init sensor SGP41 */ - ag->sgp41.setNoxLearningOffset(configuration.getNoxLearningOffset()); - ag->sgp41.setTvocLearningOffset(configuration.getTvocLearningOffset()); - if (ag->sgp41.begin(Wire) == false) { - Serial.println("SGP41 sensor not found"); - configuration.hasSensorSGP = false; + if (sgp41Init() == false) { dispSensorNotFound("SGP41"); } @@ -562,10 +574,7 @@ static void openAirInit(void) { serial1Available = false; } - ag->sgp41.setNoxLearningOffset(configuration.getNoxLearningOffset()); - ag->sgp41.setTvocLearningOffset(configuration.getTvocLearningOffset()); - if (ag->sgp41.begin(Wire) == false) { - configuration.hasSensorSGP = false; + if (sgp41Init() == false) { Serial.println("SGP sensor not found"); if (configuration.hasSensorS8 == false) { @@ -640,6 +649,16 @@ static void boardInit(void) { } else { openAirInit(); } + + /** Set S8 CO2 abc days period */ + if (configuration.hasSensorS8) { + if (ag->s8.setAbcPeriod(configuration.getCO2CalibrationAbcDays() * 24)) { + Serial.println("Set S8 AbcDays successful"); + } else { + Serial.println("Set S8 AbcDays failure"); + } + } + localServer.setFwMode(fwMode); } @@ -674,17 +693,23 @@ static void configUpdateHandle() { if (configuration.noxLearnOffsetChanged() || configuration.tvocLearnOffsetChanged()) { ag->sgp41.end(); - Serial.println("nox/tvoc learning offset changed"); - Serial.println("noxLearningOffset: " + String(configuration.getNoxLearningOffset())); - Serial.println("tvocLearningOffset: " + String(configuration.getTvocLearningOffset())); - ag->sgp41.setNoxLearningOffset(configuration.getNoxLearningOffset()); - ag->sgp41.setTvocLearningOffset(configuration.getTvocLearningOffset()); - if (ag->sgp41.begin(Wire)) { - Serial.println("Init SGP41 success"); - configuration.hasSensorSGP = true; - } else { - Serial.println("Init SGP41 failuire"); - configuration.hasSensorSGP = false; + + int oldTvocOffset = ag->sgp41.getTvocLearningOffset(); + int oldNoxOffset = ag->sgp41.getNoxLearningOffset(); + bool result = sgp41Init(); + const char *resultStr = "successful"; + if (!result) { + resultStr = "failure"; + } + if (oldTvocOffset != configuration.getTvocLearningOffset()) { + Serial.printf("Setting tvocLearningOffset from %d to %d hours %s\r\n", + oldTvocOffset, configuration.getTvocLearningOffset(), + resultStr); + } + if (oldNoxOffset != configuration.getNoxLearningOffset()) { + Serial.printf("Setting noxLearningOffset from %d to %d hours %s\r\n", + oldNoxOffset, configuration.getNoxLearningOffset(), + resultStr); } } @@ -817,7 +842,7 @@ static void updatePm(void) { Serial.printf("[2] PM3.0 Count: %d\r\n", measurements.pm03PCount_2); Serial.printf("[2] Temperature in C: %0.2f\r\n", measurements.temp_2); Serial.printf("[2] Relative Humidity: %d\r\n", measurements.hum_2); - Serial.printf("[2] Temperature compensated in C: %0.2f\r\n", + Serial.printf("[2] Temperature compensated in C: %0.2f\r\n", ag->pms5003t_1.temperatureCompensated(measurements.temp_2)); Serial.printf("[2] Relative Humidity compensated: %d\r\n", ag->pms5003t_1.humidityCompensated(measurements.hum_2)); @@ -948,9 +973,9 @@ static void tempHumUpdate(void) { Serial.printf("Temperature in C: %0.2f\r\n", measurements.Temperature); Serial.printf("Relative Humidity: %d\r\n", measurements.Humidity); Serial.printf("Temperature compensated in C: %0.2f\r\n", - ag->pms5003t_1.temperatureCompensated(measurements.Temperature)); + measurements.Temperature); Serial.printf("Relative Humidity compensated: %d\r\n", - ag->pms5003t_1.humidityCompensated(measurements.Temperature)); + measurements.Humidity); // Update compensation temperature and humidity for SGP41 if (configuration.hasSensorSGP) { From 442f0fd942d0dcb09b816629b169cd0dc997c372 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Mon, 22 Apr 2024 16:32:17 +0700 Subject: [PATCH 10/10] [update message log and fix some bug] add miss --- src/AgConfigure.cpp | 162 ++++++++++++++++++++++++++--------------- src/AgConfigure.h | 4 + src/AgStateMachine.cpp | 26 ++++--- 3 files changed, 123 insertions(+), 69 deletions(-) diff --git a/src/AgConfigure.cpp b/src/AgConfigure.cpp index 7bd551c..0fbac9b 100644 --- a/src/AgConfigure.cpp +++ b/src/AgConfigure.cpp @@ -90,6 +90,7 @@ void Configuration::loadConfig(void) { logError("Configure validate invalid"); defaultConfig(); } else { + /** Correct configuration parameter value. */ bool changed = false; if ((config.temperatureUnit != 'c') && (config.temperatureUnit != 'f')) { config.temperatureUnit = 'c'; @@ -194,32 +195,37 @@ bool Configuration::parse(String data, bool isLocal) { /** Get ConfigurationControl */ if (isLocal) { + uint8_t configurationControl = config.configurationControl; if (JSON.typeof_(root["configurationControl"]) == "string") { String configurationControl = root["configurationControl"]; - if (configurationControl == - String(CONFIGURATION_CONTROL_NAME - [ConfigurationControl::ConfigurationControlLocal])) { - config.configurationControl = - (uint8_t)ConfigurationControl::ConfigurationControlLocal; - changed = true; - } else if (configurationControl == - String( - CONFIGURATION_CONTROL_NAME - [ConfigurationControl::ConfigurationControlCloud])) { - config.configurationControl = - (uint8_t)ConfigurationControl::ConfigurationControlCloud; - changed = true; - } else if (configurationControl == - String(CONFIGURATION_CONTROL_NAME - [ConfigurationControl::ConfigurationControlBoth])) { - config.configurationControl = - (uint8_t)ConfigurationControl::ConfigurationControlBoth; - changed = true; - } else { - failedMessage = jsonValueInvalidMessage("configurationControl", - configurationControl); - jsonInvalid(); - return false; + if (configurationControl != + String(CONFIGURATION_CONTROL_NAME[config.configurationControl])) { + if (configurationControl == + String(CONFIGURATION_CONTROL_NAME + [ConfigurationControl::ConfigurationControlLocal])) { + config.configurationControl = + (uint8_t)ConfigurationControl::ConfigurationControlLocal; + changed = true; + } else if (configurationControl == + String( + CONFIGURATION_CONTROL_NAME + [ConfigurationControl::ConfigurationControlCloud])) { + config.configurationControl = + (uint8_t)ConfigurationControl::ConfigurationControlCloud; + changed = true; + } else if (configurationControl == + String( + CONFIGURATION_CONTROL_NAME + [ConfigurationControl::ConfigurationControlBoth])) { + config.configurationControl = + (uint8_t)ConfigurationControl::ConfigurationControlBoth; + changed = true; + } else { + failedMessage = jsonValueInvalidMessage("configurationControl", + configurationControl); + jsonInvalid(); + return false; + } } } else { if (jsonTypeInvalid(root["configurationControl"], "string")) { @@ -230,6 +236,15 @@ bool Configuration::parse(String data, bool isLocal) { } } + if (changed) { + changed = false; + saveConfig(); + configLogInfo( + "configurationControl", + String(CONFIGURATION_CONTROL_NAME[configurationControl]), + String(CONFIGURATION_CONTROL_NAME[config.configurationControl])); + } + if ((config.configurationControl == (byte)ConfigurationControl::ConfigurationControlCloud)) { failedMessage = "Local configure ignored"; @@ -251,17 +266,8 @@ bool Configuration::parse(String data, bool isLocal) { if (country.length() == 2) { if (country != String(config.country)) { changed = true; + configLogInfo("country", String(config.country), country); snprintf(config.country, sizeof(config.country), country.c_str()); - logInfo(String("Set country: " + country).c_str()); - } - - // Update temperature unit if get configuration from server - if (isLocal == false) { - if (country == "US") { - temperatureUnit = 'f'; - } else { - temperatureUnit = 'c'; - } } } else { failedMessage = "Country name " + country + @@ -281,9 +287,9 @@ bool Configuration::parse(String data, bool isLocal) { if (JSON.typeof_(root["pmStandard"]) == "string") { String pmStandard = root["pmStandard"]; bool inUSAQI = true; - if (pmStandard == "ugm3") { + if (pmStandard == getPMStandardString(false)) { inUSAQI = false; - } else if (pmStandard == "us-aqi") { + } else if (pmStandard == getPMStandardString(true)) { inUSAQI = true; } else { failedMessage = jsonValueInvalidMessage("pmStandard", pmStandard); @@ -292,9 +298,9 @@ bool Configuration::parse(String data, bool isLocal) { } if (inUSAQI != config.inUSAQI) { + configLogInfo("pmStandard", getPMStandardString(config.inUSAQI), pmStandard); config.inUSAQI = inUSAQI; changed = true; - logInfo("Set PM standard: " + pmStandard); } } else { if (jsonTypeInvalid(root["pmStandard"], "string")) { @@ -306,7 +312,10 @@ bool Configuration::parse(String data, bool isLocal) { if (JSON.typeof_(root["co2CalibrationRequested"]) == "boolean") { co2CalibrationRequested = root["co2CalibrationRequested"]; - logInfo("Set co2CalibrationRequested: " + String(co2CalibrationRequested)); + if(co2CalibrationRequested) { + logInfo("co2CalibrationRequested: " + + String(co2CalibrationRequested ? "True" : "False")); + } } else { if (jsonTypeInvalid(root["co2CalibrationRequested"], "boolean")) { failedMessage = @@ -318,7 +327,10 @@ bool Configuration::parse(String data, bool isLocal) { if (JSON.typeof_(root["ledBarTestRequested"]) == "boolean") { ledBarTestRequested = root["ledBarTestRequested"]; - logInfo("Set ledBarTestRequested: " + String(ledBarTestRequested)); + if(ledBarTestRequested){ + logInfo("ledBarTestRequested: " + + String(ledBarTestRequested ? "True" : "False")); + } } else { if (jsonTypeInvalid(root["ledBarTestRequested"], "boolean")) { failedMessage = jsonTypeInvalidMessage("ledBarTestRequested", "boolean"); @@ -343,9 +355,11 @@ bool Configuration::parse(String data, bool isLocal) { } if (ledBarMode != config.useRGBLedBar) { + configLogInfo("useRGBLedBar", + String(LED_BAR_MODE_NAMES[config.useRGBLedBar]), + String(LED_BAR_MODE_NAMES[ledBarMode])); config.useRGBLedBar = ledBarMode; changed = true; - logInfo("Set ledBarMode: " + mode); } } else { if (jsonTypeInvalid(root["ledBarMode"], "string")) { @@ -358,9 +372,9 @@ bool Configuration::parse(String data, bool isLocal) { if (JSON.typeof_(root["displayMode"]) == "string") { String mode = root["displayMode"]; bool displayMode = false; - if (mode == "on") { + if (mode == getDisplayModeString(true)) { displayMode = true; - } else if (mode == "off") { + } else if (mode == getDisplayModeString(false)) { displayMode = false; } else { failedMessage = jsonTypeInvalidMessage("displayMode", mode); @@ -370,8 +384,8 @@ bool Configuration::parse(String data, bool isLocal) { if (displayMode != config.displayMode) { changed = true; + configLogInfo("displayMode", getDisplayModeString(config.displayMode), mode); config.displayMode = displayMode; - logInfo("Set displayMode: " + mode); } } else { if (jsonTypeInvalid(root["displayMode"], "string")) { @@ -387,9 +401,11 @@ bool Configuration::parse(String data, bool isLocal) { abcDays = 0; } if (abcDays != config.abcDays) { + logInfo("Set abcDays: " + String(abcDays)); + configLogInfo("abcDays", getAbcDayString(config.abcDays), + String(getAbcDayString(abcDays))); config.abcDays = abcDays; changed = true; - logInfo("Set abcDays: " + String(abcDays)); } } else { if (jsonTypeInvalid(root["abcDays"], "number")) { @@ -399,13 +415,15 @@ bool Configuration::parse(String data, bool isLocal) { } } + _tvocLearningOffsetChanged = false; if (JSON.typeof_(root["tvocLearningOffset"]) == "number") { int tvocLearningOffset = root["tvocLearningOffset"]; if (tvocLearningOffset != config.tvocLearningOffset) { changed = true; _tvocLearningOffsetChanged = true; + configLogInfo("tvocLearningOffset", String(config.tvocLearningOffset), + String(tvocLearningOffset)); config.tvocLearningOffset = tvocLearningOffset; - logInfo("Set tvocLearningOffset: " + String(tvocLearningOffset)); } } else { if (jsonTypeInvalid(root["tvocLearningOffset"], "number")) { @@ -415,13 +433,15 @@ bool Configuration::parse(String data, bool isLocal) { } } + _noxLearnOffsetChanged = false; if (JSON.typeof_(root["noxLearningOffset"]) == "number") { int noxLearningOffset = root["noxLearningOffset"]; if (noxLearningOffset != config.noxLearningOffset) { changed = true; _noxLearnOffsetChanged = true; + configLogInfo("noxLearningOffset", String(config.noxLearningOffset), + String(noxLearningOffset)); config.noxLearningOffset = noxLearningOffset; - logInfo("Set noxLearningOffset: " + String(noxLearningOffset)); } } else { if (jsonTypeInvalid(root["noxLearningOffset"], "number")) { @@ -436,8 +456,8 @@ bool Configuration::parse(String data, bool isLocal) { if (broker.length() < sizeof(config.mqttBroker)) { if (broker != String(config.mqttBroker)) { changed = true; + configLogInfo("mqttBrokerUrl", String(config.mqttBroker), broker); snprintf(config.mqttBroker, sizeof(config.mqttBroker), broker.c_str()); - logInfo("Set mqttBrokerUrl: " + broker); } } else { failedMessage = @@ -456,9 +476,9 @@ bool Configuration::parse(String data, bool isLocal) { if (JSON.typeof_(root["temperatureUnit"]) == "string") { String unit = root["temperatureUnit"]; unit.toLowerCase(); - if (unit == "c") { + if ((unit == "c") || (unit == "celsius")) { temperatureUnit = 'c'; - } else if (unit == "f") { + } else if ((unit == "f") || (unit == "fahrenheit")) { temperatureUnit = 'f'; } else { failedMessage = "'temperatureUnit' value '" + unit + "' invalid"; @@ -475,8 +495,9 @@ bool Configuration::parse(String data, bool isLocal) { if (temperatureUnit != 0 && temperatureUnit != config.temperatureUnit) { changed = true; + configLogInfo("temperatureUnit", String(config.temperatureUnit), + String(temperatureUnit)); config.temperatureUnit = temperatureUnit; - logInfo("set temperatureUnit: " + String(temperatureUnit)); } if (isLocal) { @@ -484,8 +505,10 @@ bool Configuration::parse(String data, bool isLocal) { bool post = root["postDataToAirGradient"]; if (post != config.postDataToAirGradient) { changed = true; + configLogInfo("postDataToAirGradient", + String(config.postDataToAirGradient ? "true" : "false"), + String(post ? "true" : "false")); config.postDataToAirGradient = post; - logInfo("Set postDataToAirGradient: " + String(post)); } } else { if (jsonTypeInvalid(root["postDataToAirGradient"], "boolean")) { @@ -504,6 +527,7 @@ bool Configuration::parse(String data, bool isLocal) { if (model.length() < sizeof(config.model)) { if (model != String(config.model)) { changed = true; + configLogInfo("model", String(config.model), model); snprintf(config.model, sizeof(config.model), model.c_str()); } } else { @@ -524,12 +548,13 @@ bool Configuration::parse(String data, bool isLocal) { if (changed) { udpated = true; saveConfig(); + printConfig(); } else { + logInfo("Nothing changed ignore udpate"); if (ledBarTestRequested || co2CalibrationRequested) { udpated = true; } } - printConfig(); return true; } @@ -545,11 +570,7 @@ String Configuration::toString(void) { root["country"] = String(config.country); /** "pmStandard" */ - if (config.inUSAQI) { - root["pmStandard"] = "us-aqi"; - } else { - root["pmStandard"] = "ugm3"; - } + root["pmStandard"] = getPMStandardString(config.inUSAQI); /** co2CalibrationRequested */ /** ledBarTestRequested */ @@ -736,6 +757,33 @@ void Configuration::jsonInvalid(void) { logError(failedMessage); } +void Configuration::configLogInfo(String name, String fromValue, + String toValue) { + logInfo(String("Setting '") + name + String("' from '") + fromValue + + String("' to '") + toValue + String("'")); +} + +String Configuration::getPMStandardString(bool usaqi) { + if (usaqi) { + return "us-aqi"; + } + return "ugm3"; +} + +String Configuration::getDisplayModeString(bool dispMode) { + if(dispMode){ + return String("on"); + } + return String("off"); +} + +String Configuration::getAbcDayString(int value) { + if(value <= 0){ + return String("off"); + } + return String(value); +} + String Configuration::getFailedMesage(void) { return failedMessage; } void Configuration::setPostToAirGradient(bool enable) { diff --git a/src/AgConfigure.h b/src/AgConfigure.h index 687e054..b0ff9a0 100644 --- a/src/AgConfigure.h +++ b/src/AgConfigure.h @@ -44,6 +44,10 @@ private: String jsonTypeInvalidMessage(String name, String type); String jsonValueInvalidMessage(String name, String value); void jsonInvalid(void); + void configLogInfo(String name, String fromValue, String toValue); + String getPMStandardString(bool usaqi); + String getDisplayModeString(bool dispMode); + String getAbcDayString(int value); public: Configuration(Stream &debugLog); diff --git a/src/AgStateMachine.cpp b/src/AgStateMachine.cpp index 27c2ce1..2ae3b2d 100644 --- a/src/AgStateMachine.cpp +++ b/src/AgStateMachine.cpp @@ -278,20 +278,22 @@ void StateMachine::co2Calibration(void) { if (config.getCO2CalibrationAbcDays() >= 0 && config.hasSensorS8) { int newHour = config.getCO2CalibrationAbcDays() * 24; - logInfo("Requested abcDays setting: " + - String(config.getCO2CalibrationAbcDays()) + "days (" + - String(newHour) + "hours)"); int curHour = ag->s8.getAbcPeriod(); - logInfo("Current S8 abcDays setting: " + String(curHour) + "(hours)"); - if (curHour == newHour) { - logInfo("'abcDays' unchanged"); - } else { - if (ag->s8.setAbcPeriod(config.getCO2CalibrationAbcDays() * 24) == - false) { - logError("Set S8 abcDays period failed"); - } else { - logInfo("Set S8 abcDays period success"); + if (curHour != newHour) { + String resultStr = "failure"; + if (ag->s8.setAbcPeriod(config.getCO2CalibrationAbcDays() * 24)) { + resultStr = "successful"; } + String fromStr = String(curHour/24) + " days"; + if(curHour == 0){ + fromStr = "off"; + } + String toStr = String(config.getCO2CalibrationAbcDays()) + " days"; + if(config.getCO2CalibrationAbcDays() == 0) { + toStr = "off"; + } + String msg = "Setting S8 from " + fromStr + " to " + toStr + " " + resultStr; + logInfo(msg); } } else { logWarning("CO2 S8 not available, set 'abcDays' ignored");