From a1d216ac774b12632df00678cdf2d8adba83a6cf Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Tue, 9 Jul 2024 06:10:07 +0700 Subject: [PATCH 01/16] Change `tvoc` to `VOC`, #139 --- src/AgOledDisplay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AgOledDisplay.cpp b/src/AgOledDisplay.cpp index 22d25b2..ed60180 100644 --- a/src/AgOledDisplay.cpp +++ b/src/AgOledDisplay.cpp @@ -330,7 +330,7 @@ void OledDisplay::showDashboard(const char *status) { /** Draw tvocIndexlabel */ DISP()->setFont(u8g2_font_t0_12_tf); - DISP()->drawStr(85, 27, "tvoc:"); + DISP()->drawStr(85, 27, "VOC:"); /** Draw tvocIndexvalue */ if (value.TVOC >= 0) { From c8aa07ae20221eeec21e5a9310e8800a10840a5e Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Tue, 9 Jul 2024 06:44:04 +0700 Subject: [PATCH 02/16] Correct LED bar show sensor value level color, #161 --- src/AgStateMachine.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/AgStateMachine.cpp b/src/AgStateMachine.cpp index 58d777c..62305d8 100644 --- a/src/AgStateMachine.cpp +++ b/src/AgStateMachine.cpp @@ -9,9 +9,9 @@ #define RGB_COLOR_R 255, 0, 0 /** Red */ #define RGB_COLOR_G 0, 255, 0 /** Green */ -#define RGB_COLOR_Y 255, 255, 0 /** Yellow */ -#define RGB_COLOR_O 255, 165, 0 /** Organge */ -#define RGB_COLOR_P 160, 32, 240 /** Purple */ +#define RGB_COLOR_Y 255, 150, 0 /** Yellow */ +#define RGB_COLOR_O 255, 40, 0 /** Organge */ +#define RGB_COLOR_P 180, 0, 255 /** Purple */ /** * @brief Animation LED bar with color From df6cca3714053e15dc5a0f57dfab5a044670725f Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Thu, 11 Jul 2024 06:25:31 +0700 Subject: [PATCH 03/16] Ignore parameter values out of range #190 --- src/Main/utils.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++ src/Main/utils.h | 21 +++++++++++++++++++ src/PMS/PMS5003.cpp | 11 ++++++---- src/PMS/PMS5003T.cpp | 15 ++++++++------ src/S8/S8.cpp | 3 ++- src/Sht/Sht.cpp | 9 ++++++-- 6 files changed, 95 insertions(+), 13 deletions(-) create mode 100644 src/Main/utils.cpp create mode 100644 src/Main/utils.h diff --git a/src/Main/utils.cpp b/src/Main/utils.cpp new file mode 100644 index 0000000..dcd48cd --- /dev/null +++ b/src/Main/utils.cpp @@ -0,0 +1,49 @@ +#include "utils.h" + +utils::utils(/* args */) +{ +} + +utils::~utils() +{ +} + +float utils::correctTemperature(float value) { + if (value < -40) { + return -40; + } + if (value > 100) { + return 125; + } + return value; +} + +float utils::correctHumidity(float value) { + if (value < 0) { + return 0; + } + if (value > 100) { + return 100; + } + return value; +} + +int16_t utils::correctCO2(int16_t value) { + if (value < 0) { + return 0; + } + if (value > 10000) { + return 10000; + } + return value; +} + +int utils::correctPMS(int value) { + if (value < 10) { + return 10; + } + if (value > 1000) { + return 1000; + } + return value; +} diff --git a/src/Main/utils.h b/src/Main/utils.h new file mode 100644 index 0000000..38786d8 --- /dev/null +++ b/src/Main/utils.h @@ -0,0 +1,21 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#include + +class utils +{ +private: + /* data */ +public: + utils(/* args */); + ~utils(); + + static float correctTemperature(float value); + static float correctHumidity(float value); + static int16_t correctCO2(int16_t value); + static int correctPMS(int value); +}; + + +#endif /** _UTILS_H_ */ diff --git a/src/PMS/PMS5003.cpp b/src/PMS/PMS5003.cpp index 0e7c68b..1719ccc 100644 --- a/src/PMS/PMS5003.cpp +++ b/src/PMS/PMS5003.cpp @@ -1,5 +1,6 @@ #include "PMS5003.h" #include "Arduino.h" +#include "../Main/utils.h" #if defined(ESP8266) #include @@ -87,28 +88,30 @@ bool PMS5003::begin(void) { * * @return int PM1.0 index */ -int PMS5003::getPm01Ae(void) { return pms.getPM0_1(); } +int PMS5003::getPm01Ae(void) { return utils::correctPMS(pms.getPM0_1()); } /** * @brief Read PM2.5 must call this function after @ref readData success * * @return int PM2.5 index */ -int PMS5003::getPm25Ae(void) { return pms.getPM2_5(); } +int PMS5003::getPm25Ae(void) { return utils::correctPMS(pms.getPM2_5()); } /** * @brief Read PM10.0 must call this function after @ref readData success * * @return int PM10.0 index */ -int PMS5003::getPm10Ae(void) { return pms.getPM10(); } +int PMS5003::getPm10Ae(void) { return utils::correctPMS(pms.getPM10()); } /** * @brief Read PM0.3 must call this function after @ref readData success * * @return int PM0.3 index */ -int PMS5003::getPm03ParticleCount(void) { return pms.getCount0_3(); } +int PMS5003::getPm03ParticleCount(void) { + return utils::correctPMS(pms.getCount0_3()); +} /** * @brief Convert PM2.5 to US AQI diff --git a/src/PMS/PMS5003T.cpp b/src/PMS/PMS5003T.cpp index f0f9a1d..d8b0b6b 100644 --- a/src/PMS/PMS5003T.cpp +++ b/src/PMS/PMS5003T.cpp @@ -1,5 +1,6 @@ #include "PMS5003T.h" #include "Arduino.h" +#include "../Main/utils.h" #if defined(ESP8266) #include @@ -112,28 +113,30 @@ bool PMS5003T::begin(void) { * * @return int PM1.0 index */ -int PMS5003T::getPm01Ae(void) { return pms.getPM0_1(); } +int PMS5003T::getPm01Ae(void) { return utils::correctPMS(pms.getPM0_1()); } /** * @brief Read PM2.5 must call this function after @ref readData success * * @return int PM2.5 index */ -int PMS5003T::getPm25Ae(void) { return pms.getPM2_5(); } +int PMS5003T::getPm25Ae(void) { return utils::correctPMS(pms.getPM2_5()); } /** * @brief Read PM10.0 must call this function after @ref readData success * * @return int PM10.0 index */ -int PMS5003T::getPm10Ae(void) { return pms.getPM10(); } +int PMS5003T::getPm10Ae(void) { return utils::correctPMS(pms.getPM10()); } /** * @brief Read PM 0.3 Count must call this function after @ref readData success * * @return int PM 0.3 Count index */ -int PMS5003T::getPm03ParticleCount(void) { return pms.getCount0_3(); } +int PMS5003T::getPm03ParticleCount(void) { + return utils::correctPMS(pms.getCount0_3()); +} /** * @brief Convert PM2.5 to US AQI @@ -149,7 +152,7 @@ int PMS5003T::convertPm25ToUsAqi(int pm25) { return pms.pm25ToAQI(pm25); } * @return float Degree Celcius */ float PMS5003T::getTemperature(void) { - return pms.getTemp()/10.0f; + return utils::correctTemperature(pms.getTemp() / 10.0f); } /** @@ -158,7 +161,7 @@ float PMS5003T::getTemperature(void) { * @return float Percent (%) */ float PMS5003T::getRelativeHumidity(void) { - return pms.getHum()/10.0f; + return utils::correctHumidity(pms.getHum() / 10.0f); } /** diff --git a/src/S8/S8.cpp b/src/S8/S8.cpp index c09f0a9..981a8f6 100644 --- a/src/S8/S8.cpp +++ b/src/S8/S8.cpp @@ -1,5 +1,6 @@ #include "S8.h" #include "mb_crc.h" +#include "../Main/utils.h" #if defined(ESP8266) #include #else @@ -245,7 +246,7 @@ int16_t S8::getCo2(void) { AgLog("Error getting CO2 value!"); } - return co2; + return utils::correctCO2(co2); } /** diff --git a/src/Sht/Sht.cpp b/src/Sht/Sht.cpp index aaba59d..fe1932d 100644 --- a/src/Sht/Sht.cpp +++ b/src/Sht/Sht.cpp @@ -1,6 +1,7 @@ #include "Sht.h" #include "../Libraries/arduino-sht/SHTSensor.h" +#include "../Main/utils.h" /** Cast _sensor to SHTSensor */ #define shtSensor() ((SHTSensor *)(this->_sensor)) @@ -131,14 +132,18 @@ void Sht::end(void) { * * @return float */ -float Sht::getTemperature(void) { return shtSensor()->getTemperature(); } +float Sht::getTemperature(void) { + return utils::correctTemperature(shtSensor()->getTemperature()); +} /** * @brief Get humidity * * @return float */ -float Sht::getRelativeHumidity(void) { return shtSensor()->getHumidity(); } +float Sht::getRelativeHumidity(void) { + return utils::correctHumidity(shtSensor()->getHumidity()); +} /** * @brief Measure temperature and humidity From 0ece16f434e56c7f9e761c8fdbc40885b3a036c1 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Thu, 18 Jul 2024 11:28:12 +0700 Subject: [PATCH 04/16] Update screen layout, #139 --- src/AgOledDisplay.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/AgOledDisplay.cpp b/src/AgOledDisplay.cpp index ed60180..36415c2 100644 --- a/src/AgOledDisplay.cpp +++ b/src/AgOledDisplay.cpp @@ -299,12 +299,12 @@ void OledDisplay::showDashboard(const char *status) { DISP()->drawStr(1, 61, "ppm"); /** Draw vertical line */ - DISP()->drawLine(45, 14, 45, 64); - DISP()->drawLine(82, 14, 82, 64); + DISP()->drawLine(52, 14, 52, 64); + DISP()->drawLine(97, 14, 97, 64); /** Draw PM2.5 label */ DISP()->setFont(u8g2_font_t0_12_tf); - DISP()->drawStr(48, 27, "PM2.5"); + DISP()->drawStr(55, 27, "PM2.5"); /** Draw PM2.5 value */ DISP()->setFont(u8g2_font_t0_22b_tf); @@ -314,23 +314,23 @@ void OledDisplay::showDashboard(const char *status) { } else { sprintf(strBuf, "%s", "-"); } - DISP()->drawStr(48, 48, strBuf); + DISP()->drawStr(55, 48, strBuf); DISP()->setFont(u8g2_font_t0_12_tf); - DISP()->drawUTF8(48, 61, "AQI"); + DISP()->drawUTF8(55, 61, "AQI"); } else { if (value.pm25_1 >= 0) { sprintf(strBuf, "%d", value.pm25_1); } else { sprintf(strBuf, "%s", "-"); } - DISP()->drawStr(48, 48, strBuf); + DISP()->drawStr(55, 48, strBuf); DISP()->setFont(u8g2_font_t0_12_tf); - DISP()->drawUTF8(48, 61, "ug/m³"); + DISP()->drawUTF8(55, 61, "ug/m³"); } /** Draw tvocIndexlabel */ DISP()->setFont(u8g2_font_t0_12_tf); - DISP()->drawStr(85, 27, "VOC:"); + DISP()->drawStr(100, 27, "VOC:"); /** Draw tvocIndexvalue */ if (value.TVOC >= 0) { @@ -338,16 +338,16 @@ void OledDisplay::showDashboard(const char *status) { } else { sprintf(strBuf, "%s", "-"); } - DISP()->drawStr(85, 39, strBuf); + DISP()->drawStr(100, 39, strBuf); /** Draw NOx label */ - DISP()->drawStr(85, 53, "NOx:"); + DISP()->drawStr(100, 53, "NOx:"); if (value.NOx >= 0) { sprintf(strBuf, "%d", value.NOx); } else { sprintf(strBuf, "%s", "-"); } - DISP()->drawStr(85, 63, strBuf); + DISP()->drawStr(100, 63, strBuf); } while (DISP()->nextPage()); } else if (ag->isBasic()) { ag->display.clear(); From 4b2a5f55400d67aa0d33a289f1adc625c43b4c08 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Sun, 21 Jul 2024 07:13:34 +0700 Subject: [PATCH 05/16] Add PM2.5 correction formula, #182 --- src/AgOledDisplay.cpp | 16 ++++++++++++---- src/AgValue.cpp | 18 ++++++++++++++++++ src/PMS/PMS.cpp | 35 +++++++++++++++++++++++++++++++++++ src/PMS/PMS.h | 1 + src/PMS/PMS5003.cpp | 11 +++++++++++ src/PMS/PMS5003.h | 1 + src/PMS/PMS5003T.cpp | 11 +++++++++++ src/PMS/PMS5003T.h | 1 + 8 files changed, 90 insertions(+), 4 deletions(-) diff --git a/src/AgOledDisplay.cpp b/src/AgOledDisplay.cpp index 22d25b2..abd0a04 100644 --- a/src/AgOledDisplay.cpp +++ b/src/AgOledDisplay.cpp @@ -10,7 +10,7 @@ * @param hasStatus */ void OledDisplay::showTempHum(bool hasStatus) { - char buf[10]; + char buf[16]; if (value.Temperature > -1001) { if (config.isTemperatureUnitInF()) { float tempF = (value.Temperature * 9) / 5 + 32; @@ -307,10 +307,14 @@ void OledDisplay::showDashboard(const char *status) { DISP()->drawStr(48, 27, "PM2.5"); /** Draw PM2.5 value */ + int pm25 = value.pm25_1; + if (config.hasSensorSHT) { + pm25 = ag->pms5003.pm25Compensated(pm25, value.Humidity); + } DISP()->setFont(u8g2_font_t0_22b_tf); if (config.isPmStandardInUSAQI()) { if (value.pm25_1 >= 0) { - sprintf(strBuf, "%d", ag->pms5003.convertPm25ToUsAqi(value.pm25_1)); + sprintf(strBuf, "%d", ag->pms5003.convertPm25ToUsAqi(pm25)); } else { sprintf(strBuf, "%s", "-"); } @@ -319,7 +323,7 @@ void OledDisplay::showDashboard(const char *status) { DISP()->drawUTF8(48, 61, "AQI"); } else { if (value.pm25_1 >= 0) { - sprintf(strBuf, "%d", value.pm25_1); + sprintf(strBuf, "%d", pm25); } else { sprintf(strBuf, "%s", "-"); } @@ -358,8 +362,12 @@ void OledDisplay::showDashboard(const char *status) { ag->display.setText(strBuf); /** Set PM */ + int pm25 = value.pm25_1; + if(config.hasSensorSHT) { + pm25 = (int)ag->pms5003.pm25Compensated(pm25, value.Humidity); + } ag->display.setCursor(0, 12); - snprintf(strBuf, sizeof(strBuf), "PM2.5:%d", value.pm25_1); + snprintf(strBuf, sizeof(strBuf), "PM2.5:%d", pm25); ag->display.setText(strBuf); /** Set temperature and humidity */ diff --git a/src/AgValue.cpp b/src/AgValue.cpp index bd729ea..1cc029b 100644 --- a/src/AgValue.cpp +++ b/src/AgValue.cpp @@ -50,6 +50,13 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, } } + if (config->hasSensorSHT && config->hasSensorPMS1) { + int pm25 = ag->pms5003.pm25Compensated(this->pm25_1, this->Humidity); + if (pm25 >= 0) { + root["pm02Compensated"] = pm25; + } + } + } else { if (config->hasSensorPMS1 && config->hasSensorPMS2) { root["pm01"] = ag->round2((this->pm01_1 + this->pm01_2) / 2.0); @@ -66,6 +73,11 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, root["rhumCompensated"] = (int)ag->pms5003t_2.humidityCompensated( (this->hum_1 + this->hum_2) / 2.0f); } + + int pm25 = (ag->pms5003t_1.pm25Compensated(this->pm25_1, this->temp_1) + + ag->pms5003t_2.pm25Compensated(this->pm25_2, this->temp_2)) / + 2; + root["pm02Compensated"] = pm25; } if (fwMode == FW_MODE_O_1PS || fwMode == FW_MODE_O_1PST) { @@ -82,6 +94,7 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, root["rhumCompensated"] = (int)ag->pms5003t_1.humidityCompensated(this->hum_1); } + root["pm02Compensated"] = ag->pms5003t_1.pm25Compensated(this->pm25_1, this->temp_1); } if (config->hasSensorPMS2) { root["pm01"] = this->pm01_2; @@ -96,6 +109,7 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, root["rhumCompensated"] = (int)ag->pms5003t_2.humidityCompensated(this->hum_2); } + root["pm02Compensated"] = ag->pms5003t_2.pm25Compensated(this->pm25_2, this->temp_2); } } else { if (fwMode == FW_MODE_O_1P) { @@ -112,6 +126,7 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, root["rhumCompensated"] = (int)ag->pms5003t_1.humidityCompensated(this->hum_1); } + root["pm02Compensated"] = ag->pms5003t_1.pm25Compensated(this->pm25_1, this->temp_1); } else if (config->hasSensorPMS2) { root["pm01"] = this->pm01_2; root["pm02"] = this->pm25_2; @@ -125,6 +140,7 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, root["rhumCompensated"] = (int)ag->pms5003t_1.humidityCompensated(this->hum_2); } + root["pm02Compensated"] = ag->pms5003t_1.pm25Compensated(this->pm25_1, this->temp_1); } } else { if (config->hasSensorPMS1) { @@ -140,6 +156,7 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, root["channels"]["1"]["rhumCompensated"] = (int)ag->pms5003t_1.humidityCompensated(this->hum_1); } + root["channels"]["1"]["pm02Compensated"] = ag->pms5003t_1.pm25Compensated(this->pm25_1, this->temp_1); } if (config->hasSensorPMS2) { root["channels"]["2"]["pm01"] = this->pm01_2; @@ -154,6 +171,7 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, root["channels"]["2"]["rhumCompensated"] = (int)ag->pms5003t_1.humidityCompensated(this->hum_2); } + root["channels"]["2"]["pm02Compensated"] = ag->pms5003t_2.pm25Compensated(this->pm25_2, this->temp_2); } } } diff --git a/src/PMS/PMS.cpp b/src/PMS/PMS.cpp index e9a1527..0a091fd 100644 --- a/src/PMS/PMS.cpp +++ b/src/PMS/PMS.cpp @@ -270,6 +270,41 @@ int PMSBase::pm25ToAQI(int pm02) { return 500; } +/** + * @brief Correction PM2.5 + * + * @param pm25 Raw PM2.5 value + * @param humidity Humidity value (%) + * @return float + */ +int PMSBase::pm25Compensated(int pm25, float humidity) { + float value; + if (humidity < 0) { + humidity = 0; + } + if (humidity > 100) { + humidity = 100; + } + + if(pm25 < 30) { + value = (pm25 * 0.524f) - (humidity * 0.0862f) + 5.75f; + } else if(pm25 < 50) { + value = (0.786f * (pm25 / 20 - 3 / 2) + 0.524f * (1 - (pm25 / 20 - 3 / 2))) * pm25 - (0.0862f * humidity) + 5.75f; + } else if(pm25 < 210) { + value = (0.786f * pm25) - (0.0862f * humidity) + 5.75f; + } else if(pm25 < 260) { + value = (0.69f * (pm25/50 - 21/5) + 0.786f * (1 - (pm25/50 - 21/5))) * pm25 - (0.0862f * humidity * (1 - (pm25/50 - 21/5))) + (2.966f * (pm25/50 -21/5)) + (5.75f * (1 - (pm25/50 - 21/5))) + (8.84f * (1.e-4) * pm25* (pm25/50 - 21/5)); + } else { + value = 2.966f + (0.69f * pm25) + (8.84f * (1.e-4) * pm25); + } + + if(value < 0) { + value = 0; + } + + return (int)value; +} + /** * @brief Convert two byte value to uint16_t value * diff --git a/src/PMS/PMS.h b/src/PMS/PMS.h index 4fa086a..c748d6b 100644 --- a/src/PMS/PMS.h +++ b/src/PMS/PMS.h @@ -28,6 +28,7 @@ public: uint16_t getHum(void); int pm25ToAQI(int pm02); + int pm25Compensated(int pm25, float humidity); private: Stream *stream; diff --git a/src/PMS/PMS5003.cpp b/src/PMS/PMS5003.cpp index 0e7c68b..4134855 100644 --- a/src/PMS/PMS5003.cpp +++ b/src/PMS/PMS5003.cpp @@ -118,6 +118,17 @@ int PMS5003::getPm03ParticleCount(void) { return pms.getCount0_3(); } */ int PMS5003::convertPm25ToUsAqi(int pm25) { return pms.pm25ToAQI(pm25); } +/** + * @brief Correct PM2.5 + * + * @param pm25 PM2.5 raw value + * @param humidity Humidity value + * @return float + */ +int PMS5003::pm25Compensated(int pm25, float humidity) { + return pms.pm25Compensated(pm25, humidity); +} + /** * @brief Check device initialized or not * diff --git a/src/PMS/PMS5003.h b/src/PMS/PMS5003.h index cd66b07..b5be03c 100644 --- a/src/PMS/PMS5003.h +++ b/src/PMS/PMS5003.h @@ -24,6 +24,7 @@ public: int getPm10Ae(void); int getPm03ParticleCount(void); int convertPm25ToUsAqi(int pm25); + int pm25Compensated(int pm25, float humidity); private: bool _isBegin = false; diff --git a/src/PMS/PMS5003T.cpp b/src/PMS/PMS5003T.cpp index f0f9a1d..7cf6e3b 100644 --- a/src/PMS/PMS5003T.cpp +++ b/src/PMS/PMS5003T.cpp @@ -161,6 +161,17 @@ float PMS5003T::getRelativeHumidity(void) { return pms.getHum()/10.0f; } +/** + * @brief Correct PM2.5 + * + * @param pm25 PM2.5 raw value + * @param humidity Humidity value + * @return float + */ +float PMS5003T::pm25Compensated(int pm25, float humidity) { + return pms.pm25Compensated(pm25, humidity); +} + /** * @brief Check device initialized or not * diff --git a/src/PMS/PMS5003T.h b/src/PMS/PMS5003T.h index 2c99b7e..48b8333 100644 --- a/src/PMS/PMS5003T.h +++ b/src/PMS/PMS5003T.h @@ -29,6 +29,7 @@ public: int convertPm25ToUsAqi(int pm25); float getTemperature(void); float getRelativeHumidity(void); + float pm25Compensated(int pm25, float humidity); private: bool _isBegin = false; From 5fb27b6d1e2874a5a79afa8ead123315803bafa7 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Wed, 24 Jul 2024 09:05:57 +0700 Subject: [PATCH 06/16] Check value sensor value --- examples/BASIC/BASIC.ino | 14 +- examples/BASIC/OpenMetrics.cpp | 40 +-- .../DiyProIndoorV3_3/DiyProIndoorV3_3.ino | 14 +- examples/DiyProIndoorV3_3/OpenMetrics.cpp | 40 +-- .../DiyProIndoorV4_2/DiyProIndoorV4_2.ino | 14 +- examples/DiyProIndoorV4_2/OpenMetrics.cpp | 40 +-- examples/OneOpenAir/OneOpenAir.ino | 38 +- examples/OneOpenAir/OpenMetrics.cpp | 40 +-- src/AgOledDisplay.cpp | 60 ++-- src/AgValue.cpp | 329 +++++++++++++----- src/AirGradient.h | 1 + src/Main/utils.cpp | 100 ++++-- src/Main/utils.h | 17 +- src/PMS/PMS5003.cpp | 8 +- src/PMS/PMS5003T.cpp | 12 +- src/S8/S8.cpp | 4 +- src/Sgp41/Sgp41.cpp | 34 +- src/Sgp41/Sgp41.h | 1 + src/Sht/Sht.cpp | 4 +- 19 files changed, 525 insertions(+), 285 deletions(-) diff --git a/examples/BASIC/BASIC.ino b/examples/BASIC/BASIC.ino index 8928c68..f212c6d 100644 --- a/examples/BASIC/BASIC.ino +++ b/examples/BASIC/BASIC.ino @@ -233,7 +233,7 @@ void loop() { static void co2Update(void) { int value = ag.s8.getCo2(); - if (value >= 0) { + if (utils::isValidCO2(value)) { measurements.CO2 = value; getCO2FailCount = 0; Serial.printf("CO2 (ppm): %d\r\n", measurements.CO2); @@ -241,7 +241,7 @@ static void co2Update(void) { getCO2FailCount++; Serial.printf("Get CO2 failed: %d\r\n", getCO2FailCount); if (getCO2FailCount >= 3) { - measurements.CO2 = -1; + measurements.CO2 = utils::getInvalidCO2(); } } } @@ -516,10 +516,10 @@ static void updatePm(void) { pmFailCount++; Serial.printf("PMS read failed: %d\r\n", pmFailCount); if (pmFailCount >= 3) { - measurements.pm01_1 = -1; - measurements.pm25_1 = -1; - measurements.pm10_1 = -1; - measurements.pm03PCount_1 = -1; + measurements.pm01_1 = utils::getInvalidPMS(); + measurements.pm25_1 = utils::getInvalidPMS(); + measurements.pm10_1 = utils::getInvalidPMS(); + measurements.pm03PCount_1 = utils::getInvalidPMS(); } } } @@ -564,5 +564,7 @@ static void tempHumUpdate(void) { } } else { Serial.println("SHT read failed"); + measurements.Temperature = utils::getInvalidTemperature(); + measurements.Humidity = utils::getInvalidHumidity(); } } diff --git a/examples/BASIC/OpenMetrics.cpp b/examples/BASIC/OpenMetrics.cpp index 5270768..3392d97 100644 --- a/examples/BASIC/OpenMetrics.cpp +++ b/examples/BASIC/OpenMetrics.cpp @@ -65,14 +65,14 @@ String OpenMetrics::getPayload(void) { add_metric_point("", String(measure.CO2)); } - float _temp = -1001; - float _hum = -1; - int pm01 = -1; - int pm25 = -1; - int pm10 = -1; - int pm03PCount = -1; - int atmpCompensated = -1; - int ahumCompensated = -1; + float _temp = utils::getInvalidTemperature(); + float _hum = utils::getInvalidHumidity(); + int pm01 = utils::getInvalidPMS(); + int pm25 = utils::getInvalidPMS(); + int pm10 = utils::getInvalidPMS(); + int pm03PCount = utils::getInvalidPMS(); + int atmpCompensated = utils::getInvalidTemperature(); + int ahumCompensated = utils::getInvalidHumidity(); if (config.hasSensorSHT) { _temp = measure.Temperature; @@ -89,28 +89,28 @@ String OpenMetrics::getPayload(void) { } if (config.hasSensorPMS1) { - if (pm01 >= 0) { + if (utils::isValidPMS(pm01)) { add_metric("pm1", "PM1.0 concentration as measured by the AirGradient PMS " "sensor, in micrograms per cubic meter", "gauge", "ugm3"); add_metric_point("", String(pm01)); } - if (pm25 >= 0) { + if (utils::isValidPMS(pm25)) { add_metric("pm2d5", "PM2.5 concentration as measured by the AirGradient PMS " "sensor, in micrograms per cubic meter", "gauge", "ugm3"); add_metric_point("", String(pm25)); } - if (pm10 >= 0) { + if (utils::isValidPMS(pm10)) { add_metric("pm10", "PM10 concentration as measured by the AirGradient PMS " "sensor, in micrograms per cubic meter", "gauge", "ugm3"); add_metric_point("", String(pm10)); } - if (pm03PCount >= 0) { + if (utils::isValidPMS03Count(pm03PCount)) { add_metric("pm0d3", "PM0.3 concentration as measured by the AirGradient PMS " "sensor, in number of particules per 100 milliliters", @@ -120,28 +120,28 @@ String OpenMetrics::getPayload(void) { } if (config.hasSensorSGP) { - if (measure.TVOC >= 0) { + if (utils::isValidVOC(measure.TVOC)) { add_metric("tvoc_index", "The processed Total Volatile Organic Compounds (TVOC) index " "as measured by the AirGradient SGP sensor", "gauge"); add_metric_point("", String(measure.TVOC)); } - if (measure.TVOCRaw >= 0) { + if (utils::isValidVOC(measure.TVOCRaw)) { add_metric("tvoc_raw", "The raw input value to the Total Volatile Organic Compounds " "(TVOC) index as measured by the AirGradient SGP sensor", "gauge"); add_metric_point("", String(measure.TVOCRaw)); } - if (measure.NOx >= 0) { + if (utils::isValidNOx(measure.NOx)) { add_metric("nox_index", "The processed Nitrous Oxide (NOx) index as measured by the " "AirGradient SGP sensor", "gauge"); add_metric_point("", String(measure.NOx)); } - if (measure.NOxRaw >= 0) { + if (utils::isValidNOx(measure.NOxRaw)) { add_metric("nox_raw", "The raw input value to the Nitrous Oxide (NOx) index as " "measured by the AirGradient SGP sensor", @@ -150,7 +150,7 @@ String OpenMetrics::getPayload(void) { } } - if (_temp > -1001) { + if (utils::isValidTemperature(_temp)) { add_metric( "temperature", "The ambient temperature as measured by the AirGradient SHT / PMS " @@ -158,7 +158,7 @@ String OpenMetrics::getPayload(void) { "gauge", "celsius"); add_metric_point("", String(_temp)); } - if (atmpCompensated > -1001) { + if (utils::isValidTemperature(atmpCompensated)) { add_metric("temperature_compensated", "The compensated ambient temperature as measured by the " "AirGradient SHT / PMS " @@ -166,14 +166,14 @@ String OpenMetrics::getPayload(void) { "gauge", "celsius"); add_metric_point("", String(atmpCompensated)); } - if (_hum >= 0) { + if (utils::isValidHumidity(_hum)) { add_metric( "humidity", "The relative humidity as measured by the AirGradient SHT sensor", "gauge", "percent"); add_metric_point("", String(_hum)); } - if (ahumCompensated >= 0) { + if (utils::isValidHumidity(ahumCompensated)) { add_metric("humidity_compensated", "The compensated relative humidity as measured by the " "AirGradient SHT / PMS sensor", diff --git a/examples/DiyProIndoorV3_3/DiyProIndoorV3_3.ino b/examples/DiyProIndoorV3_3/DiyProIndoorV3_3.ino index d1eaa76..6b43a06 100644 --- a/examples/DiyProIndoorV3_3/DiyProIndoorV3_3.ino +++ b/examples/DiyProIndoorV3_3/DiyProIndoorV3_3.ino @@ -231,7 +231,7 @@ void loop() { static void co2Update(void) { int value = ag.s8.getCo2(); - if (value >= 0) { + if (utils::isValidCO2(value)) { measurements.CO2 = value; getCO2FailCount = 0; Serial.printf("CO2 (ppm): %d\r\n", measurements.CO2); @@ -239,7 +239,7 @@ static void co2Update(void) { getCO2FailCount++; Serial.printf("Get CO2 failed: %d\r\n", getCO2FailCount); if (getCO2FailCount >= 3) { - measurements.CO2 = -1; + measurements.CO2 = utils::getInvalidCO2(); } } } @@ -568,10 +568,10 @@ static void updatePm(void) { pmFailCount++; Serial.printf("PMS read failed: %d\r\n", pmFailCount); if (pmFailCount >= 3) { - measurements.pm01_1 = -1; - measurements.pm25_1 = -1; - measurements.pm10_1 = -1; - measurements.pm03PCount_1 = -1; + measurements.pm01_1 = utils::getInvalidPMS(); + measurements.pm25_1 = utils::getInvalidPMS(); + measurements.pm10_1 = utils::getInvalidPMS(); + measurements.pm03PCount_1 = utils::getInvalidPMS(); } } } @@ -616,5 +616,7 @@ static void tempHumUpdate(void) { } } else { Serial.println("SHT read failed"); + measurements.Temperature = utils::getInvalidTemperature(); + measurements.Humidity = utils::getInvalidHumidity(); } } diff --git a/examples/DiyProIndoorV3_3/OpenMetrics.cpp b/examples/DiyProIndoorV3_3/OpenMetrics.cpp index 5270768..3392d97 100644 --- a/examples/DiyProIndoorV3_3/OpenMetrics.cpp +++ b/examples/DiyProIndoorV3_3/OpenMetrics.cpp @@ -65,14 +65,14 @@ String OpenMetrics::getPayload(void) { add_metric_point("", String(measure.CO2)); } - float _temp = -1001; - float _hum = -1; - int pm01 = -1; - int pm25 = -1; - int pm10 = -1; - int pm03PCount = -1; - int atmpCompensated = -1; - int ahumCompensated = -1; + float _temp = utils::getInvalidTemperature(); + float _hum = utils::getInvalidHumidity(); + int pm01 = utils::getInvalidPMS(); + int pm25 = utils::getInvalidPMS(); + int pm10 = utils::getInvalidPMS(); + int pm03PCount = utils::getInvalidPMS(); + int atmpCompensated = utils::getInvalidTemperature(); + int ahumCompensated = utils::getInvalidHumidity(); if (config.hasSensorSHT) { _temp = measure.Temperature; @@ -89,28 +89,28 @@ String OpenMetrics::getPayload(void) { } if (config.hasSensorPMS1) { - if (pm01 >= 0) { + if (utils::isValidPMS(pm01)) { add_metric("pm1", "PM1.0 concentration as measured by the AirGradient PMS " "sensor, in micrograms per cubic meter", "gauge", "ugm3"); add_metric_point("", String(pm01)); } - if (pm25 >= 0) { + if (utils::isValidPMS(pm25)) { add_metric("pm2d5", "PM2.5 concentration as measured by the AirGradient PMS " "sensor, in micrograms per cubic meter", "gauge", "ugm3"); add_metric_point("", String(pm25)); } - if (pm10 >= 0) { + if (utils::isValidPMS(pm10)) { add_metric("pm10", "PM10 concentration as measured by the AirGradient PMS " "sensor, in micrograms per cubic meter", "gauge", "ugm3"); add_metric_point("", String(pm10)); } - if (pm03PCount >= 0) { + if (utils::isValidPMS03Count(pm03PCount)) { add_metric("pm0d3", "PM0.3 concentration as measured by the AirGradient PMS " "sensor, in number of particules per 100 milliliters", @@ -120,28 +120,28 @@ String OpenMetrics::getPayload(void) { } if (config.hasSensorSGP) { - if (measure.TVOC >= 0) { + if (utils::isValidVOC(measure.TVOC)) { add_metric("tvoc_index", "The processed Total Volatile Organic Compounds (TVOC) index " "as measured by the AirGradient SGP sensor", "gauge"); add_metric_point("", String(measure.TVOC)); } - if (measure.TVOCRaw >= 0) { + if (utils::isValidVOC(measure.TVOCRaw)) { add_metric("tvoc_raw", "The raw input value to the Total Volatile Organic Compounds " "(TVOC) index as measured by the AirGradient SGP sensor", "gauge"); add_metric_point("", String(measure.TVOCRaw)); } - if (measure.NOx >= 0) { + if (utils::isValidNOx(measure.NOx)) { add_metric("nox_index", "The processed Nitrous Oxide (NOx) index as measured by the " "AirGradient SGP sensor", "gauge"); add_metric_point("", String(measure.NOx)); } - if (measure.NOxRaw >= 0) { + if (utils::isValidNOx(measure.NOxRaw)) { add_metric("nox_raw", "The raw input value to the Nitrous Oxide (NOx) index as " "measured by the AirGradient SGP sensor", @@ -150,7 +150,7 @@ String OpenMetrics::getPayload(void) { } } - if (_temp > -1001) { + if (utils::isValidTemperature(_temp)) { add_metric( "temperature", "The ambient temperature as measured by the AirGradient SHT / PMS " @@ -158,7 +158,7 @@ String OpenMetrics::getPayload(void) { "gauge", "celsius"); add_metric_point("", String(_temp)); } - if (atmpCompensated > -1001) { + if (utils::isValidTemperature(atmpCompensated)) { add_metric("temperature_compensated", "The compensated ambient temperature as measured by the " "AirGradient SHT / PMS " @@ -166,14 +166,14 @@ String OpenMetrics::getPayload(void) { "gauge", "celsius"); add_metric_point("", String(atmpCompensated)); } - if (_hum >= 0) { + if (utils::isValidHumidity(_hum)) { add_metric( "humidity", "The relative humidity as measured by the AirGradient SHT sensor", "gauge", "percent"); add_metric_point("", String(_hum)); } - if (ahumCompensated >= 0) { + if (utils::isValidHumidity(ahumCompensated)) { add_metric("humidity_compensated", "The compensated relative humidity as measured by the " "AirGradient SHT / PMS sensor", diff --git a/examples/DiyProIndoorV4_2/DiyProIndoorV4_2.ino b/examples/DiyProIndoorV4_2/DiyProIndoorV4_2.ino index 3b16795..4322238 100644 --- a/examples/DiyProIndoorV4_2/DiyProIndoorV4_2.ino +++ b/examples/DiyProIndoorV4_2/DiyProIndoorV4_2.ino @@ -258,7 +258,7 @@ void loop() { static void co2Update(void) { int value = ag.s8.getCo2(); - if (value >= 0) { + if (utils::isValidCO2(value)) { measurements.CO2 = value; getCO2FailCount = 0; Serial.printf("CO2 (ppm): %d\r\n", measurements.CO2); @@ -266,7 +266,7 @@ static void co2Update(void) { getCO2FailCount++; Serial.printf("Get CO2 failed: %d\r\n", getCO2FailCount); if (getCO2FailCount >= 3) { - measurements.CO2 = -1; + measurements.CO2 = utils::getInvalidCO2(); } } } @@ -611,10 +611,10 @@ static void updatePm(void) { pmFailCount++; Serial.printf("PMS read failed: %d\r\n", pmFailCount); if (pmFailCount >= 3) { - measurements.pm01_1 = -1; - measurements.pm25_1 = -1; - measurements.pm10_1 = -1; - measurements.pm03PCount_1 = -1; + measurements.pm01_1 = utils::getInvalidPMS(); + measurements.pm25_1 = utils::getInvalidPMS(); + measurements.pm10_1 = utils::getInvalidPMS(); + measurements.pm03PCount_1 = utils::getInvalidPMS(); } } } @@ -659,5 +659,7 @@ static void tempHumUpdate(void) { } } else { Serial.println("SHT read failed"); + measurements.Temperature = utils::getInvalidTemperature(); + measurements.Humidity = utils::getInvalidHumidity(); } } diff --git a/examples/DiyProIndoorV4_2/OpenMetrics.cpp b/examples/DiyProIndoorV4_2/OpenMetrics.cpp index 5270768..3392d97 100644 --- a/examples/DiyProIndoorV4_2/OpenMetrics.cpp +++ b/examples/DiyProIndoorV4_2/OpenMetrics.cpp @@ -65,14 +65,14 @@ String OpenMetrics::getPayload(void) { add_metric_point("", String(measure.CO2)); } - float _temp = -1001; - float _hum = -1; - int pm01 = -1; - int pm25 = -1; - int pm10 = -1; - int pm03PCount = -1; - int atmpCompensated = -1; - int ahumCompensated = -1; + float _temp = utils::getInvalidTemperature(); + float _hum = utils::getInvalidHumidity(); + int pm01 = utils::getInvalidPMS(); + int pm25 = utils::getInvalidPMS(); + int pm10 = utils::getInvalidPMS(); + int pm03PCount = utils::getInvalidPMS(); + int atmpCompensated = utils::getInvalidTemperature(); + int ahumCompensated = utils::getInvalidHumidity(); if (config.hasSensorSHT) { _temp = measure.Temperature; @@ -89,28 +89,28 @@ String OpenMetrics::getPayload(void) { } if (config.hasSensorPMS1) { - if (pm01 >= 0) { + if (utils::isValidPMS(pm01)) { add_metric("pm1", "PM1.0 concentration as measured by the AirGradient PMS " "sensor, in micrograms per cubic meter", "gauge", "ugm3"); add_metric_point("", String(pm01)); } - if (pm25 >= 0) { + if (utils::isValidPMS(pm25)) { add_metric("pm2d5", "PM2.5 concentration as measured by the AirGradient PMS " "sensor, in micrograms per cubic meter", "gauge", "ugm3"); add_metric_point("", String(pm25)); } - if (pm10 >= 0) { + if (utils::isValidPMS(pm10)) { add_metric("pm10", "PM10 concentration as measured by the AirGradient PMS " "sensor, in micrograms per cubic meter", "gauge", "ugm3"); add_metric_point("", String(pm10)); } - if (pm03PCount >= 0) { + if (utils::isValidPMS03Count(pm03PCount)) { add_metric("pm0d3", "PM0.3 concentration as measured by the AirGradient PMS " "sensor, in number of particules per 100 milliliters", @@ -120,28 +120,28 @@ String OpenMetrics::getPayload(void) { } if (config.hasSensorSGP) { - if (measure.TVOC >= 0) { + if (utils::isValidVOC(measure.TVOC)) { add_metric("tvoc_index", "The processed Total Volatile Organic Compounds (TVOC) index " "as measured by the AirGradient SGP sensor", "gauge"); add_metric_point("", String(measure.TVOC)); } - if (measure.TVOCRaw >= 0) { + if (utils::isValidVOC(measure.TVOCRaw)) { add_metric("tvoc_raw", "The raw input value to the Total Volatile Organic Compounds " "(TVOC) index as measured by the AirGradient SGP sensor", "gauge"); add_metric_point("", String(measure.TVOCRaw)); } - if (measure.NOx >= 0) { + if (utils::isValidNOx(measure.NOx)) { add_metric("nox_index", "The processed Nitrous Oxide (NOx) index as measured by the " "AirGradient SGP sensor", "gauge"); add_metric_point("", String(measure.NOx)); } - if (measure.NOxRaw >= 0) { + if (utils::isValidNOx(measure.NOxRaw)) { add_metric("nox_raw", "The raw input value to the Nitrous Oxide (NOx) index as " "measured by the AirGradient SGP sensor", @@ -150,7 +150,7 @@ String OpenMetrics::getPayload(void) { } } - if (_temp > -1001) { + if (utils::isValidTemperature(_temp)) { add_metric( "temperature", "The ambient temperature as measured by the AirGradient SHT / PMS " @@ -158,7 +158,7 @@ String OpenMetrics::getPayload(void) { "gauge", "celsius"); add_metric_point("", String(_temp)); } - if (atmpCompensated > -1001) { + if (utils::isValidTemperature(atmpCompensated)) { add_metric("temperature_compensated", "The compensated ambient temperature as measured by the " "AirGradient SHT / PMS " @@ -166,14 +166,14 @@ String OpenMetrics::getPayload(void) { "gauge", "celsius"); add_metric_point("", String(atmpCompensated)); } - if (_hum >= 0) { + if (utils::isValidHumidity(_hum)) { add_metric( "humidity", "The relative humidity as measured by the AirGradient SHT sensor", "gauge", "percent"); add_metric_point("", String(_hum)); } - if (ahumCompensated >= 0) { + if (utils::isValidHumidity(ahumCompensated)) { add_metric("humidity_compensated", "The compensated relative humidity as measured by the " "AirGradient SHT / PMS sensor", diff --git a/examples/OneOpenAir/OneOpenAir.ino b/examples/OneOpenAir/OneOpenAir.ino index 7cbf2e7..5f026ca 100644 --- a/examples/OneOpenAir/OneOpenAir.ino +++ b/examples/OneOpenAir/OneOpenAir.ino @@ -317,7 +317,7 @@ void loop() { static void co2Update(void) { int value = ag->s8.getCo2(); - if (value >= 0) { + if (utils::isValidCO2(value)) { measurements.CO2 = value; getCO2FailCount = 0; Serial.printf("CO2 (ppm): %d\r\n", measurements.CO2); @@ -325,7 +325,7 @@ static void co2Update(void) { getCO2FailCount++; Serial.printf("Get CO2 failed: %d\r\n", getCO2FailCount); if (getCO2FailCount >= 3) { - measurements.CO2 = -1; + measurements.CO2 = utils::getInvalidCO2(); } } } @@ -1020,10 +1020,10 @@ static void updatePm(void) { pmFailCount++; Serial.printf("PMS read failed: %d\r\n", pmFailCount); if (pmFailCount >= 3) { - measurements.pm01_1 = -1; - measurements.pm25_1 = -1; - measurements.pm10_1 = -1; - measurements.pm03PCount_1 = -1; + measurements.pm01_1 = utils::getInvalidPMS(); + measurements.pm25_1 = utils::getInvalidPMS(); + measurements.pm10_1 = utils::getInvalidPMS(); + measurements.pm03PCount_1 = utils::getInvalidPMS(); } } } else { @@ -1051,12 +1051,12 @@ static void updatePm(void) { Serial.printf("[1] Relative Humidity compensated: %f\r\n", ag->pms5003t_1.humidityCompensated(measurements.hum_1)); } else { - measurements.pm01_1 = -1; - measurements.pm25_1 = -1; - measurements.pm10_1 = -1; - measurements.pm03PCount_1 = -1; - measurements.temp_1 = -1001; - measurements.hum_1 = -1; + measurements.pm01_1 = utils::getInvalidPMS(); + measurements.pm25_1 = utils::getInvalidPMS(); + measurements.pm10_1 = utils::getInvalidPMS(); + measurements.pm03PCount_1 = utils::getInvalidPMS(); + measurements.temp_1 = utils::getInvalidTemperature(); + measurements.hum_1 = utils::getInvalidHumidity(); } if (configuration.hasSensorPMS2 && (ag->pms5003t_2.isFailed() == false)) { @@ -1081,12 +1081,12 @@ static void updatePm(void) { 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; - measurements.pm10_2 = -1; - measurements.pm03PCount_2 = -1; - measurements.temp_2 = -1001; - measurements.hum_2 = -1; + measurements.pm01_2 = utils::getInvalidPMS(); + measurements.pm25_2 = utils::getInvalidPMS(); + measurements.pm10_2 = utils::getInvalidPMS(); + measurements.pm03PCount_2 = utils::getInvalidPMS(); + measurements.temp_2 = utils::getInvalidTemperature(); + measurements.hum_2 = utils::getInvalidHumidity(); } if (configuration.hasSensorPMS1 && configuration.hasSensorPMS2 && @@ -1226,6 +1226,8 @@ static void tempHumUpdate(void) { measurements.Humidity); } } else { + measurements.Temperature = utils::getInvalidTemperature(); + measurements.Humidity = utils::getInvalidHumidity(); Serial.println("SHT read failed"); } } diff --git a/examples/OneOpenAir/OpenMetrics.cpp b/examples/OneOpenAir/OpenMetrics.cpp index 0f4c92c..c458a8c 100644 --- a/examples/OneOpenAir/OpenMetrics.cpp +++ b/examples/OneOpenAir/OpenMetrics.cpp @@ -65,14 +65,14 @@ String OpenMetrics::getPayload(void) { add_metric_point("", String(measure.CO2)); } - float _temp = -1001; - float _hum = -1; - int pm01 = -1; - int pm25 = -1; - int pm10 = -1; - int pm03PCount = -1; - int atmpCompensated = -1; - int ahumCompensated = -1; + float _temp = utils::getInvalidTemperature(); + float _hum = utils::getInvalidHumidity(); + int pm01 = utils::getInvalidPMS(); + int pm25 = utils::getInvalidPMS(); + int pm10 = utils::getInvalidPMS(); + int pm03PCount = utils::getInvalidPMS(); + int atmpCompensated = utils::getInvalidTemperature(); + int ahumCompensated = utils::getInvalidHumidity(); if (config.hasSensorPMS1 && config.hasSensorPMS2) { _temp = (measure.temp_1 + measure.temp_2) / 2.0f; _hum = (measure.hum_1 + measure.hum_2) / 2.0f; @@ -123,28 +123,28 @@ String OpenMetrics::getPayload(void) { } if (config.hasSensorPMS1 || config.hasSensorPMS2) { - if (pm01 >= 0) { + if (utils::isValidPMS(pm01)) { add_metric("pm1", "PM1.0 concentration as measured by the AirGradient PMS " "sensor, in micrograms per cubic meter", "gauge", "ugm3"); add_metric_point("", String(pm01)); } - if (pm25 >= 0) { + if (utils::isValidPMS(pm25)) { add_metric("pm2d5", "PM2.5 concentration as measured by the AirGradient PMS " "sensor, in micrograms per cubic meter", "gauge", "ugm3"); add_metric_point("", String(pm25)); } - if (pm10 >= 0) { + if (utils::isValidPMS(pm10)) { add_metric("pm10", "PM10 concentration as measured by the AirGradient PMS " "sensor, in micrograms per cubic meter", "gauge", "ugm3"); add_metric_point("", String(pm10)); } - if (pm03PCount >= 0) { + if (utils::isValidPMS03Count(pm03PCount)) { add_metric("pm0d3", "PM0.3 concentration as measured by the AirGradient PMS " "sensor, in number of particules per 100 milliliters", @@ -154,28 +154,28 @@ String OpenMetrics::getPayload(void) { } if (config.hasSensorSGP) { - if (measure.TVOC >= 0) { + if (utils::isValidVOC(measure.TVOC)) { add_metric("tvoc_index", "The processed Total Volatile Organic Compounds (TVOC) index " "as measured by the AirGradient SGP sensor", "gauge"); add_metric_point("", String(measure.TVOC)); } - if (measure.TVOCRaw >= 0) { + if (utils::isValidVOC(measure.TVOCRaw)) { add_metric("tvoc_raw", "The raw input value to the Total Volatile Organic Compounds " "(TVOC) index as measured by the AirGradient SGP sensor", "gauge"); add_metric_point("", String(measure.TVOCRaw)); } - if (measure.NOx >= 0) { + if (utils::isValidNOx(measure.NOx)) { add_metric("nox_index", "The processed Nitrous Oxide (NOx) index as measured by the " "AirGradient SGP sensor", "gauge"); add_metric_point("", String(measure.NOx)); } - if (measure.NOxRaw >= 0) { + if (utils::isValidNOx(measure.NOxRaw)) { add_metric("nox_raw", "The raw input value to the Nitrous Oxide (NOx) index as " "measured by the AirGradient SGP sensor", @@ -184,14 +184,14 @@ String OpenMetrics::getPayload(void) { } } - if (_temp > -1001) { + if (utils::isValidTemperature(_temp)) { add_metric("temperature", "The ambient temperature as measured by the AirGradient SHT / PMS " "sensor, in degrees Celsius", "gauge", "celsius"); add_metric_point("", String(_temp)); } - if (atmpCompensated > -1001) { + if (utils::isValidTemperature(atmpCompensated)) { add_metric( "temperature_compensated", "The compensated ambient temperature as measured by the AirGradient SHT / PMS " @@ -199,14 +199,14 @@ String OpenMetrics::getPayload(void) { "gauge", "celsius"); add_metric_point("", String(atmpCompensated)); } - if (_hum >= 0) { + if (utils::isValidHumidity(_hum)) { add_metric( "humidity", "The relative humidity as measured by the AirGradient SHT sensor", "gauge", "percent"); add_metric_point("", String(_hum)); } - if (ahumCompensated >= 0) { + if (utils::isValidHumidity(ahumCompensated)) { add_metric( "humidity_compensated", "The compensated relative humidity as measured by the AirGradient SHT / PMS sensor", diff --git a/src/AgOledDisplay.cpp b/src/AgOledDisplay.cpp index 22d25b2..7dcf65f 100644 --- a/src/AgOledDisplay.cpp +++ b/src/AgOledDisplay.cpp @@ -1,5 +1,6 @@ #include "AgOledDisplay.h" #include "Libraries/U8g2/src/U8g2lib.h" +#include "Main/utils.h" /** Cast U8G2 */ #define DISP() ((U8G2_SH1106_128X64_NONAME_F_HW_I2C *)(this->u8g2)) @@ -10,8 +11,8 @@ * @param hasStatus */ void OledDisplay::showTempHum(bool hasStatus) { - char buf[10]; - if (value.Temperature > -1001) { + char buf[16]; + if (utils::isValidTemperature(value.Temperature)) { if (config.isTemperatureUnitInF()) { float tempF = (value.Temperature * 9) / 5 + 32; if (hasStatus) { @@ -36,10 +37,10 @@ void OledDisplay::showTempHum(bool hasStatus) { DISP()->drawUTF8(1, 10, buf); /** Show humidty */ - if (value.Humidity >= 0) { + if (utils::isValidHumidity(value.Humidity)) { snprintf(buf, sizeof(buf), "%d%%", value.Humidity); } else { - snprintf(buf, sizeof(buf), "%-%%"); + snprintf(buf, sizeof(buf), "-%%"); } if (value.Humidity > 99) { @@ -283,12 +284,8 @@ void OledDisplay::showDashboard(const char *status) { DISP()->drawUTF8(1, 27, "CO2"); DISP()->setFont(u8g2_font_t0_22b_tf); - if (value.CO2 > 0) { - int val = 9999; - if (value.CO2 < 10000) { - val = value.CO2; - } - sprintf(strBuf, "%d", val); + if (utils::isValidCO2(value.CO2)) { + sprintf(strBuf, "%d", value.CO2); } else { sprintf(strBuf, "%s", "-"); } @@ -309,7 +306,7 @@ void OledDisplay::showDashboard(const char *status) { /** Draw PM2.5 value */ DISP()->setFont(u8g2_font_t0_22b_tf); if (config.isPmStandardInUSAQI()) { - if (value.pm25_1 >= 0) { + if (utils::isValidPMS(value.pm25_1)) { sprintf(strBuf, "%d", ag->pms5003.convertPm25ToUsAqi(value.pm25_1)); } else { sprintf(strBuf, "%s", "-"); @@ -318,7 +315,7 @@ void OledDisplay::showDashboard(const char *status) { DISP()->setFont(u8g2_font_t0_12_tf); DISP()->drawUTF8(48, 61, "AQI"); } else { - if (value.pm25_1 >= 0) { + if (utils::isValidPMS(value.pm25_1)) { sprintf(strBuf, "%d", value.pm25_1); } else { sprintf(strBuf, "%s", "-"); @@ -333,7 +330,7 @@ void OledDisplay::showDashboard(const char *status) { DISP()->drawStr(85, 27, "tvoc:"); /** Draw tvocIndexvalue */ - if (value.TVOC >= 0) { + if (utils::isValidVOC(value.TVOC)) { sprintf(strBuf, "%d", value.TVOC); } else { sprintf(strBuf, "%s", "-"); @@ -342,7 +339,7 @@ void OledDisplay::showDashboard(const char *status) { /** Draw NOx label */ DISP()->drawStr(85, 53, "NOx:"); - if (value.NOx >= 0) { + if (utils::isValidNOx(value.NOx)) { sprintf(strBuf, "%d", value.NOx); } else { sprintf(strBuf, "%s", "-"); @@ -353,34 +350,49 @@ void OledDisplay::showDashboard(const char *status) { ag->display.clear(); /** Set CO2 */ - snprintf(strBuf, sizeof(strBuf), "CO2:%d", 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 */ ag->display.setCursor(0, 12); - snprintf(strBuf, sizeof(strBuf), "PM2.5:%d", value.pm25_1); + if (utils::isValidPMS(value.pm25_1)) { + snprintf(strBuf, sizeof(strBuf), "PM2.5:%d", value.pm25_1); + } else { + snprintf(strBuf, sizeof(strBuf), "PM2.5:-"); + } ag->display.setText(strBuf); /** Set temperature and humidity */ - if (value.Temperature <= -1001.0f) { - if (config.isTemperatureUnitInF()) { - snprintf(strBuf, sizeof(strBuf), "T:-F"); - } else { - snprintf(strBuf, sizeof(strBuf), "T:-C"); - } - } else { + if (utils::isValidTemperature(value.Temperature)) { if (config.isTemperatureUnitInF()) { float tempF = (value.Temperature * 9) / 5 + 32; snprintf(strBuf, sizeof(strBuf), "T:%d F", (int)tempF); } else { snprintf(strBuf, sizeof(strBuf), "T:%d C", (int)value.Temperature); } + } else { + if (config.isTemperatureUnitInF()) { + snprintf(strBuf, sizeof(strBuf), "T:-F"); + } else { + snprintf(strBuf, sizeof(strBuf), "T:-C"); + } } + ag->display.setCursor(0, 24); ag->display.setText(strBuf); - snprintf(strBuf, sizeof(strBuf), "H:%d %%", (int)value.Humidity); + if (utils::isValidHumidity(value.Humidity)) { + snprintf(strBuf, sizeof(strBuf), "H:%d %%", (int)value.Humidity); + } else { + snprintf(strBuf, sizeof(strBuf), "H:- %%"); + } + ag->display.setCursor(0, 36); ag->display.setText(strBuf); diff --git a/src/AgValue.cpp b/src/AgValue.cpp index bd729ea..b0cd3a0 100644 --- a/src/AgValue.cpp +++ b/src/AgValue.cpp @@ -1,6 +1,7 @@ #include "AgValue.h" #include "AgConfigure.h" #include "AirGradient.h" +#include "Main/utils.h" #include "Libraries/Arduino_JSON/src/Arduino_JSON.h" String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, @@ -13,36 +14,35 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, if (localServer) { root["serialno"] = ag->deviceId(); } - if (config->hasSensorS8) { - if (this->CO2 >= 0) { - root["rco2"] = this->CO2; - } + + if (config->hasSensorS8 && utils::isValidCO2(this->CO2)) { + root["rco2"] = this->CO2; } if (ag->isOne() || (ag->isPro4_2()) || ag->isPro3_3() || ag->isBasic()) { if (config->hasSensorPMS1) { - if (this->pm01_1 >= 0) { + if (utils::isValidPMS(this->pm01_1)) { root["pm01"] = this->pm01_1; } - if (this->pm25_1 >= 0) { + if (utils::isValidPMS(this->pm25_1)) { root["pm02"] = this->pm25_1; } - if (this->pm10_1 >= 0) { + if (utils::isValidPMS(this->pm10_1)) { root["pm10"] = this->pm10_1; } - if (this->pm03PCount_1 >= 0) { + if (utils::isValidPMS03Count(this->pm03PCount_1)) { root["pm003Count"] = this->pm03PCount_1; } } if (config->hasSensorSHT) { - if (this->Temperature > -1001) { + if (utils::isValidTemperature(this->Temperature)) { root["atmp"] = ag->round2(this->Temperature); if (localServer) { root["atmpCompensated"] = ag->round2(this->Temperature); } } - if (this->Humidity >= 0) { + if (utils::isValidHumidity(this->Humidity)) { root["rhum"] = this->Humidity; if (localServer) { root["rhumCompensated"] = this->Humidity; @@ -52,107 +52,250 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, } else { if (config->hasSensorPMS1 && config->hasSensorPMS2) { - root["pm01"] = ag->round2((this->pm01_1 + this->pm01_2) / 2.0); - root["pm02"] = ag->round2((this->pm25_1 + this->pm25_2) / 2.0); - root["pm10"] = ag->round2((this->pm10_1 + this->pm10_2) / 2.0); - root["pm003Count"] = - ag->round2((this->pm03PCount_1 + this->pm03PCount_2) / 2.0); - root["atmp"] = ag->round2((this->temp_1 + this->temp_2) / 2.0f); - root["rhum"] = ag->round2((this->hum_1 + this->hum_2) / 2.0f); - if (localServer) { - root["atmpCompensated"] = - ag->round2(ag->pms5003t_2.temperatureCompensated( - (this->temp_1 + this->temp_2) / 2.0f)); - root["rhumCompensated"] = (int)ag->pms5003t_2.humidityCompensated( - (this->hum_1 + this->hum_2) / 2.0f); + if (utils::isValidPMS(this->pm01_1) && utils::isValidPMS(this->pm01_2)) { + root["pm01"] = ag->round2((this->pm01_1 + this->pm01_2) / 2.0f); + } + if (utils::isValidPMS(this->pm25_1) && utils::isValidPMS(this->pm25_2)) { + root["pm02"] = ag->round2((this->pm25_1 + this->pm25_2) / 2.0f); + } + if (utils::isValidPMS(this->pm10_1) && utils::isValidPMS(this->pm10_2)) { + root["pm10"] = ag->round2((this->pm10_1 + this->pm10_2) / 2.0f); + } + if (utils::isValidPMS(this->pm03PCount_1) && utils::isValidPMS(this->pm03PCount_2)) { + root["pm003Count"] = ag->round2((this->pm03PCount_1 + this->pm03PCount_2) / 2.0f); + } + + float val; + if (utils::isValidTemperature(this->temp_1) && utils::isValidTemperature(this->temp_1)) { + root["atmp"] = ag->round2((this->temp_1 + this->temp_2) / 2.0f); + if (localServer) { + val = ag->pms5003t_2.temperatureCompensated((this->temp_1 + this->temp_2) / 2.0f); + if (utils::isValidTemperature(val)) { + root["atmpCompensated"] = ag->round2(val); + } + } + } + if (utils::isValidHumidity(this->hum_1) && utils::isValidHumidity(this->hum_1)) { + root["rhum"] = ag->round2((this->hum_1 + this->hum_2) / 2.0f); + if (localServer) { + val = ag->pms5003t_2.humidityCompensated((this->hum_1 + this->hum_2) / 2.0f); + if (utils::isValidHumidity(val)) { + root["rhumCompensated"] = (int)val; + } + } } } if (fwMode == FW_MODE_O_1PS || fwMode == FW_MODE_O_1PST) { + float val; if (config->hasSensorPMS1) { - root["pm01"] = this->pm01_1; - root["pm02"] = this->pm25_1; - root["pm10"] = this->pm10_1; - root["pm003Count"] = this->pm03PCount_1; - root["atmp"] = ag->round2(this->temp_1); - root["rhum"] = this->hum_1; - if (localServer) { - root["atmpCompensated"] = - ag->round2(ag->pms5003t_1.temperatureCompensated(this->temp_1)); - root["rhumCompensated"] = - (int)ag->pms5003t_1.humidityCompensated(this->hum_1); + if (utils::isValidPMS(this->pm01_1)) { + root["pm01"] = this->pm01_1; + } + if (utils::isValidPMS(this->pm25_1)) { + root["pm02"] = this->pm25_1; + } + if (utils::isValidPMS(this->pm10_1)) { + root["pm10"] = this->pm10_1; + } + if (utils::isValidPMS03Count(this->pm03PCount_1)) { + root["pm003Count"] = this->pm03PCount_1; + } + if (utils::isValidTemperature(this->temp_1)) { + root["atmp"] = ag->round2(this->temp_1); + + if (localServer) { + val = ag->pms5003t_1.temperatureCompensated(this->temp_1); + if (utils::isValidTemperature(val)) { + root["atmpCompensated"] = ag->round2(val); + } + } + } + if (utils::isValidHumidity(this->hum_1)) { + root["rhum"] = this->hum_1; + + if (localServer) { + val = ag->pms5003t_1.humidityCompensated(this->hum_1); + if (utils::isValidHumidity(val)) { + root["rhumCompensated"] = (int)val; + } + } } } if (config->hasSensorPMS2) { - root["pm01"] = this->pm01_2; - root["pm02"] = this->pm25_2; - root["pm10"] = this->pm10_2; - root["pm003Count"] = this->pm03PCount_2; - root["atmp"] = ag->round2(this->temp_2); - root["rhum"] = this->hum_2; - if (localServer) { - root["atmpCompensated"] = - ag->round2(ag->pms5003t_2.temperatureCompensated(this->temp_2)); - root["rhumCompensated"] = - (int)ag->pms5003t_2.humidityCompensated(this->hum_2); + if(utils::isValidPMS(this->pm01_2)) { + root["pm01"] = this->pm01_2; + } + if(utils::isValidPMS(this->pm25_2)) { + root["pm02"] = this->pm25_2; + } + if(utils::isValidPMS(this->pm10_2)) { + root["pm10"] = this->pm10_2; + } + if(utils::isValidPMS03Count(this->pm03PCount_2)) { + root["pm003Count"] = this->pm03PCount_2; + } + + float val; + if (utils::isValidTemperature(this->temp_2)) { + root["atmp"] = ag->round2(this->temp_2); + + if (localServer) { + val = ag->pms5003t_2.temperatureCompensated(this->temp_2); + if (utils::isValidTemperature(val)) { + root["atmpCompensated"] = ag->round2(val); + } + } + } + if(utils::isValidHumidity(this->hum_2)) { + root["rhum"] = this->hum_2; + + if (localServer) { + val = ag->pms5003t_2.humidityCompensated(this->hum_2); + if (utils::isValidHumidity(val)) { + root["rhumCompensated"] = (int)val; + } + } } } } else { if (fwMode == FW_MODE_O_1P) { + float val; if (config->hasSensorPMS1) { - root["pm01"] = this->pm01_1; - root["pm02"] = this->pm25_1; - root["pm10"] = this->pm10_1; - root["pm003Count"] = this->pm03PCount_1; - root["atmp"] = ag->round2(this->temp_1); - root["rhum"] = this->hum_1; - if (localServer) { - root["atmpCompensated"] = - ag->round2(ag->pms5003t_1.temperatureCompensated(this->temp_1)); - root["rhumCompensated"] = - (int)ag->pms5003t_1.humidityCompensated(this->hum_1); + if (utils::isValidPMS(this->pm01_1)) { + root["pm01"] = this->pm01_1; + } + if (utils::isValidPMS(this->pm25_1)) { + root["pm02"] = this->pm25_1; + } + if (utils::isValidPMS(this->pm10_1)) { + root["pm10"] = this->pm10_1; + } + if (utils::isValidPMS03Count(this->pm03PCount_1)) { + root["pm003Count"] = this->pm03PCount_1; + } + if (utils::isValidTemperature(this->temp_1)) { + root["atmp"] = ag->round2(this->temp_1); + + if (localServer) { + val = ag->pms5003t_1.temperatureCompensated(this->temp_1); + if (utils::isValidTemperature(val)) { + root["atmpCompensated"] = ag->round2(val); + } + } + } + if (utils::isValidHumidity(this->hum_1)) { + root["rhum"] = this->hum_1; + if(localServer) { + val = ag->pms5003t_1.humidityCompensated(this->hum_1); + if(utils::isValidHumidity(val)) { + root["rhumCompensated"] = (int)val; + } + } } } else if (config->hasSensorPMS2) { - root["pm01"] = this->pm01_2; - root["pm02"] = this->pm25_2; - root["pm10"] = this->pm10_2; - root["pm003Count"] = this->pm03PCount_2; - root["atmp"] = ag->round2(this->temp_2); - root["rhum"] = this->hum_2; - if (localServer) { - root["atmpCompensated"] = - ag->round2(ag->pms5003t_1.temperatureCompensated(this->temp_2)); - root["rhumCompensated"] = - (int)ag->pms5003t_1.humidityCompensated(this->hum_2); + if(utils::isValidPMS(this->pm01_2)) { + root["pm01"] = this->pm01_2; + } + if(utils::isValidPMS(this->pm25_2)) { + root["pm02"] = this->pm25_2; + } + if(utils::isValidPMS(this->pm10_2)) { + root["pm10"] = this->pm10_2; + } + if(utils::isValidPMS03Count(this->pm03PCount_2)) { + root["pm003Count"] = this->pm03PCount_2; + } + if (utils::isValidTemperature(this->temp_2)) { + root["atmp"] = ag->round2(this->temp_2); + if (localServer) { + + val = ag->pms5003t_1.temperatureCompensated(this->temp_2); + if (utils::isValidTemperature(val)) { + root["atmpCompensated"] = ag->round2(val); + } + } + } + if (utils::isValidHumidity(this->hum_2)) { + root["rhum"] = this->hum_2; + + if(localServer) { + val = ag->pms5003t_1.humidityCompensated(this->hum_2); + if(utils::isValidHumidity(val)) { + root["rhumCompensated"] = (int)val; + } + } } } } else { + float val; if (config->hasSensorPMS1) { - root["channels"]["1"]["pm01"] = this->pm01_1; - root["channels"]["1"]["pm02"] = this->pm25_1; - root["channels"]["1"]["pm10"] = this->pm10_1; - root["channels"]["1"]["pm003Count"] = this->pm03PCount_1; - root["channels"]["1"]["atmp"] = ag->round2(this->temp_1); - root["channels"]["1"]["rhum"] = this->hum_1; - if (localServer) { - root["channels"]["1"]["atmpCompensated"] = - ag->round2(ag->pms5003t_1.temperatureCompensated(this->temp_1)); - root["channels"]["1"]["rhumCompensated"] = - (int)ag->pms5003t_1.humidityCompensated(this->hum_1); + if(utils::isValidPMS(this->pm01_1)) { + root["channels"]["1"]["pm01"] = this->pm01_1; + } + if(utils::isValidPMS(this->pm25_1)) { + root["channels"]["1"]["pm02"] = this->pm25_1; + } + if(utils::isValidPMS(this->pm10_1)) { + root["channels"]["1"]["pm10"] = this->pm10_1; + } + if (utils::isValidPMS03Count(this->pm03PCount_1)) { + root["channels"]["1"]["pm003Count"] = this->pm03PCount_1; + } + if(utils::isValidTemperature(this->temp_1)) { + root["channels"]["1"]["atmp"] = ag->round2(this->temp_1); + + if (localServer) { + val = ag->pms5003t_1.temperatureCompensated(this->temp_1); + if (utils::isValidTemperature(val)) { + root["channels"]["1"]["atmpCompensated"] = ag->round2(val); + } + } + } + if (utils::isValidHumidity(this->hum_1)) { + root["channels"]["1"]["rhum"] = this->hum_1; + + if (localServer) { + val = ag->pms5003t_1.humidityCompensated(this->hum_1); + if (utils::isValidHumidity(val)) { + root["channels"]["1"]["rhumCompensated"] = (int)val; + } + } } } if (config->hasSensorPMS2) { - root["channels"]["2"]["pm01"] = this->pm01_2; - root["channels"]["2"]["pm02"] = this->pm25_2; - root["channels"]["2"]["pm10"] = this->pm10_2; - root["channels"]["2"]["pm003Count"] = this->pm03PCount_2; - root["channels"]["2"]["atmp"] = ag->round2(this->temp_2); - root["channels"]["2"]["rhum"] = this->hum_2; - if (localServer) { - root["channels"]["2"]["atmpCompensated"] = - ag->round2(ag->pms5003t_1.temperatureCompensated(this->temp_2)); - root["channels"]["2"]["rhumCompensated"] = - (int)ag->pms5003t_1.humidityCompensated(this->hum_2); + float val; + if (utils::isValidPMS(this->pm01_2)) { + root["channels"]["2"]["pm01"] = this->pm01_2; + } + if (utils::isValidPMS(this->pm25_2)) { + root["channels"]["2"]["pm02"] = this->pm25_2; + } + if (utils::isValidPMS(this->pm10_2)) { + root["channels"]["2"]["pm10"] = this->pm10_2; + } + if (utils::isValidPMS03Count(this->pm03PCount_2)) { + root["channels"]["2"]["pm003Count"] = this->pm03PCount_2; + } + if (utils::isValidTemperature(this->temp_2)) { + root["channels"]["2"]["atmp"] = ag->round2(this->temp_2); + + if (localServer) { + val = ag->pms5003t_1.temperatureCompensated(this->temp_2); + if (utils::isValidTemperature(val)) { + root["channels"]["2"]["atmpCompensated"] = ag->round2(val); + } + } + } + if (utils::isValidHumidity(this->hum_2)) { + root["channels"]["2"]["rhum"] = this->hum_2; + + if (localServer) { + val = ag->pms5003t_1.humidityCompensated(this->hum_2); + if (utils::isValidHumidity(val)) { + root["channels"]["2"]["rhumCompensated"] = (int)val; + } + } } } } @@ -160,16 +303,16 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, } if (config->hasSensorSGP) { - if (this->TVOC >= 0) { + if (utils::isValidVOC(this->TVOC)) { root["tvocIndex"] = this->TVOC; } - if (this->TVOCRaw >= 0) { + if (utils::isValidVOC(this->TVOCRaw)) { root["tvocRaw"] = this->TVOCRaw; } - if (this->NOx >= 0) { + if (utils::isValidNOx(this->NOx)) { root["noxIndex"] = this->NOx; } - if (this->NOxRaw >= 0) { + if (utils::isValidNOx(this->NOxRaw)) { root["noxRaw"] = this->NOxRaw; } } diff --git a/src/AirGradient.h b/src/AirGradient.h index 5c47e1b..54abd91 100644 --- a/src/AirGradient.h +++ b/src/AirGradient.h @@ -12,6 +12,7 @@ #include "S8/S8.h" #include "Sgp41/Sgp41.h" #include "Sht/Sht.h" +#include "Main/utils.h" #ifndef GIT_VERSION #define GIT_VERSION "snapshot" diff --git a/src/Main/utils.cpp b/src/Main/utils.cpp index dcd48cd..cedd357 100644 --- a/src/Main/utils.cpp +++ b/src/Main/utils.cpp @@ -1,49 +1,85 @@ #include "utils.h" -utils::utils(/* args */) -{ +#define VALID_TEMPERATURE_MAX (125) +#define VALID_TEMPERATURE_MIN (-40) +#define INVALID_TEMPERATURE (-41) + +#define VALID_HUMIDITY_MAX (100) +#define VALID_HUMIDITY_MIN (0) +#define INVALID_HUMIDITY (-1) + +#define VALID_PMS_MAX (1000) +#define VALID_PMS_MIN (0) +#define INVALID_PMS (-1) + +#define VALID_CO2_MAX (10000) +#define VALID_CO2_MIN (0) +#define INVALID_CO2 (-1) + +#define INVALID_NOX (-1) +#define INVALID_VOC (-1) + +utils::utils(/* args */) {} + +utils::~utils() {} + +bool utils::isValidTemperature(float value) { + if (value >= VALID_TEMPERATURE_MIN && value <= VALID_TEMPERATURE_MAX) { + return true; + } + return false; } -utils::~utils() -{ +bool utils::isValidHumidity(float value) { + if (value >= VALID_HUMIDITY_MIN && value <= VALID_HUMIDITY_MAX) { + return true; + } + return false; } -float utils::correctTemperature(float value) { - if (value < -40) { - return -40; +bool utils::isValidCO2(int16_t value) { + if (value >= VALID_CO2_MIN && value <= VALID_CO2_MAX) { + return true; } - if (value > 100) { - return 125; - } - return value; + return false; } -float utils::correctHumidity(float value) { - if (value < 0) { - return 0; +bool utils::isValidPMS(int value) { + if (value >= VALID_PMS_MIN && value <= VALID_PMS_MAX) { + return true; } - if (value > 100) { - return 100; - } - return value; + return false; } -int16_t utils::correctCO2(int16_t value) { - if (value < 0) { - return 0; +bool utils::isValidPMS03Count(int value) { + if (value >= 0) { + return true; } - if (value > 10000) { - return 10000; - } - return value; + return false; } -int utils::correctPMS(int value) { - if (value < 10) { - return 10; +bool utils::isValidNOx(int value) { + if (value > INVALID_NOX) { + return true; } - if (value > 1000) { - return 1000; - } - return value; + return false; } + +bool utils::isValidVOC(int value) { + if (value > INVALID_VOC) { + return true; + } + return false; +} + +float utils::getInvalidTemperature(void) { return INVALID_TEMPERATURE; } + +float utils::getInvalidHumidity(void) { return INVALID_HUMIDITY; } + +int utils::getInvalidCO2(void) { return INVALID_CO2; } + +int utils::getInvalidPMS(void) { return INVALID_PMS; } + +int utils::getInvalidNOx(void) { return INVALID_NOX; } + +int utils::getInvalidVOC(void) { return INVALID_VOC; } diff --git a/src/Main/utils.h b/src/Main/utils.h index 38786d8..841d5ec 100644 --- a/src/Main/utils.h +++ b/src/Main/utils.h @@ -11,10 +11,19 @@ public: utils(/* args */); ~utils(); - static float correctTemperature(float value); - static float correctHumidity(float value); - static int16_t correctCO2(int16_t value); - static int correctPMS(int value); + static bool isValidTemperature(float value); + static bool isValidHumidity(float value); + static bool isValidCO2(int16_t value); + static bool isValidPMS(int value); + static bool isValidPMS03Count(int value); + static bool isValidNOx(int value); + static bool isValidVOC(int value); + static float getInvalidTemperature(void); + static float getInvalidHumidity(void); + static int getInvalidCO2(void); + static int getInvalidPMS(void); + static int getInvalidNOx(void); + static int getInvalidVOC(void); }; diff --git a/src/PMS/PMS5003.cpp b/src/PMS/PMS5003.cpp index 1719ccc..0c1ea83 100644 --- a/src/PMS/PMS5003.cpp +++ b/src/PMS/PMS5003.cpp @@ -88,21 +88,21 @@ bool PMS5003::begin(void) { * * @return int PM1.0 index */ -int PMS5003::getPm01Ae(void) { return utils::correctPMS(pms.getPM0_1()); } +int PMS5003::getPm01Ae(void) { return pms.getPM0_1(); } /** * @brief Read PM2.5 must call this function after @ref readData success * * @return int PM2.5 index */ -int PMS5003::getPm25Ae(void) { return utils::correctPMS(pms.getPM2_5()); } +int PMS5003::getPm25Ae(void) { return pms.getPM2_5(); } /** * @brief Read PM10.0 must call this function after @ref readData success * * @return int PM10.0 index */ -int PMS5003::getPm10Ae(void) { return utils::correctPMS(pms.getPM10()); } +int PMS5003::getPm10Ae(void) { return pms.getPM10(); } /** * @brief Read PM0.3 must call this function after @ref readData success @@ -110,7 +110,7 @@ int PMS5003::getPm10Ae(void) { return utils::correctPMS(pms.getPM10()); } * @return int PM0.3 index */ int PMS5003::getPm03ParticleCount(void) { - return utils::correctPMS(pms.getCount0_3()); + return pms.getCount0_3(); } /** diff --git a/src/PMS/PMS5003T.cpp b/src/PMS/PMS5003T.cpp index d8b0b6b..4f427fd 100644 --- a/src/PMS/PMS5003T.cpp +++ b/src/PMS/PMS5003T.cpp @@ -113,21 +113,21 @@ bool PMS5003T::begin(void) { * * @return int PM1.0 index */ -int PMS5003T::getPm01Ae(void) { return utils::correctPMS(pms.getPM0_1()); } +int PMS5003T::getPm01Ae(void) { return pms.getPM0_1(); } /** * @brief Read PM2.5 must call this function after @ref readData success * * @return int PM2.5 index */ -int PMS5003T::getPm25Ae(void) { return utils::correctPMS(pms.getPM2_5()); } +int PMS5003T::getPm25Ae(void) { return pms.getPM2_5(); } /** * @brief Read PM10.0 must call this function after @ref readData success * * @return int PM10.0 index */ -int PMS5003T::getPm10Ae(void) { return utils::correctPMS(pms.getPM10()); } +int PMS5003T::getPm10Ae(void) { return pms.getPM10(); } /** * @brief Read PM 0.3 Count must call this function after @ref readData success @@ -135,7 +135,7 @@ int PMS5003T::getPm10Ae(void) { return utils::correctPMS(pms.getPM10()); } * @return int PM 0.3 Count index */ int PMS5003T::getPm03ParticleCount(void) { - return utils::correctPMS(pms.getCount0_3()); + return pms.getCount0_3(); } /** @@ -152,7 +152,7 @@ int PMS5003T::convertPm25ToUsAqi(int pm25) { return pms.pm25ToAQI(pm25); } * @return float Degree Celcius */ float PMS5003T::getTemperature(void) { - return utils::correctTemperature(pms.getTemp() / 10.0f); + return pms.getTemp() / 10.0f; } /** @@ -161,7 +161,7 @@ float PMS5003T::getTemperature(void) { * @return float Percent (%) */ float PMS5003T::getRelativeHumidity(void) { - return utils::correctHumidity(pms.getHum() / 10.0f); + return pms.getHum() / 10.0f; } /** diff --git a/src/S8/S8.cpp b/src/S8/S8.cpp index 981a8f6..a8f9158 100644 --- a/src/S8/S8.cpp +++ b/src/S8/S8.cpp @@ -104,7 +104,7 @@ void S8::getFirmwareVersion(char firmver[]) { */ int32_t S8::getSensorTypeId(void) { if (this->isBegin() == false) { - return -1; + return utils::getInvalidCO2(); } int32_t sensorType = 0; @@ -246,7 +246,7 @@ int16_t S8::getCo2(void) { AgLog("Error getting CO2 value!"); } - return utils::correctCO2(co2); + return co2; } /** diff --git a/src/Sgp41/Sgp41.cpp b/src/Sgp41/Sgp41.cpp index 502dcb9..3f957a1 100644 --- a/src/Sgp41/Sgp41.cpp +++ b/src/Sgp41/Sgp41.cpp @@ -2,6 +2,7 @@ #include "../Libraries/SensirionSGP41/src/SensirionI2CSgp41.h" #include "../Libraries/Sensirion_Gas_Index_Algorithm/src/NOxGasIndexAlgorithm.h" #include "../Libraries/Sensirion_Gas_Index_Algorithm/src/VOCGasIndexAlgorithm.h" +#include "../Main/utils.h" #define sgpSensor() ((SensirionI2CSgp41 *)(this->_sensor)) #define vocAlgorithm() ((VOCGasIndexAlgorithm *)(this->_vocAlgorithm)) @@ -66,6 +67,7 @@ bool Sgp41::begin(TwoWire &wire) { } onConditioning = true; + _handleFailCount = 0; #ifdef ESP32 /** Create task */ xTaskCreate( @@ -108,7 +110,21 @@ void Sgp41::handle(void) { noxRaw = srawNox; nox = noxAlgorithm()->process(srawNox); tvoc = vocAlgorithm()->process(srawVoc); + + _handleFailCount = 0; // AgLog("Polling SGP41 success: tvoc: %d, nox: %d", tvoc, nox); + } else { + if(_handleFailCount < 5) { + _handleFailCount++; + AgLog("Polling SGP41 failed: %d", _handleFailCount); + } + + if (_handleFailCount >= 5) { + tvocRaw = utils::getInvalidVOC(); + tvoc = utils::getInvalidVOC(); + noxRaw = utils::getInvalidNOx(); + nox = utils::getInvalidNOx(); + } } } } @@ -141,7 +157,21 @@ void Sgp41::_handle(void) { noxRaw = srawNox; nox = noxAlgorithm()->process(srawNox); tvoc = vocAlgorithm()->process(srawVoc); + + _handleFailCount = 0; // AgLog("Polling SGP41 success: tvoc: %d, nox: %d", tvoc, nox); + } else { + if(_handleFailCount < 5) { + _handleFailCount++; + AgLog("Polling SGP41 failed: %d", _handleFailCount); + } + + if (_handleFailCount >= 5) { + tvocRaw = utils::getInvalidVOC(); + tvoc = utils::getInvalidVOC(); + noxRaw = utils::getInvalidNOx(); + nox = utils::getInvalidNOx(); + } } } } @@ -176,7 +206,7 @@ void Sgp41::end(void) { */ int Sgp41::getTvocIndex(void) { if (onConditioning) { - return -1; + return utils::getInvalidVOC(); } return tvoc; } @@ -188,7 +218,7 @@ int Sgp41::getTvocIndex(void) { */ int Sgp41::getNoxIndex(void) { if (onConditioning) { - return -1; + return utils::getInvalidNOx(); } return nox; } diff --git a/src/Sgp41/Sgp41.h b/src/Sgp41/Sgp41.h index 9e5674e..381af7f 100644 --- a/src/Sgp41/Sgp41.h +++ b/src/Sgp41/Sgp41.h @@ -35,6 +35,7 @@ private: bool onConditioning = true; bool ready = false; bool _isBegin = false; + uint8_t _handleFailCount = 0; void *_sensor; void *_vocAlgorithm; void *_noxAlgorithm; diff --git a/src/Sht/Sht.cpp b/src/Sht/Sht.cpp index fe1932d..0492ee1 100644 --- a/src/Sht/Sht.cpp +++ b/src/Sht/Sht.cpp @@ -133,7 +133,7 @@ void Sht::end(void) { * @return float */ float Sht::getTemperature(void) { - return utils::correctTemperature(shtSensor()->getTemperature()); + return shtSensor()->getTemperature(); } /** @@ -142,7 +142,7 @@ float Sht::getTemperature(void) { * @return float */ float Sht::getRelativeHumidity(void) { - return utils::correctHumidity(shtSensor()->getHumidity()); + return shtSensor()->getHumidity(); } /** From 9ae9b2ac9cfeaaa7288b55a42add6c212c35cebd Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Wed, 24 Jul 2024 20:18:48 +0700 Subject: [PATCH 07/16] display float value on display with 1 digit --- src/AgOledDisplay.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AgOledDisplay.cpp b/src/AgOledDisplay.cpp index 7dcf65f..224565f 100644 --- a/src/AgOledDisplay.cpp +++ b/src/AgOledDisplay.cpp @@ -372,9 +372,9 @@ void OledDisplay::showDashboard(const char *status) { if (utils::isValidTemperature(value.Temperature)) { if (config.isTemperatureUnitInF()) { float tempF = (value.Temperature * 9) / 5 + 32; - snprintf(strBuf, sizeof(strBuf), "T:%d F", (int)tempF); + snprintf(strBuf, sizeof(strBuf), "T:%0.1f F", tempF); } else { - snprintf(strBuf, sizeof(strBuf), "T:%d C", (int)value.Temperature); + snprintf(strBuf, sizeof(strBuf), "T:%0.f1 C", value.Temperature); } } else { if (config.isTemperatureUnitInF()) { From c12bac4ce3a1211545b37fafc9bc2a81adb0809c Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Wed, 24 Jul 2024 20:19:06 +0700 Subject: [PATCH 08/16] Update invalid temperature value --- src/Main/utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Main/utils.cpp b/src/Main/utils.cpp index cedd357..386a520 100644 --- a/src/Main/utils.cpp +++ b/src/Main/utils.cpp @@ -2,7 +2,7 @@ #define VALID_TEMPERATURE_MAX (125) #define VALID_TEMPERATURE_MIN (-40) -#define INVALID_TEMPERATURE (-41) +#define INVALID_TEMPERATURE (-1000) #define VALID_HUMIDITY_MAX (100) #define VALID_HUMIDITY_MIN (0) From 9097eed137746e1f94525774926586b0e57b3ec0 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Wed, 24 Jul 2024 20:31:43 +0700 Subject: [PATCH 09/16] [fix] typo comment --- src/AgStateMachine.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/AgStateMachine.cpp b/src/AgStateMachine.cpp index 62305d8..b6e9610 100644 --- a/src/AgStateMachine.cpp +++ b/src/AgStateMachine.cpp @@ -10,7 +10,7 @@ #define RGB_COLOR_R 255, 0, 0 /** Red */ #define RGB_COLOR_G 0, 255, 0 /** Green */ #define RGB_COLOR_Y 255, 150, 0 /** Yellow */ -#define RGB_COLOR_O 255, 40, 0 /** Organge */ +#define RGB_COLOR_O 255, 40, 0 /** Orange */ #define RGB_COLOR_P 180, 0, 255 /** Purple */ /** @@ -573,7 +573,7 @@ void StateMachine::handleLeds(AgStateMachineState state) { case AgStateMachineWiFiManagerMode: { /** In WiFi Manager Mode */ /** Turn LED OFF */ - /** Turn midle LED Color */ + /** Turn middle LED Color */ if (ag->isOne()) { ag->ledBar.setColor(0, 0, 255, ag->ledBar.getNumberOfLeds() / 2); } else { @@ -713,7 +713,7 @@ void StateMachine::handleLeds(AgStateMachineState state) { break; } case AgStateMachineSensorConfigFailed: { - /** Server is reachable but there is some configuration issue to be fixed on + /** Server is reachable but there is some configuration issue to be fixed on * the server side */ if (ag->isOne()) { ag->ledBar.setColor(139, 24, 248, 0); From ed7b8df6fe2d5e683ae598f3a967455ced58332b Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Mon, 29 Jul 2024 06:00:54 +0700 Subject: [PATCH 10/16] log URLs of all HTTP requests to AG backend / log status codes of responses --- src/AgApiClient.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/AgApiClient.cpp b/src/AgApiClient.cpp index 1f7c83b..8a523ad 100644 --- a/src/AgApiClient.cpp +++ b/src/AgApiClient.cpp @@ -66,6 +66,10 @@ bool AgApiClient::fetchServerConfiguration(void) { /** Get data */ int retCode = client.GET(); + + logInfo(String("GET: ") + uri); + logInfo(String("Return code: ") + String(retCode)); + if (retCode != 200) { client.end(); getConfigFailed = true; @@ -112,18 +116,22 @@ bool AgApiClient::postToServer(String data) { String uri = "http://hw.airgradient.com/sensors/airgradient:" + ag->deviceId() + "/measures"; - logInfo("Post uri: " + uri); - logInfo("Post data: " + data); + // logInfo("Post uri: " + uri); + // logInfo("Post data: " + data); WiFiClient wifiClient; HTTPClient client; if (client.begin(wifiClient, uri.c_str()) == false) { + logError("Init client failed"); return false; } client.addHeader("content-type", "application/json"); int retCode = client.POST(data); client.end(); + logInfo(String("POST: ") + uri); + logInfo(String("Return code: ") + String(retCode)); + if ((retCode == 200) || (retCode == 429)) { postToServerFailed = false; return true; From b0ae851427fb202f840a43ec87334286abb86625 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Tue, 30 Jul 2024 20:26:19 +0700 Subject: [PATCH 11/16] Fix nox position --- src/AgOledDisplay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AgOledDisplay.cpp b/src/AgOledDisplay.cpp index 044fb8e..05f54f6 100644 --- a/src/AgOledDisplay.cpp +++ b/src/AgOledDisplay.cpp @@ -338,7 +338,7 @@ void OledDisplay::showDashboard(const char *status) { DISP()->drawStr(100, 39, strBuf); /** Draw NOx label */ - DISP()->drawStr(85, 53, "NOx:"); + DISP()->drawStr(100, 53, "NOx:"); if (utils::isValidNOx(value.NOx)) { sprintf(strBuf, "%d", value.NOx); } else { From e46e11c03066a4aba3706b90f9184582c1c94178 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Thu, 8 Aug 2024 05:53:24 +0700 Subject: [PATCH 12/16] `round2` support negative value --- src/AirGradient.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/AirGradient.cpp b/src/AirGradient.cpp index e036982..46ed874 100644 --- a/src/AirGradient.cpp +++ b/src/AirGradient.cpp @@ -41,7 +41,14 @@ String AirGradient::getVersion(void) { return GIT_VERSION; } BoardType AirGradient::getBoardType(void) { return boardType; } double AirGradient::round2(double value) { - return (int)(value * 100 + 0.5) / 100.0; + double ret; + if (value >= 0) { + ret = (int)(value * 100 + 0.5f); + } else { + ret = (int)(value * 100 - 0.5f); + } + + return ret / 100; } String AirGradient::getBoardName(void) { From 97f0696002853035a1f4592a23671c78f2573d51 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Fri, 9 Aug 2024 13:19:28 +0700 Subject: [PATCH 13/16] set default wifi on factory reset. --- examples/OneOpenAir/OneOpenAir.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/OneOpenAir/OneOpenAir.ino b/examples/OneOpenAir/OneOpenAir.ino index 5f026ca..80deb36 100644 --- a/examples/OneOpenAir/OneOpenAir.ino +++ b/examples/OneOpenAir/OneOpenAir.ino @@ -421,8 +421,8 @@ static void factoryConfigReset(void) { } /** Reset WIFI */ - WiFi.enableSTA(true); // Incase offline mode - WiFi.disconnect(true, true); + Serial.println("Set wifi connect to 'airgradient' as default"); + WiFi.begin("airgradient", "cleanair"); /** Reset local config */ configuration.reset(); From 5edb21cfe9b6474327cdf89a87dac644fa9b3d84 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Thu, 15 Aug 2024 09:10:48 +0700 Subject: [PATCH 14/16] Fix: PMS5003T only return positive temperature value --- src/PMS/PMS.cpp | 48 +++++++++++++++++++++++++++++------------------- src/PMS/PMS.h | 5 +++-- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/PMS/PMS.cpp b/src/PMS/PMS.cpp index e9a1527..d4101fe 100644 --- a/src/PMS/PMS.cpp +++ b/src/PMS/PMS.cpp @@ -3,7 +3,7 @@ /** * @brief Init and check that sensor has connected - * + * * @param stream UART stream * @return true Sucecss * @return false Failure @@ -86,7 +86,7 @@ void PMSBase::handle() { case 2: { buf[bufIndex++] = value; if (bufIndex >= 4) { - len = toValue(&buf[2]); + len = toI16(&buf[2]); if (len != 28) { // Serial.printf("Got good bad len %d\r\n", len); len += 4; @@ -152,98 +152,98 @@ bool PMSBase::isFailed(void) { return failed; } * * @return uint16_t */ -uint16_t PMSBase::getRaw0_1(void) { return toValue(&package[4]); } +uint16_t PMSBase::getRaw0_1(void) { return toU16(&package[4]); } /** * @brief Read PMS 2.5 ug/m3 with CF = 1 PM estimates * * @return uint16_t */ -uint16_t PMSBase::getRaw2_5(void) { return toValue(&package[6]); } +uint16_t PMSBase::getRaw2_5(void) { return toU16(&package[6]); } /** * @brief Read PMS 10 ug/m3 with CF = 1 PM estimates * * @return uint16_t */ -uint16_t PMSBase::getRaw10(void) { return toValue(&package[8]); } +uint16_t PMSBase::getRaw10(void) { return toU16(&package[8]); } /** * @brief Read PMS 0.1 ug/m3 * * @return uint16_t */ -uint16_t PMSBase::getPM0_1(void) { return toValue(&package[10]); } +uint16_t PMSBase::getPM0_1(void) { return toU16(&package[10]); } /** * @brief Read PMS 2.5 ug/m3 * * @return uint16_t */ -uint16_t PMSBase::getPM2_5(void) { return toValue(&package[12]); } +uint16_t PMSBase::getPM2_5(void) { return toU16(&package[12]); } /** * @brief Read PMS 10 ug/m3 * * @return uint16_t */ -uint16_t PMSBase::getPM10(void) { return toValue(&package[14]); } +uint16_t PMSBase::getPM10(void) { return toU16(&package[14]); } /** * @brief Get numnber concentrations over 0.3 um/0.1L * * @return uint16_t */ -uint16_t PMSBase::getCount0_3(void) { return toValue(&package[16]); } +uint16_t PMSBase::getCount0_3(void) { return toU16(&package[16]); } /** * @brief Get numnber concentrations over 0.5 um/0.1L * * @return uint16_t */ -uint16_t PMSBase::getCount0_5(void) { return toValue(&package[18]); } +uint16_t PMSBase::getCount0_5(void) { return toU16(&package[18]); } /** * @brief Get numnber concentrations over 1.0 um/0.1L * * @return uint16_t */ -uint16_t PMSBase::getCount1_0(void) { return toValue(&package[20]); } +uint16_t PMSBase::getCount1_0(void) { return toU16(&package[20]); } /** * @brief Get numnber concentrations over 2.5 um/0.1L * * @return uint16_t */ -uint16_t PMSBase::getCount2_5(void) { return toValue(&package[22]); } +uint16_t PMSBase::getCount2_5(void) { return toU16(&package[22]); } /** * @brief Get numnber concentrations over 5.0 um/0.1L (only PMS5003) * * @return uint16_t */ -uint16_t PMSBase::getCount5_0(void) { return toValue(&package[24]); } +uint16_t PMSBase::getCount5_0(void) { return toU16(&package[24]); } /** * @brief Get numnber concentrations over 10.0 um/0.1L (only PMS5003) * * @return uint16_t */ -uint16_t PMSBase::getCount10(void) { return toValue(&package[26]); } +uint16_t PMSBase::getCount10(void) { return toU16(&package[26]); } /** * @brief Get temperature (only PMS5003T) * * @return uint16_t */ -uint16_t PMSBase::getTemp(void) { return toValue(&package[24]); } +int16_t PMSBase::getTemp(void) { return toI16(&package[24]); } /** * @brief Get humidity (only PMS5003T) * * @return uint16_t */ -uint16_t PMSBase::getHum(void) { return toValue(&package[26]); } +uint16_t PMSBase::getHum(void) { return toU16(&package[26]); } /** * @brief Convert PMS2.5 to US AQI unit @@ -274,9 +274,19 @@ int PMSBase::pm25ToAQI(int pm02) { * @brief Convert two byte value to uint16_t value * * @param buf bytes array (must be >= 2) - * @return uint16_t + * @return int16_t */ -uint16_t PMSBase::toValue(char *buf) { return (buf[0] << 8) | buf[1]; } +int16_t PMSBase::toI16(char *buf) { + int16_t value = buf[0]; + value = (value << 8) | buf[1]; + return value; +} + +uint16_t PMSBase::toU16(char *buf) { + uint16_t value = buf[0]; + value = (value << 8) | buf[1]; + return value; +} /** * @brief Validate package data @@ -290,7 +300,7 @@ bool PMSBase::validate(char *buf) { for (int i = 0; i < 30; i++) { sum += buf[i]; } - if (sum == toValue(&buf[30])) { + if (sum == toU16(&buf[30])) { for (int i = 0; i < 32; i++) { package[i] = buf[i]; } diff --git a/src/PMS/PMS.h b/src/PMS/PMS.h index 4fa086a..2e65930 100644 --- a/src/PMS/PMS.h +++ b/src/PMS/PMS.h @@ -24,7 +24,7 @@ public: uint16_t getCount10(void); /** For PMS5003T*/ - uint16_t getTemp(void); + int16_t getTemp(void); uint16_t getHum(void); int pm25ToAQI(int pm02); @@ -36,7 +36,8 @@ private: bool failed = false; uint32_t lastRead; - uint16_t toValue(char *buf); + int16_t toI16(char *buf); + uint16_t toU16(char* buf); bool validate(char *buf); }; From 3be321811592cb6d4faee660cd7fc67d55bda985 Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Thu, 15 Aug 2024 09:11:38 +0700 Subject: [PATCH 15/16] Update invalid value and optimize code operator. --- src/Main/utils.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Main/utils.cpp b/src/Main/utils.cpp index 386a520..1c8175d 100644 --- a/src/Main/utils.cpp +++ b/src/Main/utils.cpp @@ -12,10 +12,14 @@ #define VALID_PMS_MIN (0) #define INVALID_PMS (-1) +#define VALID_PMS03COUNT_MIN (0) + #define VALID_CO2_MAX (10000) #define VALID_CO2_MIN (0) #define INVALID_CO2 (-1) +#define VALID_NOX_MIN (0) +#define VALID_VOC_MIN (0) #define INVALID_NOX (-1) #define INVALID_VOC (-1) @@ -24,49 +28,49 @@ utils::utils(/* args */) {} utils::~utils() {} bool utils::isValidTemperature(float value) { - if (value >= VALID_TEMPERATURE_MIN && value <= VALID_TEMPERATURE_MAX) { + if ((value >= VALID_TEMPERATURE_MIN) && (value <= VALID_TEMPERATURE_MAX)) { return true; } return false; } bool utils::isValidHumidity(float value) { - if (value >= VALID_HUMIDITY_MIN && value <= VALID_HUMIDITY_MAX) { + if ((value >= VALID_HUMIDITY_MIN) && (value <= VALID_HUMIDITY_MAX)) { return true; } return false; } bool utils::isValidCO2(int16_t value) { - if (value >= VALID_CO2_MIN && value <= VALID_CO2_MAX) { + if ((value >= VALID_CO2_MIN) && (value <= VALID_CO2_MAX)) { return true; } return false; } bool utils::isValidPMS(int value) { - if (value >= VALID_PMS_MIN && value <= VALID_PMS_MAX) { + if ((value >= VALID_PMS_MIN) && (value <= VALID_PMS_MAX)) { return true; } return false; } bool utils::isValidPMS03Count(int value) { - if (value >= 0) { + if (value >= VALID_PMS03COUNT_MIN) { return true; } return false; } bool utils::isValidNOx(int value) { - if (value > INVALID_NOX) { + if (value >= VALID_NOX_MIN) { return true; } return false; } bool utils::isValidVOC(int value) { - if (value > INVALID_VOC) { + if (value >= VALID_VOC_MIN) { return true; } return false; From f3a9c722b254dfcd9a910034c736765bb14cd84b Mon Sep 17 00:00:00 2001 From: Phat Nguyen Date: Fri, 16 Aug 2024 06:39:52 +0700 Subject: [PATCH 16/16] Change `pm25Compensated` to `compensated` --- src/AgOledDisplay.cpp | 4 ++-- src/AgValue.cpp | 18 +++++++++--------- src/PMS/PMS.cpp | 4 ++-- src/PMS/PMS.h | 2 +- src/PMS/PMS5003.cpp | 4 ++-- src/PMS/PMS5003.h | 2 +- src/PMS/PMS5003T.cpp | 4 ++-- src/PMS/PMS5003T.h | 2 +- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/AgOledDisplay.cpp b/src/AgOledDisplay.cpp index adf2ab5..8b07ada 100644 --- a/src/AgOledDisplay.cpp +++ b/src/AgOledDisplay.cpp @@ -306,7 +306,7 @@ void OledDisplay::showDashboard(const char *status) { /** Draw PM2.5 value */ int pm25 = value.pm25_1; if (config.hasSensorSHT) { - pm25 = ag->pms5003.pm25Compensated(pm25, value.Humidity); + pm25 = ag->pms5003.compensated(pm25, value.Humidity); } DISP()->setFont(u8g2_font_t0_22b_tf); if (config.isPmStandardInUSAQI()) { @@ -366,7 +366,7 @@ void OledDisplay::showDashboard(const char *status) { /** Set PM */ int pm25 = value.pm25_1; if(config.hasSensorSHT) { - pm25 = (int)ag->pms5003.pm25Compensated(pm25, value.Humidity); + pm25 = (int)ag->pms5003.compensated(pm25, value.Humidity); } ag->display.setCursor(0, 12); if (utils::isValidPMS(value.pm25_1)) { diff --git a/src/AgValue.cpp b/src/AgValue.cpp index 0f39922..015a788 100644 --- a/src/AgValue.cpp +++ b/src/AgValue.cpp @@ -51,7 +51,7 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, } if (config->hasSensorSHT && config->hasSensorPMS1) { - int pm25 = ag->pms5003.pm25Compensated(this->pm25_1, this->Humidity); + int pm25 = ag->pms5003.compensated(this->pm25_1, this->Humidity); if (pm25 >= 0) { root["pm02Compensated"] = pm25; } @@ -92,8 +92,8 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, } } - int pm25 = (ag->pms5003t_1.pm25Compensated(this->pm25_1, this->temp_1) + - ag->pms5003t_2.pm25Compensated(this->pm25_2, this->temp_2)) / + int pm25 = (ag->pms5003t_1.compensated(this->pm25_1, this->temp_1) + + ag->pms5003t_2.compensated(this->pm25_2, this->temp_2)) / 2; root["pm02Compensated"] = pm25; } @@ -133,7 +133,7 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, } } } - root["pm02Compensated"] = ag->pms5003t_1.pm25Compensated(this->pm25_1, this->temp_1); + root["pm02Compensated"] = ag->pms5003t_1.compensated(this->pm25_1, this->temp_1); } if (config->hasSensorPMS2) { if(utils::isValidPMS(this->pm01_2)) { @@ -170,7 +170,7 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, } } } - root["pm02Compensated"] = ag->pms5003t_2.pm25Compensated(this->pm25_2, this->temp_2); + root["pm02Compensated"] = ag->pms5003t_2.compensated(this->pm25_2, this->temp_2); } } else { if (fwMode == FW_MODE_O_1P) { @@ -207,7 +207,7 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, } } } - root["pm02Compensated"] = ag->pms5003t_1.pm25Compensated(this->pm25_1, this->temp_1); + root["pm02Compensated"] = ag->pms5003t_1.compensated(this->pm25_1, this->temp_1); } else if (config->hasSensorPMS2) { if(utils::isValidPMS(this->pm01_2)) { root["pm01"] = this->pm01_2; @@ -241,7 +241,7 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, } } } - root["pm02Compensated"] = ag->pms5003t_1.pm25Compensated(this->pm25_1, this->temp_1); + root["pm02Compensated"] = ag->pms5003t_1.compensated(this->pm25_1, this->temp_1); } } else { float val; @@ -278,7 +278,7 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, } } } - root["channels"]["1"]["pm02Compensated"] = ag->pms5003t_1.pm25Compensated(this->pm25_1, this->temp_1); + root["channels"]["1"]["pm02Compensated"] = ag->pms5003t_1.compensated(this->pm25_1, this->temp_1); } if (config->hasSensorPMS2) { float val; @@ -314,7 +314,7 @@ String Measurements::toString(bool localServer, AgFirmwareMode fwMode, int rssi, } } } - root["channels"]["2"]["pm02Compensated"] = ag->pms5003t_2.pm25Compensated(this->pm25_2, this->temp_2); + root["channels"]["2"]["pm02Compensated"] = ag->pms5003t_2.compensated(this->pm25_2, this->temp_2); } } } diff --git a/src/PMS/PMS.cpp b/src/PMS/PMS.cpp index 0a091fd..fb32767 100644 --- a/src/PMS/PMS.cpp +++ b/src/PMS/PMS.cpp @@ -275,9 +275,9 @@ int PMSBase::pm25ToAQI(int pm02) { * * @param pm25 Raw PM2.5 value * @param humidity Humidity value (%) - * @return float + * @return int */ -int PMSBase::pm25Compensated(int pm25, float humidity) { +int PMSBase::compensated(int pm25, float humidity) { float value; if (humidity < 0) { humidity = 0; diff --git a/src/PMS/PMS.h b/src/PMS/PMS.h index c748d6b..43e61b0 100644 --- a/src/PMS/PMS.h +++ b/src/PMS/PMS.h @@ -28,7 +28,7 @@ public: uint16_t getHum(void); int pm25ToAQI(int pm02); - int pm25Compensated(int pm25, float humidity); + int compensated(int pm25, float humidity); private: Stream *stream; diff --git a/src/PMS/PMS5003.cpp b/src/PMS/PMS5003.cpp index 09a9e8d..8a49550 100644 --- a/src/PMS/PMS5003.cpp +++ b/src/PMS/PMS5003.cpp @@ -128,8 +128,8 @@ int PMS5003::convertPm25ToUsAqi(int pm25) { return pms.pm25ToAQI(pm25); } * @param humidity Humidity value * @return float */ -int PMS5003::pm25Compensated(int pm25, float humidity) { - return pms.pm25Compensated(pm25, humidity); +int PMS5003::compensated(int pm25, float humidity) { + return pms.compensated(pm25, humidity); } /** diff --git a/src/PMS/PMS5003.h b/src/PMS/PMS5003.h index b5be03c..aa6fcd9 100644 --- a/src/PMS/PMS5003.h +++ b/src/PMS/PMS5003.h @@ -24,7 +24,7 @@ public: int getPm10Ae(void); int getPm03ParticleCount(void); int convertPm25ToUsAqi(int pm25); - int pm25Compensated(int pm25, float humidity); + int compensated(int pm25, float humidity); private: bool _isBegin = false; diff --git a/src/PMS/PMS5003T.cpp b/src/PMS/PMS5003T.cpp index e754c6e..97cc9c7 100644 --- a/src/PMS/PMS5003T.cpp +++ b/src/PMS/PMS5003T.cpp @@ -171,8 +171,8 @@ float PMS5003T::getRelativeHumidity(void) { * @param humidity Humidity value * @return float */ -float PMS5003T::pm25Compensated(int pm25, float humidity) { - return pms.pm25Compensated(pm25, humidity); +float PMS5003T::compensated(int pm25, float humidity) { + return pms.compensated(pm25, humidity); } /** diff --git a/src/PMS/PMS5003T.h b/src/PMS/PMS5003T.h index 48b8333..3d2d567 100644 --- a/src/PMS/PMS5003T.h +++ b/src/PMS/PMS5003T.h @@ -29,7 +29,7 @@ public: int convertPm25ToUsAqi(int pm25); float getTemperature(void); float getRelativeHumidity(void); - float pm25Compensated(int pm25, float humidity); + float compensated(int pm25, float humidity); private: bool _isBegin = false;