From 20245f2110787dd462749b241931d61ce3895e88 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Sat, 21 Sep 2024 13:06:01 +0700 Subject: [PATCH 1/3] Saving work --- docs/local-server.md | 87 ++++++++++++++++++++++--------------------- src/AgConfigure.cpp | 68 +++++++++++++++++++++++---------- src/AgConfigure.h | 1 + src/AgOledDisplay.cpp | 76 +++++++++++++++++++++---------------- src/AgOledDisplay.h | 2 +- src/Main/utils.cpp | 5 +++ src/Main/utils.h | 1 + 7 files changed, 145 insertions(+), 95 deletions(-) diff --git a/docs/local-server.md b/docs/local-server.md index 1daede0..25cab52 100644 --- a/docs/local-server.md +++ b/docs/local-server.md @@ -41,33 +41,35 @@ You get the following response: "bootCount": 6, "ledMode": "pm", "firmware": "3.1.3", - "model": "I-9PSL" + "model": "I-9PSL", + "monitorDisplayCompensatedValues": true } ``` -| Properties | Type | Explanation | -|------------------|--------|--------------------------------------------------------------------| -| `serialno` | String | Serial Number of the monitor | -| `wifi` | Number | WiFi signal strength | -| `pm01` | Number | PM1 in ug/m3 | -| `pm02` | Number | PM2.5 in ug/m3 | -| `pm10` | Number | PM10 in ug/m3 | -| `pm02Compensated` | Number | PM2.5 in ug/m3 with correction applied (from fw version 3.1.4 onwards) | -| `rco2` | Number | CO2 in ppm | -| `pm003Count` | Number | Particle count per dL | -| `atmp` | Number | Temperature in Degrees Celsius | -| `atmpCompensated` | Number | Temperature in Degrees Celsius with correction applied | -| `rhum` | Number | Relative Humidity | -| `rhumCompensated` | Number | Relative Humidity with correction applied | -| `tvocIndex` | Number | Senisiron VOC Index | -| `tvocRaw` | Number | VOC raw value | -| `noxIndex` | Number | Senisirion NOx Index | -| `noxRaw` | Number | NOx raw value | -| `boot` | Number | Counts every measurement cycle. Low boot counts indicate restarts. | -| `bootCount` | Number | Same as boot property. Required for Home Assistant compatability. Will be depreciated. | -| `ledMode` | String | Current configuration of the LED mode | -| `firmware` | String | Current firmware version | -| `model` | String | Current model name | +| Properties | Type | Explanation | +|-----------------------------------|---------|----------------------------------------------------------------------------------------| +| `serialno` | String | Serial Number of the monitor | +| `wifi` | Number | WiFi signal strength | +| `pm01` | Number | PM1 in ug/m3 | +| `pm02` | Number | PM2.5 in ug/m3 | +| `pm10` | Number | PM10 in ug/m3 | +| `pm02Compensated` | Number | PM2.5 in ug/m3 with correction applied (from fw version 3.1.4 onwards) | +| `rco2` | Number | CO2 in ppm | +| `pm003Count` | Number | Particle count per dL | +| `atmp` | Number | Temperature in Degrees Celsius | +| `atmpCompensated` | Number | Temperature in Degrees Celsius with correction applied | +| `rhum` | Number | Relative Humidity | +| `rhumCompensated` | Number | Relative Humidity with correction applied | +| `tvocIndex` | Number | Senisiron VOC Index | +| `tvocRaw` | Number | VOC raw value | +| `noxIndex` | Number | Senisirion NOx Index | +| `noxRaw` | Number | NOx raw value | +| `boot` | Number | Counts every measurement cycle. Low boot counts indicate restarts. | +| `bootCount` | Number | Same as boot property. Required for Home Assistant compatability. Will be depreciated. | +| `ledMode` | String | Current configuration of the LED mode | +| `firmware` | String | Current firmware version | +| `model` | String | Current model name | +| `monitorDisplayCompensatedValues` | Boolean | Switching Display of AirGradient ONE to Compensated / Non Compensated Values | Compensated values apply correction algorithms to make the sensor values more accurate. Temperature and relative humidity correction is only applied on the outdoor monitor Open Air but the properties _compensated will still be send also for the indoor monitor AirGradient ONE. @@ -110,21 +112,22 @@ If the monitor is set up on the AirGradient dashboard, it will also receive conf #### Configuration Parameters (GET/PUT) -| Properties | Description | Type | Accepted Values | Example | -|-------------------------|:-------------------------------------------------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------| -| `country` | Country where the device is. | String | Country code as [ALPHA-2 notation](https://www.iban.com/country-codes) | {"country": "TH"} | -| `model` | Hardware identifier (only GET). | String | I-9PSL-DE | {"model": "I-9PSL-DE"} | -| `pmStandard` | Particle matter standard used on the display. | String | `ugm3`: ug/m3
`us-aqi`: USAQI | {"pmStandard": "ugm3"} | -| `ledBarMode` | Mode in which the led bar can be set. | String | `co2`: LED bar displays CO2
`pm`: LED bar displays PM
`off`: Turn off LED bar | {"ledBarMode": "off"} | -| `displayBrightness` | Brightness of the Display. | Number | 0-100 | {"displayBrightness": 50} | -| `ledBarBrightness` | Brightness of the LEDBar. | Number | 0-100 | {"ledBarBrightness": 40} | -| `abcDays` | Number of days for CO2 automatic baseline calibration. | Number | Maximum 200 days. Default 8 days. | {"abcDays": 8} | -| `mqttBrokerUrl` | MQTT broker URL. | String | | {"mqttBrokerUrl": "mqtt://192.168.0.18:1883"} | -| `temperatureUnit` | Temperature unit shown on the display. | String | `c` or `C`: Degree Celsius °C
`f` or `F`: Degree Fahrenheit °F | {"temperatureUnit": "c"} | -| `configurationControl` | The configuration source of the device. | String | `both`: Accept local and cloud configuration
`local`: Accept only local configuration
`cloud`: Accept only cloud configuration | {"configurationControl": "both"} | -| `postDataToAirGradient` | Send data to AirGradient cloud. | Boolean | `true`: Enabled
`false`: Disabled | {"postDataToAirGradient": true} | -| `co2CalibrationRequested` | Can be set to trigger a calibration. | Boolean | `true`: CO2 calibration (400ppm) will be triggered | {"co2CalibrationRequested": true} | -| `ledBarTestRequested` | Can be set to trigger a test. | Boolean | `true` : LEDs will run test sequence | {"ledBarTestRequested": true} | -| `noxLearningOffset` | Set NOx learning gain offset. | Number | 0-720 (default 12) | {"noxLearningOffset": 12} | -| `tvocLearningOffset` | Set VOC learning gain offset. | Number | 0-720 (default 12) | {"tvocLearningOffset": 12} | -| `offlineMode` | Set monitor to run without WiFi. | Boolean | `false`: Disabled (default)
`true`: Enabled | {"offlineMode": true} | +| Properties | Description | Type | Accepted Values | Example | +|-----------------------------------|:-----------------------------------------------------------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------| +| `country` | Country where the device is. | String | Country code as [ALPHA-2 notation](https://www.iban.com/country-codes) | `{"country": "TH"}` | +| `model` | Hardware identifier (only GET). | String | I-9PSL-DE | `{"model": "I-9PSL-DE"}` | +| `pmStandard` | Particle matter standard used on the display. | String | `ugm3`: ug/m3
`us-aqi`: USAQI | `{"pmStandard": "ugm3"}` | +| `ledBarMode` | Mode in which the led bar can be set. | String | `co2`: LED bar displays CO2
`pm`: LED bar displays PM
`off`: Turn off LED bar | `{"ledBarMode": "off"}` | +| `displayBrightness` | Brightness of the Display. | Number | 0-100 | `{"displayBrightness": 50}` | +| `ledBarBrightness` | Brightness of the LEDBar. | Number | 0-100 | `{"ledBarBrightness": 40}` | +| `abcDays` | Number of days for CO2 automatic baseline calibration. | Number | Maximum 200 days. Default 8 days. | `{"abcDays": 8}` | +| `mqttBrokerUrl` | MQTT broker URL. | String | | `{"mqttBrokerUrl": "mqtt://192.168.0.18:1883"}` | +| `temperatureUnit` | Temperature unit shown on the display. | String | `c` or `C`: Degree Celsius °C
`f` or `F`: Degree Fahrenheit °F | `{"temperatureUnit": "c"}` | +| `configurationControl` | The configuration source of the device. | String | `both`: Accept local and cloud configuration
`local`: Accept only local configuration
`cloud`: Accept only cloud configuration | `{"configurationControl": "both"}` | +| `postDataToAirGradient` | Send data to AirGradient cloud. | Boolean | `true`: Enabled
`false`: Disabled | `{"postDataToAirGradient": true}` | +| `co2CalibrationRequested` | Can be set to trigger a calibration. | Boolean | `true`: CO2 calibration (400ppm) will be triggered | `{"co2CalibrationRequested": true}` | +| `ledBarTestRequested` | Can be set to trigger a test. | Boolean | `true` : LEDs will run test sequence | `{"ledBarTestRequested": true}` | +| `noxLearningOffset` | Set NOx learning gain offset. | Number | 0-720 (default 12) | `{"noxLearningOffset": 12}` | +| `tvocLearningOffset` | Set VOC learning gain offset. | Number | 0-720 (default 12) | `{"tvocLearningOffset": 12}` | +| `offlineMode` | Set monitor to run without WiFi. | Boolean | `false`: Disabled (default)
`true`: Enabled | `{"offlineMode": true}` | +| `monitorDisplayCompensatedValues` | Set the display show the PM value with/without compensate value (From [3.1.8]()) | Boolean | `false`: Without compensate (default)
`true`: with compensate | `{"monitorDisplayCompensatedValues": false }` | diff --git a/src/AgConfigure.cpp b/src/AgConfigure.cpp index 99e00c1..f3abd7c 100644 --- a/src/AgConfigure.cpp +++ b/src/AgConfigure.cpp @@ -41,21 +41,23 @@ JSON_PROP_DEF(displayBrightness); JSON_PROP_DEF(co2CalibrationRequested); JSON_PROP_DEF(ledBarTestRequested); JSON_PROP_DEF(offlineMode); +JSON_PROP_DEF(monitorDisplayCompensatedValues); -#define jprop_model_default "" -#define jprop_country_default "TH" -#define jprop_pmStandard_default getPMStandardString(false) -#define jprop_ledBarMode_default getLedBarModeName(LedBarMode::LedBarModeCO2) -#define jprop_abcDays_default 8 -#define jprop_tvocLearningOffset_default 12 -#define jprop_noxLearningOffset_default 12 -#define jprop_mqttBrokerUrl_default "" -#define jprop_temperatureUnit_default "c" -#define jprop_configurationControl_default String(CONFIGURATION_CONTROL_NAME[ConfigurationControl::ConfigurationControlBoth]) -#define jprop_postDataToAirGradient_default true -#define jprop_ledBarBrightness_default 100 -#define jprop_displayBrightness_default 100 -#define jprop_offlineMode_default false +#define jprop_model_default "" +#define jprop_country_default "TH" +#define jprop_pmStandard_default getPMStandardString(false) +#define jprop_ledBarMode_default getLedBarModeName(LedBarMode::LedBarModeCO2) +#define jprop_abcDays_default 8 +#define jprop_tvocLearningOffset_default 12 +#define jprop_noxLearningOffset_default 12 +#define jprop_mqttBrokerUrl_default "" +#define jprop_temperatureUnit_default "c" +#define jprop_configurationControl_default String(CONFIGURATION_CONTROL_NAME[ConfigurationControl::ConfigurationControlBoth]) +#define jprop_postDataToAirGradient_default true +#define jprop_ledBarBrightness_default 100 +#define jprop_displayBrightness_default 100 +#define jprop_offlineMode_default false +#define jprop_monitorDisplayCompensatedValues_default false JSONVar jconfig; @@ -167,6 +169,7 @@ void Configuration::defaultConfig(void) { jconfig[jprop_abcDays] = jprop_abcDays_default; jconfig[jprop_model] = jprop_model_default; jconfig[jprop_offlineMode] = jprop_offlineMode_default; + jconfig[jprop_monitorDisplayCompensatedValues] = jprop_monitorDisplayCompensatedValues_default; saveConfig(); } @@ -628,6 +631,27 @@ bool Configuration::parse(String data, bool isLocal) { } } + if (JSON.typeof_(root[jprop_monitorDisplayCompensatedValues]) == "boolean") { + bool value = root[jprop_monitorDisplayCompensatedValues]; + bool oldValue = jconfig[jprop_monitorDisplayCompensatedValues]; + if (value != oldValue) { + changed = true; + jconfig[jprop_monitorDisplayCompensatedValues] = value; + + configLogInfo(String(jprop_monitorDisplayCompensatedValues), + String(oldValue ? "true" : "false"), + String(value ? "true" : "false")); + } + } else { + if (jsonTypeInvalid(root[jprop_monitorDisplayCompensatedValues], + "boolean")) { + failedMessage = jsonTypeInvalidMessage( + String(jprop_monitorDisplayCompensatedValues), "boolean"); + jsonInvalid(); + return false; + } + } + if (ag->getBoardType() == ONE_INDOOR || ag->getBoardType() == OPEN_AIR_OUTDOOR) { if (JSON.typeof_(root["targetFirmware"]) == "string") { @@ -1082,12 +1106,14 @@ void Configuration::toConfig(const char *buf) { } if (JSON.typeof_(jconfig[jprop_offlineMode]) != "boolean") { - isInvalid = true; - } else { - isInvalid = false; + jconfig[jprop_offlineMode] = jprop_offlineMode_default; } - if (isInvalid) { - jconfig[jprop_offlineMode] = false; + + /** Validate monitorDisplayCompensatedValues */ + if (JSON.typeof_(jconfig[jprop_monitorDisplayCompensatedValues]) != + "boolean") { + jconfig[jprop_monitorDisplayCompensatedValues] = + jprop_monitorDisplayCompensatedValues_default; } if (changed) { @@ -1173,6 +1199,10 @@ bool Configuration::isLedBarModeChanged(void) { return changed; } +bool Configuration::isMonitorDisplayCompensatedValues(void) { + return jconfig[jprop_monitorDisplayCompensatedValues]; +} + bool Configuration::isDisplayBrightnessChanged(void) { bool changed = displayBrightnessChanged; displayBrightnessChanged = false; diff --git a/src/AgConfigure.h b/src/AgConfigure.h index 24473ec..a899b64 100644 --- a/src/AgConfigure.h +++ b/src/AgConfigure.h @@ -82,6 +82,7 @@ public: void setOfflineMode(bool offline); void setOfflineModeWithoutSave(bool offline); bool isLedBarModeChanged(void); + bool isMonitorDisplayCompensatedValues(void); }; #endif /** _AG_CONFIG_H_ */ diff --git a/src/AgOledDisplay.cpp b/src/AgOledDisplay.cpp index 8250407..2a18d59 100644 --- a/src/AgOledDisplay.cpp +++ b/src/AgOledDisplay.cpp @@ -10,37 +10,49 @@ * * @param hasStatus */ -void OledDisplay::showTempHum(bool hasStatus) { - char buf[16]; +void OledDisplay::showTempHum(bool hasStatus, char* buf, int buf_size) { if (utils::isValidTemperature(value.Temperature)) { + float t = 0.0f; + if(ag->isOpenAir() && config.isMonitorDisplayCompensatedValues()) { + if(config.isTemperatureUnitInF()) { + /** Compensate temperature */ + t = ag->pms5003t_1.compensateTemp(value.Temperature); + /** Convert C to F */ + t = (t * 9)/5.0f + 32.0f; + } + } else { + + } + + if (config.isTemperatureUnitInF()) { float tempF = (value.Temperature * 9) / 5 + 32; if (hasStatus) { - snprintf(buf, sizeof(buf), "%0.1f", tempF); + snprintf(buf, buf_size, "%0.1f", tempF); } else { - snprintf(buf, sizeof(buf), "%0.1f°F", tempF); + snprintf(buf, buf_size, "%0.1f°F", tempF); } } else { if (hasStatus) { - snprintf(buf, sizeof(buf), "%.1f", value.Temperature); + snprintf(buf, buf_size, "%.1f", value.Temperature); } else { - snprintf(buf, sizeof(buf), "%.1f°C", value.Temperature); + snprintf(buf, buf_size, "%.1f°C", value.Temperature); } } } else { if (config.isTemperatureUnitInF()) { - snprintf(buf, sizeof(buf), "-°F"); + snprintf(buf, buf_size, "-°F"); } else { - snprintf(buf, sizeof(buf), "-°C"); + snprintf(buf, buf_size, "-°C"); } } DISP()->drawUTF8(1, 10, buf); /** Show humidty */ if (utils::isValidHumidity(value.Humidity)) { - snprintf(buf, sizeof(buf), "%d%%", value.Humidity); + snprintf(buf, buf_size, "%d%%", value.Humidity); } else { - snprintf(buf, sizeof(buf), "-%%"); + snprintf(buf, buf_size, "-%%"); } if (value.Humidity > 99) { @@ -261,7 +273,7 @@ void OledDisplay::showDashboard(const char *status) { do { DISP()->setFont(u8g2_font_t0_16_tf); if ((status == NULL) || (strlen(status) == 0)) { - showTempHum(false); + showTempHum(false, strBuf, sizeof(strBuf)); } else { String strStatus = "Show status: " + String(status); logInfo(strStatus); @@ -272,7 +284,7 @@ void OledDisplay::showDashboard(const char *status) { /** Show WiFi NA*/ if (strcmp(status, "WiFi N/A") == 0) { DISP()->setFont(u8g2_font_t0_12_tf); - showTempHum(true); + showTempHum(true, strBuf, sizeof(strBuf)); } } @@ -304,29 +316,27 @@ void OledDisplay::showDashboard(const char *status) { DISP()->drawStr(55, 27, "PM2.5"); /** Draw PM2.5 value */ - int pm25 = value.pm25_1; - if (config.hasSensorSHT) { - pm25 = ag->pms5003.compensate(pm25, value.Humidity); - logInfo("PM2.5:" + String(value.pm25_1) + String("Compensated:") + String(pm25)); - } - DISP()->setFont(u8g2_font_t0_22b_tf); - if (config.isPmStandardInUSAQI()) { - if (utils::isValidPm(pm25)) { + if (utils::isValidPm(value.pm25_1)) { + int pm25 = value.pm25_1; + if (config.isPmStandardInUSAQI() && + config.isMonitorDisplayCompensatedValues()) { + if (config.hasSensorSHT) { + pm25 = ag->pms5003.compensate(pm25, value.Humidity); + } sprintf(strBuf, "%d", ag->pms5003.convertPm25ToUsAqi(pm25)); } else { - sprintf(strBuf, "%s", "-"); + sprintf(strBuf, "%d", pm25); } - DISP()->drawStr(55, 48, strBuf); - DISP()->setFont(u8g2_font_t0_12_tf); + } else { + sprintf(strBuf, "%s", "-"); + } + DISP()->setFont(u8g2_font_t0_22b_tf); + DISP()->drawStr(55, 48, strBuf); + + DISP()->setFont(u8g2_font_t0_12_tf); + if (config.isPmStandardInUSAQI()) { DISP()->drawUTF8(55, 61, "AQI"); } else { - if (utils::isValidPm(pm25)) { - sprintf(strBuf, "%d", pm25); - } else { - sprintf(strBuf, "%s", "-"); - } - DISP()->drawStr(55, 48, strBuf); - DISP()->setFont(u8g2_font_t0_12_tf); DISP()->drawUTF8(55, 61, "ug/m³"); } @@ -355,18 +365,18 @@ void OledDisplay::showDashboard(const char *status) { ag->display.clear(); /** Set CO2 */ - if(utils::isValidCO2(value.CO2)) { + if (utils::isValidCO2(value.CO2)) { snprintf(strBuf, sizeof(strBuf), "CO2:%d", value.CO2); } else { snprintf(strBuf, sizeof(strBuf), "CO2:-"); } - + ag->display.setCursor(0, 0); ag->display.setText(strBuf); /** Set PM */ int pm25 = value.pm25_1; - if(config.hasSensorSHT) { + if (config.hasSensorSHT && config.isMonitorDisplayCompensatedValues()) { pm25 = (int)ag->pms5003.compensate(pm25, value.Humidity); } ag->display.setCursor(0, 12); diff --git a/src/AgOledDisplay.h b/src/AgOledDisplay.h index 28a0cba..435ff4c 100644 --- a/src/AgOledDisplay.h +++ b/src/AgOledDisplay.h @@ -16,7 +16,7 @@ private: Measurements &value; bool isDisplayOff = false; - void showTempHum(bool hasStatus); + void showTempHum(bool hasStatus, char* buf, int buf_size); void setCentralText(int y, String text); void setCentralText(int y, const char *text); diff --git a/src/Main/utils.cpp b/src/Main/utils.cpp index 42b06a5..33f8618 100644 --- a/src/Main/utils.cpp +++ b/src/Main/utils.cpp @@ -87,3 +87,8 @@ int utils::getInvalidPmValue(void) { return INVALID_PMS; } int utils::getInvalidNOx(void) { return INVALID_NOX; } int utils::getInvalidVOC(void) { return INVALID_VOC; } + +float utils::degreeC_To_F(float t) { + /** (t * 9)/5 + 32 */ + return t * 1.8f + 32.0f; +} diff --git a/src/Main/utils.h b/src/Main/utils.h index b51ac98..6b8452b 100644 --- a/src/Main/utils.h +++ b/src/Main/utils.h @@ -24,6 +24,7 @@ public: static int getInvalidPmValue(void); static int getInvalidNOx(void); static int getInvalidVOC(void); + static float degreeC_To_F(float t); }; From 9d014794061803c41c3ee8ead9470f67e25a0a80 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Sat, 21 Sep 2024 14:08:42 +0700 Subject: [PATCH 2/3] Update show PM compensate value on display and documents --- docs/local-server.md | 2 +- src/AgOledDisplay.cpp | 49 +++++++++++++++++++++--------------------- src/AgStateMachine.cpp | 6 +++++- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/docs/local-server.md b/docs/local-server.md index 25cab52..68582b9 100644 --- a/docs/local-server.md +++ b/docs/local-server.md @@ -130,4 +130,4 @@ If the monitor is set up on the AirGradient dashboard, it will also receive conf | `noxLearningOffset` | Set NOx learning gain offset. | Number | 0-720 (default 12) | `{"noxLearningOffset": 12}` | | `tvocLearningOffset` | Set VOC learning gain offset. | Number | 0-720 (default 12) | `{"tvocLearningOffset": 12}` | | `offlineMode` | Set monitor to run without WiFi. | Boolean | `false`: Disabled (default)
`true`: Enabled | `{"offlineMode": true}` | -| `monitorDisplayCompensatedValues` | Set the display show the PM value with/without compensate value (From [3.1.8]()) | Boolean | `false`: Without compensate (default)
`true`: with compensate | `{"monitorDisplayCompensatedValues": false }` | +| `monitorDisplayCompensatedValues` | Set the display show the PM value with/without compensate value (From [3.1.9]()) | Boolean | `false`: Without compensate (default)
`true`: with compensate | `{"monitorDisplayCompensatedValues": false }` | diff --git a/src/AgOledDisplay.cpp b/src/AgOledDisplay.cpp index 2a18d59..451da32 100644 --- a/src/AgOledDisplay.cpp +++ b/src/AgOledDisplay.cpp @@ -10,36 +10,30 @@ * * @param hasStatus */ -void OledDisplay::showTempHum(bool hasStatus, char* buf, int buf_size) { +void OledDisplay::showTempHum(bool hasStatus, char *buf, int buf_size) { + /** Temperature */ if (utils::isValidTemperature(value.Temperature)) { float t = 0.0f; - if(ag->isOpenAir() && config.isMonitorDisplayCompensatedValues()) { - if(config.isTemperatureUnitInF()) { - /** Compensate temperature */ - t = ag->pms5003t_1.compensateTemp(value.Temperature); - /** Convert C to F */ - t = (t * 9)/5.0f + 32.0f; - } + if (config.isTemperatureUnitInF()) { + t = utils::degreeC_To_F(value.Temperature); } else { - + t = value.Temperature; } - if (config.isTemperatureUnitInF()) { - float tempF = (value.Temperature * 9) / 5 + 32; if (hasStatus) { - snprintf(buf, buf_size, "%0.1f", tempF); + snprintf(buf, buf_size, "%0.1f", t); } else { - snprintf(buf, buf_size, "%0.1f°F", tempF); + snprintf(buf, buf_size, "%0.1f°F", t); } } else { if (hasStatus) { - snprintf(buf, buf_size, "%.1f", value.Temperature); + snprintf(buf, buf_size, "%.1f", t); } else { - snprintf(buf, buf_size, "%.1f°C", value.Temperature); + snprintf(buf, buf_size, "%.1f°C", t); } } - } else { + } else { /** Show invalid value */ if (config.isTemperatureUnitInF()) { snprintf(buf, buf_size, "-°F"); } else { @@ -48,7 +42,7 @@ void OledDisplay::showTempHum(bool hasStatus, char* buf, int buf_size) { } DISP()->drawUTF8(1, 10, buf); - /** Show humidty */ + /** Show humidity */ if (utils::isValidHumidity(value.Humidity)) { snprintf(buf, buf_size, "%d%%", value.Humidity); } else { @@ -318,21 +312,25 @@ void OledDisplay::showDashboard(const char *status) { /** Draw PM2.5 value */ if (utils::isValidPm(value.pm25_1)) { int pm25 = value.pm25_1; - if (config.isPmStandardInUSAQI() && - config.isMonitorDisplayCompensatedValues()) { - if (config.hasSensorSHT) { - pm25 = ag->pms5003.compensate(pm25, value.Humidity); - } + + /** Compensate PM2.5 value. */ + if (config.hasSensorSHT && config.isMonitorDisplayCompensatedValues()) { + pm25 = ag->pms5003.compensate(pm25, value.Humidity); + logInfo("PM2.5 compensate: " + String(pm25)); + } + + if (config.isPmStandardInUSAQI()) { sprintf(strBuf, "%d", ag->pms5003.convertPm25ToUsAqi(pm25)); } else { sprintf(strBuf, "%d", pm25); } - } else { + } else { /** Show invalid value. */ sprintf(strBuf, "%s", "-"); } DISP()->setFont(u8g2_font_t0_22b_tf); DISP()->drawStr(55, 48, strBuf); + /** Draw PM2.5 unit */ DISP()->setFont(u8g2_font_t0_12_tf); if (config.isPmStandardInUSAQI()) { DISP()->drawUTF8(55, 61, "AQI"); @@ -379,6 +377,7 @@ void OledDisplay::showDashboard(const char *status) { if (config.hasSensorSHT && config.isMonitorDisplayCompensatedValues()) { pm25 = (int)ag->pms5003.compensate(pm25, value.Humidity); } + ag->display.setCursor(0, 12); if (utils::isValidPm(pm25)) { snprintf(strBuf, sizeof(strBuf), "PM2.5:%d", pm25); @@ -390,8 +389,8 @@ void OledDisplay::showDashboard(const char *status) { /** Set temperature and humidity */ if (utils::isValidTemperature(value.Temperature)) { if (config.isTemperatureUnitInF()) { - float tempF = (value.Temperature * 9) / 5 + 32; - snprintf(strBuf, sizeof(strBuf), "T:%0.1f F", tempF); + snprintf(strBuf, sizeof(strBuf), "T:%0.1f F", + utils::degreeC_To_F(value.Temperature)); } else { snprintf(strBuf, sizeof(strBuf), "T:%0.f1 C", value.Temperature); } diff --git a/src/AgStateMachine.cpp b/src/AgStateMachine.cpp index f2e6105..8cc0372 100644 --- a/src/AgStateMachine.cpp +++ b/src/AgStateMachine.cpp @@ -141,7 +141,11 @@ void StateMachine::co2handleLeds(void) { * */ void StateMachine::pm25handleLeds(void) { - int pm25Value = ag->pms5003.compensate(value.pm25_1, value.Humidity); + int pm25Value = value.pm25_1; + if (config.isMonitorDisplayCompensatedValues() && config.hasSensorSHT) { + pm25Value = ag->pms5003.compensate(value.pm25_1, value.Humidity); + } + if (pm25Value < 5) { /** G; 1 */ ag->ledBar.setColor(RGB_COLOR_G, ag->ledBar.getNumberOfLeds() - 1); From 866684eb30d28da42a8acdebddfd4544c1f65464 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Sat, 21 Sep 2024 14:26:06 +0700 Subject: [PATCH 3/3] fix load configuration value changed --- src/AgConfigure.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/AgConfigure.cpp b/src/AgConfigure.cpp index f3abd7c..3f3005f 100644 --- a/src/AgConfigure.cpp +++ b/src/AgConfigure.cpp @@ -1106,12 +1106,14 @@ void Configuration::toConfig(const char *buf) { } if (JSON.typeof_(jconfig[jprop_offlineMode]) != "boolean") { + changed = true; jconfig[jprop_offlineMode] = jprop_offlineMode_default; } /** Validate monitorDisplayCompensatedValues */ if (JSON.typeof_(jconfig[jprop_monitorDisplayCompensatedValues]) != "boolean") { + changed = true; jconfig[jprop_monitorDisplayCompensatedValues] = jprop_monitorDisplayCompensatedValues_default; }