diff --git a/examples/BASIC/BASIC.ino b/examples/BASIC/BASIC.ino index b3be046..66daa1c 100644 --- a/examples/BASIC/BASIC.ino +++ b/examples/BASIC/BASIC.ino @@ -49,9 +49,8 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License #define SENSOR_TVOC_UPDATE_INTERVAL 1000 /** ms */ #define SENSOR_CO2_UPDATE_INTERVAL 4000 /** ms */ #define SENSOR_PM_UPDATE_INTERVAL 2000 /** ms */ -#define SENSOR_TEMP_HUM_UPDATE_INTERVAL 2000 /** ms */ +#define SENSOR_TEMP_HUM_UPDATE_INTERVAL 6000 /** ms */ #define DISPLAY_DELAY_SHOW_CONTENT_MS 2000 /** ms */ -#define FIRMWARE_CHECK_FOR_UPDATE_MS (60 * 60 * 1000) /** ms */ static AirGradient ag(DIY_BASIC); static Configuration configuration(Serial); @@ -68,7 +67,6 @@ static LocalServer localServer(Serial, openMetrics, measurements, configuration, wifiConnector); static MqttClient mqttClient(Serial); -static int getCO2FailCount = 0; static AgFirmwareMode fwMode = FW_MODE_I_BASIC_40PS; static String fwNewVersion; @@ -90,6 +88,8 @@ static void wdgFeedUpdate(void); static bool sgp41Init(void); static void wifiFactoryConfigure(void); static void mqttHandle(void); +static int calculateMaxPeriod(int updateInterval); +static void setMeasurementMaxPeriod(); AgSchedule dispLedSchedule(DISP_UPDATE_INTERVAL, oledDisplaySchedule); AgSchedule configSchedule(SERVER_CONFIG_SYNC_INTERVAL, @@ -130,6 +130,10 @@ void setup() { /** Init sensor */ boardInit(); + setMeasurementMaxPeriod(); + + // Uncomment below line to print every measurements reading update + // measurements.setDebug(true); /** Connecting wifi */ bool connectToWifi = false; @@ -230,17 +234,16 @@ void loop() { } static void co2Update(void) { + if (!configuration.hasSensorS8) { + // Device don't have S8 sensor + return; + } + int value = ag.s8.getCo2(); if (utils::isValidCO2(value)) { - measurements.CO2 = value; - getCO2FailCount = 0; - Serial.printf("CO2 (ppm): %d\r\n", measurements.CO2); + measurements.update(Measurements::CO2, value); } else { - getCO2FailCount++; - Serial.printf("Get CO2 failed: %d\r\n", getCO2FailCount); - if (getCO2FailCount >= 3) { - measurements.CO2 = utils::getInvalidCO2(); - } + measurements.update(Measurements::CO2, utils::getInvalidCO2()); } } @@ -313,8 +316,7 @@ static void mqttHandle(void) { } if (mqttClient.isConnected()) { - String payload = measurements.toString(true, fwMode, wifiConnector.RSSI(), - &ag, &configuration); + String payload = measurements.toString(true, fwMode, wifiConnector.RSSI(), ag, configuration); String topic = "airgradient/readings/" + ag.deviceId(); if (mqttClient.publish(topic.c_str(), payload.c_str(), payload.length())) { Serial.println("MQTT sync success"); @@ -490,46 +492,27 @@ static void oledDisplaySchedule(void) { } static void updateTvoc(void) { - measurements.TVOC = ag.sgp41.getTvocIndex(); - measurements.TVOCRaw = ag.sgp41.getTvocRaw(); - measurements.NOx = ag.sgp41.getNoxIndex(); - measurements.NOxRaw = ag.sgp41.getNoxRaw(); + if (!configuration.hasSensorSGP) { + return; + } - Serial.println(); - Serial.printf("TVOC index: %d\r\n", measurements.TVOC); - Serial.printf("TVOC raw: %d\r\n", measurements.TVOCRaw); - Serial.printf("NOx index: %d\r\n", measurements.NOx); - Serial.printf("NOx raw: %d\r\n", measurements.NOxRaw); + measurements.update(Measurements::TVOC, ag.sgp41.getTvocIndex()); + measurements.update(Measurements::TVOCRaw, ag.sgp41.getTvocRaw()); + measurements.update(Measurements::NOx, ag.sgp41.getNoxIndex()); + measurements.update(Measurements::NOxRaw, ag.sgp41.getNoxRaw()); } static void updatePm(void) { if (ag.pms5003.connected()) { - measurements.pm01_1 = ag.pms5003.getPm01Ae(); - measurements.pm25_1 = ag.pms5003.getPm25Ae(); - measurements.pm10_1 = ag.pms5003.getPm10Ae(); - measurements.pm03PCount_1 = ag.pms5003.getPm03ParticleCount(); - - Serial.println(); - Serial.printf("PM1 ug/m3: %d\r\n", measurements.pm01_1); - Serial.printf("PM2.5 ug/m3: %d\r\n", measurements.pm25_1); - Serial.printf("PM10 ug/m3: %d\r\n", measurements.pm10_1); - Serial.printf("PM0.3 Count: %d\r\n", measurements.pm03PCount_1); - Serial.printf("PM firmware version: %d\r\n", ag.pms5003.getFirmwareVersion()); - ag.pms5003.resetFailCount(); + measurements.update(Measurements::PM01, ag.pms5003.getPm01Ae()); + measurements.update(Measurements::PM25, ag.pms5003.getPm25Ae()); + measurements.update(Measurements::PM10, ag.pms5003.getPm10Ae()); + measurements.update(Measurements::PM03_PC, ag.pms5003.getPm03ParticleCount()); } else { - ag.pms5003.updateFailCount(); - Serial.printf("PMS read failed %d times\r\n", ag.pms5003.getFailCount()); - if (ag.pms5003.getFailCount() >= PMS_FAIL_COUNT_SET_INVALID) { - measurements.pm01_1 = utils::getInvalidPmValue(); - measurements.pm25_1 = utils::getInvalidPmValue(); - measurements.pm10_1 = utils::getInvalidPmValue(); - measurements.pm03PCount_1 = utils::getInvalidPmValue(); - } - - if(ag.pms5003.getFailCount() >= ag.pms5003.getFailCountMax()) { - Serial.printf("PMS failure count reach to max set %d, restarting...", ag.pms5003.getFailCountMax()); - ESP.restart(); - } + measurements.update(Measurements::PM01, utils::getInvalidPmValue()); + measurements.update(Measurements::PM25, utils::getInvalidPmValue()); + measurements.update(Measurements::PM10, utils::getInvalidPmValue()); + measurements.update(Measurements::PM03_PC, utils::getInvalidPmValue()); } } @@ -540,8 +523,7 @@ static void sendDataToServer(void) { return; } - String syncData = measurements.toString(false, fwMode, wifiConnector.RSSI(), - &ag, &configuration); + String syncData = measurements.toString(false, fwMode, wifiConnector.RSSI(), ag, configuration); if (apiClient.postToServer(syncData)) { Serial.println(); Serial.println( @@ -552,26 +534,54 @@ static void sendDataToServer(void) { } static void tempHumUpdate(void) { - delay(100); if (ag.sht.measure()) { - measurements.Temperature = ag.sht.getTemperature(); - measurements.Humidity = ag.sht.getRelativeHumidity(); + float temp = ag.sht.getTemperature(); + float rhum = ag.sht.getRelativeHumidity(); - Serial.printf("Temperature in C: %0.2f\r\n", measurements.Temperature); - Serial.printf("Relative Humidity: %d\r\n", measurements.Humidity); - Serial.printf("Temperature compensated in C: %0.2f\r\n", - measurements.Temperature); - Serial.printf("Relative Humidity compensated: %d\r\n", - measurements.Humidity); + measurements.update(Measurements::Temperature, temp); + measurements.update(Measurements::Humidity, rhum); // Update compensation temperature and humidity for SGP41 if (configuration.hasSensorSGP) { - ag.sgp41.setCompensationTemperatureHumidity(measurements.Temperature, - measurements.Humidity); + ag.sgp41.setCompensationTemperatureHumidity(temp, rhum); } } else { + measurements.update(Measurements::Temperature, utils::getInvalidTemperature()); + measurements.update(Measurements::Humidity, utils::getInvalidHumidity()); Serial.println("SHT read failed"); - measurements.Temperature = utils::getInvalidTemperature(); - measurements.Humidity = utils::getInvalidHumidity(); } } + +/* Set max period for each measurement type based on sensor update interval*/ +void setMeasurementMaxPeriod() { + /// Max period for S8 sensors measurements + measurements.maxPeriod(Measurements::CO2, calculateMaxPeriod(SENSOR_CO2_UPDATE_INTERVAL)); + /// Max period for SGP sensors measurements + measurements.maxPeriod(Measurements::TVOC, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::TVOCRaw, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::NOx, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::NOxRaw, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); + /// Max period for PMS sensors measurements + measurements.maxPeriod(Measurements::PM25, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::PM01, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::PM10, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::PM03_PC, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + // Temperature and Humidity + if (configuration.hasSensorSHT) { + /// Max period for SHT sensors measurements + measurements.maxPeriod(Measurements::Temperature, + calculateMaxPeriod(SENSOR_TEMP_HUM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::Humidity, + calculateMaxPeriod(SENSOR_TEMP_HUM_UPDATE_INTERVAL)); + } else { + /// Temp and hum data retrieved from PMS5003T sensor + measurements.maxPeriod(Measurements::Temperature, + calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::Humidity, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + } +} + +int calculateMaxPeriod(int updateInterval) { + // 0.5 is 50% reduced interval for max period + return (SERVER_SYNC_INTERVAL - (SERVER_SYNC_INTERVAL * 0.5)) / updateInterval; +} \ No newline at end of file diff --git a/examples/BASIC/LocalServer.cpp b/examples/BASIC/LocalServer.cpp index 8970ece..61a6dfb 100644 --- a/examples/BASIC/LocalServer.cpp +++ b/examples/BASIC/LocalServer.cpp @@ -53,9 +53,8 @@ void LocalServer::_GET_metrics(void) { } void LocalServer::_GET_measure(void) { - server.send( - 200, "application/json", - measure.toString(true, fwMode, wifiConnector.RSSI(), ag, &config)); + String toSend = measure.toString(true, fwMode, wifiConnector.RSSI(), *ag, config); + server.send(200, "application/json", toSend); } void LocalServer::setFwMode(AgFirmwareMode fwMode) { this->fwMode = fwMode; } diff --git a/examples/BASIC/OpenMetrics.cpp b/examples/BASIC/OpenMetrics.cpp index cffd2c6..ddf2d4c 100644 --- a/examples/BASIC/OpenMetrics.cpp +++ b/examples/BASIC/OpenMetrics.cpp @@ -73,19 +73,30 @@ String OpenMetrics::getPayload(void) { int pm03PCount = utils::getInvalidPmValue(); int atmpCompensated = utils::getInvalidTemperature(); int ahumCompensated = utils::getInvalidHumidity(); + int tvoc = utils::getInvalidVOC(); + int tvoc_raw = utils::getInvalidVOC(); + int nox = utils::getInvalidNOx(); + int nox_raw = utils::getInvalidNOx(); if (config.hasSensorSHT) { - _temp = measure.Temperature; - _hum = measure.Humidity; + _temp = measure.getFloat(Measurements::Temperature); + _hum = measure.getFloat(Measurements::Humidity); atmpCompensated = _temp; ahumCompensated = _hum; } if (config.hasSensorPMS1) { - pm01 = measure.pm01_1; - pm25 = measure.pm25_1; - pm10 = measure.pm10_1; - pm03PCount = measure.pm03PCount_1; + pm01 = measure.get(Measurements::PM01); + pm25 = measure.get(Measurements::PM25); + pm10 = measure.get(Measurements::PM10); + pm03PCount = measure.get(Measurements::PM03_PC); + } + + if (config.hasSensorSGP) { + tvoc = measure.get(Measurements::TVOC); + tvoc_raw = measure.get(Measurements::TVOCRaw); + nox = measure.get(Measurements::NOx); + nox_raw = measure.get(Measurements::NOxRaw); } if (config.hasSensorPMS1) { @@ -120,33 +131,33 @@ String OpenMetrics::getPayload(void) { } if (config.hasSensorSGP) { - if (utils::isValidVOC(measure.TVOC)) { + if (utils::isValidVOC(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)); + add_metric_point("", String(tvoc)); } - if (utils::isValidVOC(measure.TVOCRaw)) { + if (utils::isValidVOC(tvoc_raw)) { 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)); + add_metric_point("", String(tvoc_raw)); } - if (utils::isValidNOx(measure.NOx)) { + if (utils::isValidNOx(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)); + add_metric_point("", String(nox)); } - if (utils::isValidNOx(measure.NOxRaw)) { + if (utils::isValidNOx(nox_raw)) { add_metric("nox_raw", "The raw input value to the Nitrous Oxide (NOx) index as " "measured by the AirGradient SGP sensor", "gauge"); - add_metric_point("", String(measure.NOxRaw)); + add_metric_point("", String(nox_raw)); } } diff --git a/examples/DiyProIndoorV3_3/DiyProIndoorV3_3.ino b/examples/DiyProIndoorV3_3/DiyProIndoorV3_3.ino index b67e262..dd87cb4 100644 --- a/examples/DiyProIndoorV3_3/DiyProIndoorV3_3.ino +++ b/examples/DiyProIndoorV3_3/DiyProIndoorV3_3.ino @@ -49,9 +49,8 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License #define SENSOR_TVOC_UPDATE_INTERVAL 1000 /** ms */ #define SENSOR_CO2_UPDATE_INTERVAL 4000 /** ms */ #define SENSOR_PM_UPDATE_INTERVAL 2000 /** ms */ -#define SENSOR_TEMP_HUM_UPDATE_INTERVAL 2000 /** ms */ +#define SENSOR_TEMP_HUM_UPDATE_INTERVAL 6000 /** ms */ #define DISPLAY_DELAY_SHOW_CONTENT_MS 2000 /** ms */ -#define FIRMWARE_CHECK_FOR_UPDATE_MS (60 * 60 * 1000) /** ms */ static AirGradient ag(DIY_PRO_INDOOR_V3_3); static Configuration configuration(Serial); @@ -68,7 +67,6 @@ static LocalServer localServer(Serial, openMetrics, measurements, configuration, wifiConnector); static MqttClient mqttClient(Serial); -static int getCO2FailCount = 0; static AgFirmwareMode fwMode = FW_MODE_I_33PS; static String fwNewVersion; @@ -90,6 +88,8 @@ static void wdgFeedUpdate(void); static bool sgp41Init(void); static void wifiFactoryConfigure(void); static void mqttHandle(void); +static int calculateMaxPeriod(int updateInterval); +static void setMeasurementMaxPeriod(); AgSchedule dispLedSchedule(DISP_UPDATE_INTERVAL, oledDisplaySchedule); AgSchedule configSchedule(SERVER_CONFIG_SYNC_INTERVAL, @@ -130,6 +130,10 @@ void setup() { /** Init sensor */ boardInit(); + setMeasurementMaxPeriod(); + + // Uncomment below line to print every measurements reading update + // measurements.setDebug(true); /** Connecting wifi */ bool connectToWifi = false; @@ -228,17 +232,16 @@ void loop() { } static void co2Update(void) { + if (!configuration.hasSensorS8) { + // Device don't have S8 sensor + return; + } + int value = ag.s8.getCo2(); if (utils::isValidCO2(value)) { - measurements.CO2 = value; - getCO2FailCount = 0; - Serial.printf("CO2 (ppm): %d\r\n", measurements.CO2); + measurements.update(Measurements::CO2, value); } else { - getCO2FailCount++; - Serial.printf("Get CO2 failed: %d\r\n", getCO2FailCount); - if (getCO2FailCount >= 3) { - measurements.CO2 = utils::getInvalidCO2(); - } + measurements.update(Measurements::CO2, utils::getInvalidCO2()); } } @@ -370,8 +373,7 @@ static void mqttHandle(void) { } if (mqttClient.isConnected()) { - String payload = measurements.toString(true, fwMode, wifiConnector.RSSI(), - &ag, &configuration); + String payload = measurements.toString(true, fwMode, wifiConnector.RSSI(), ag, configuration); String topic = "airgradient/readings/" + ag.deviceId(); if (mqttClient.publish(topic.c_str(), payload.c_str(), payload.length())) { Serial.println("MQTT sync success"); @@ -542,46 +544,27 @@ static void oledDisplaySchedule(void) { } static void updateTvoc(void) { - measurements.TVOC = ag.sgp41.getTvocIndex(); - measurements.TVOCRaw = ag.sgp41.getTvocRaw(); - measurements.NOx = ag.sgp41.getNoxIndex(); - measurements.NOxRaw = ag.sgp41.getNoxRaw(); + if (!configuration.hasSensorSGP) { + return; + } - Serial.println(); - Serial.printf("TVOC index: %d\r\n", measurements.TVOC); - Serial.printf("TVOC raw: %d\r\n", measurements.TVOCRaw); - Serial.printf("NOx index: %d\r\n", measurements.NOx); - Serial.printf("NOx raw: %d\r\n", measurements.NOxRaw); + measurements.update(Measurements::TVOC, ag.sgp41.getTvocIndex()); + measurements.update(Measurements::TVOCRaw, ag.sgp41.getTvocRaw()); + measurements.update(Measurements::NOx, ag.sgp41.getNoxIndex()); + measurements.update(Measurements::NOxRaw, ag.sgp41.getNoxRaw()); } static void updatePm(void) { if (ag.pms5003.connected()) { - measurements.pm01_1 = ag.pms5003.getPm01Ae(); - measurements.pm25_1 = ag.pms5003.getPm25Ae(); - measurements.pm10_1 = ag.pms5003.getPm10Ae(); - measurements.pm03PCount_1 = ag.pms5003.getPm03ParticleCount(); - - Serial.println(); - Serial.printf("PM1 ug/m3: %d\r\n", measurements.pm01_1); - Serial.printf("PM2.5 ug/m3: %d\r\n", measurements.pm25_1); - Serial.printf("PM10 ug/m3: %d\r\n", measurements.pm10_1); - Serial.printf("PM0.3 Count: %d\r\n", measurements.pm03PCount_1); - Serial.printf("PM firmware version: %d\r\n", ag.pms5003.getFirmwareVersion()); - ag.pms5003.resetFailCount(); + measurements.update(Measurements::PM01, ag.pms5003.getPm01Ae()); + measurements.update(Measurements::PM25, ag.pms5003.getPm25Ae()); + measurements.update(Measurements::PM10, ag.pms5003.getPm10Ae()); + measurements.update(Measurements::PM03_PC, ag.pms5003.getPm03ParticleCount()); } else { - ag.pms5003.updateFailCount(); - Serial.printf("PMS read failed %d times\r\n", ag.pms5003.getFailCount()); - if (ag.pms5003.getFailCount() >= PMS_FAIL_COUNT_SET_INVALID) { - measurements.pm01_1 = utils::getInvalidPmValue(); - measurements.pm25_1 = utils::getInvalidPmValue(); - measurements.pm10_1 = utils::getInvalidPmValue(); - measurements.pm03PCount_1 = utils::getInvalidPmValue(); - } - - if(ag.pms5003.getFailCount() >= ag.pms5003.getFailCountMax()) { - Serial.printf("PMS failure count reach to max set %d, restarting...", ag.pms5003.getFailCountMax()); - ESP.restart(); - } + measurements.update(Measurements::PM01, utils::getInvalidPmValue()); + measurements.update(Measurements::PM25, utils::getInvalidPmValue()); + measurements.update(Measurements::PM10, utils::getInvalidPmValue()); + measurements.update(Measurements::PM03_PC, utils::getInvalidPmValue()); } } @@ -592,8 +575,7 @@ static void sendDataToServer(void) { return; } - String syncData = measurements.toString(false, fwMode, wifiConnector.RSSI(), - &ag, &configuration); + String syncData = measurements.toString(false, fwMode, wifiConnector.RSSI(), ag, configuration); if (apiClient.postToServer(syncData)) { Serial.println(); Serial.println( @@ -604,26 +586,54 @@ static void sendDataToServer(void) { } static void tempHumUpdate(void) { - delay(100); if (ag.sht.measure()) { - measurements.Temperature = ag.sht.getTemperature(); - measurements.Humidity = ag.sht.getRelativeHumidity(); + float temp = ag.sht.getTemperature(); + float rhum = ag.sht.getRelativeHumidity(); - Serial.printf("Temperature in C: %0.2f\r\n", measurements.Temperature); - Serial.printf("Relative Humidity: %d\r\n", measurements.Humidity); - Serial.printf("Temperature compensated in C: %0.2f\r\n", - measurements.Temperature); - Serial.printf("Relative Humidity compensated: %d\r\n", - measurements.Humidity); + measurements.update(Measurements::Temperature, temp); + measurements.update(Measurements::Humidity, rhum); // Update compensation temperature and humidity for SGP41 if (configuration.hasSensorSGP) { - ag.sgp41.setCompensationTemperatureHumidity(measurements.Temperature, - measurements.Humidity); + ag.sgp41.setCompensationTemperatureHumidity(temp, rhum); } } else { + measurements.update(Measurements::Temperature, utils::getInvalidTemperature()); + measurements.update(Measurements::Humidity, utils::getInvalidHumidity()); Serial.println("SHT read failed"); - measurements.Temperature = utils::getInvalidTemperature(); - measurements.Humidity = utils::getInvalidHumidity(); } } + +/* Set max period for each measurement type based on sensor update interval*/ +void setMeasurementMaxPeriod() { + /// Max period for S8 sensors measurements + measurements.maxPeriod(Measurements::CO2, calculateMaxPeriod(SENSOR_CO2_UPDATE_INTERVAL)); + /// Max period for SGP sensors measurements + measurements.maxPeriod(Measurements::TVOC, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::TVOCRaw, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::NOx, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::NOxRaw, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); + /// Max period for PMS sensors measurements + measurements.maxPeriod(Measurements::PM25, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::PM01, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::PM10, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::PM03_PC, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + // Temperature and Humidity + if (configuration.hasSensorSHT) { + /// Max period for SHT sensors measurements + measurements.maxPeriod(Measurements::Temperature, + calculateMaxPeriod(SENSOR_TEMP_HUM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::Humidity, + calculateMaxPeriod(SENSOR_TEMP_HUM_UPDATE_INTERVAL)); + } else { + /// Temp and hum data retrieved from PMS5003T sensor + measurements.maxPeriod(Measurements::Temperature, + calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::Humidity, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + } +} + +int calculateMaxPeriod(int updateInterval) { + // 0.5 is 50% reduced interval for max period + return (SERVER_SYNC_INTERVAL - (SERVER_SYNC_INTERVAL * 0.5)) / updateInterval; +} \ No newline at end of file diff --git a/examples/DiyProIndoorV3_3/LocalServer.cpp b/examples/DiyProIndoorV3_3/LocalServer.cpp index 8970ece..61a6dfb 100644 --- a/examples/DiyProIndoorV3_3/LocalServer.cpp +++ b/examples/DiyProIndoorV3_3/LocalServer.cpp @@ -53,9 +53,8 @@ void LocalServer::_GET_metrics(void) { } void LocalServer::_GET_measure(void) { - server.send( - 200, "application/json", - measure.toString(true, fwMode, wifiConnector.RSSI(), ag, &config)); + String toSend = measure.toString(true, fwMode, wifiConnector.RSSI(), *ag, config); + server.send(200, "application/json", toSend); } void LocalServer::setFwMode(AgFirmwareMode fwMode) { this->fwMode = fwMode; } diff --git a/examples/DiyProIndoorV3_3/OpenMetrics.cpp b/examples/DiyProIndoorV3_3/OpenMetrics.cpp index cffd2c6..ddf2d4c 100644 --- a/examples/DiyProIndoorV3_3/OpenMetrics.cpp +++ b/examples/DiyProIndoorV3_3/OpenMetrics.cpp @@ -73,19 +73,30 @@ String OpenMetrics::getPayload(void) { int pm03PCount = utils::getInvalidPmValue(); int atmpCompensated = utils::getInvalidTemperature(); int ahumCompensated = utils::getInvalidHumidity(); + int tvoc = utils::getInvalidVOC(); + int tvoc_raw = utils::getInvalidVOC(); + int nox = utils::getInvalidNOx(); + int nox_raw = utils::getInvalidNOx(); if (config.hasSensorSHT) { - _temp = measure.Temperature; - _hum = measure.Humidity; + _temp = measure.getFloat(Measurements::Temperature); + _hum = measure.getFloat(Measurements::Humidity); atmpCompensated = _temp; ahumCompensated = _hum; } if (config.hasSensorPMS1) { - pm01 = measure.pm01_1; - pm25 = measure.pm25_1; - pm10 = measure.pm10_1; - pm03PCount = measure.pm03PCount_1; + pm01 = measure.get(Measurements::PM01); + pm25 = measure.get(Measurements::PM25); + pm10 = measure.get(Measurements::PM10); + pm03PCount = measure.get(Measurements::PM03_PC); + } + + if (config.hasSensorSGP) { + tvoc = measure.get(Measurements::TVOC); + tvoc_raw = measure.get(Measurements::TVOCRaw); + nox = measure.get(Measurements::NOx); + nox_raw = measure.get(Measurements::NOxRaw); } if (config.hasSensorPMS1) { @@ -120,33 +131,33 @@ String OpenMetrics::getPayload(void) { } if (config.hasSensorSGP) { - if (utils::isValidVOC(measure.TVOC)) { + if (utils::isValidVOC(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)); + add_metric_point("", String(tvoc)); } - if (utils::isValidVOC(measure.TVOCRaw)) { + if (utils::isValidVOC(tvoc_raw)) { 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)); + add_metric_point("", String(tvoc_raw)); } - if (utils::isValidNOx(measure.NOx)) { + if (utils::isValidNOx(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)); + add_metric_point("", String(nox)); } - if (utils::isValidNOx(measure.NOxRaw)) { + if (utils::isValidNOx(nox_raw)) { add_metric("nox_raw", "The raw input value to the Nitrous Oxide (NOx) index as " "measured by the AirGradient SGP sensor", "gauge"); - add_metric_point("", String(measure.NOxRaw)); + add_metric_point("", String(nox_raw)); } } diff --git a/examples/DiyProIndoorV4_2/DiyProIndoorV4_2.ino b/examples/DiyProIndoorV4_2/DiyProIndoorV4_2.ino index bac20a5..7a2a800 100644 --- a/examples/DiyProIndoorV4_2/DiyProIndoorV4_2.ino +++ b/examples/DiyProIndoorV4_2/DiyProIndoorV4_2.ino @@ -49,9 +49,8 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License #define SENSOR_TVOC_UPDATE_INTERVAL 1000 /** ms */ #define SENSOR_CO2_UPDATE_INTERVAL 4000 /** ms */ #define SENSOR_PM_UPDATE_INTERVAL 2000 /** ms */ -#define SENSOR_TEMP_HUM_UPDATE_INTERVAL 2000 /** ms */ +#define SENSOR_TEMP_HUM_UPDATE_INTERVAL 6000 /** ms */ #define DISPLAY_DELAY_SHOW_CONTENT_MS 2000 /** ms */ -#define FIRMWARE_CHECK_FOR_UPDATE_MS (60 * 60 * 1000) /** ms */ static AirGradient ag(DIY_PRO_INDOOR_V4_2); static Configuration configuration(Serial); @@ -69,7 +68,6 @@ static LocalServer localServer(Serial, openMetrics, measurements, configuration, static MqttClient mqttClient(Serial); static uint32_t factoryBtnPressTime = 0; -static int getCO2FailCount = 0; static AgFirmwareMode fwMode = FW_MODE_I_42PS; static String fwNewVersion; @@ -91,6 +89,8 @@ static void wdgFeedUpdate(void); static bool sgp41Init(void); static void wifiFactoryConfigure(void); static void mqttHandle(void); +static int calculateMaxPeriod(int updateInterval); +static void setMeasurementMaxPeriod(); AgSchedule dispLedSchedule(DISP_UPDATE_INTERVAL, oledDisplaySchedule); AgSchedule configSchedule(SERVER_CONFIG_SYNC_INTERVAL, @@ -131,6 +131,10 @@ void setup() { /** Init sensor */ boardInit(); + setMeasurementMaxPeriod(); + + // Uncomment below line to print every measurements reading update + // measurements.setDebug(true); /** Connecting wifi */ bool connectToWifi = false; @@ -255,17 +259,16 @@ void loop() { } static void co2Update(void) { + if (!configuration.hasSensorS8) { + // Device don't have S8 sensor + return; + } + int value = ag.s8.getCo2(); if (utils::isValidCO2(value)) { - measurements.CO2 = value; - getCO2FailCount = 0; - Serial.printf("CO2 (ppm): %d\r\n", measurements.CO2); + measurements.update(Measurements::CO2, value); } else { - getCO2FailCount++; - Serial.printf("Get CO2 failed: %d\r\n", getCO2FailCount); - if (getCO2FailCount >= 3) { - measurements.CO2 = utils::getInvalidCO2(); - } + measurements.update(Measurements::CO2, utils::getInvalidCO2()); } } @@ -393,8 +396,7 @@ static void mqttHandle(void) { } if (mqttClient.isConnected()) { - String payload = measurements.toString(true, fwMode, wifiConnector.RSSI(), - &ag, &configuration); + String payload = measurements.toString(true, fwMode, wifiConnector.RSSI(), ag, configuration); String topic = "airgradient/readings/" + ag.deviceId(); if (mqttClient.publish(topic.c_str(), payload.c_str(), payload.length())) { Serial.println("MQTT sync success"); @@ -583,46 +585,27 @@ static void oledDisplaySchedule(void) { } static void updateTvoc(void) { - measurements.TVOC = ag.sgp41.getTvocIndex(); - measurements.TVOCRaw = ag.sgp41.getTvocRaw(); - measurements.NOx = ag.sgp41.getNoxIndex(); - measurements.NOxRaw = ag.sgp41.getNoxRaw(); + if (!configuration.hasSensorSGP) { + return; + } - Serial.println(); - Serial.printf("TVOC index: %d\r\n", measurements.TVOC); - Serial.printf("TVOC raw: %d\r\n", measurements.TVOCRaw); - Serial.printf("NOx index: %d\r\n", measurements.NOx); - Serial.printf("NOx raw: %d\r\n", measurements.NOxRaw); + measurements.update(Measurements::TVOC, ag.sgp41.getTvocIndex()); + measurements.update(Measurements::TVOCRaw, ag.sgp41.getTvocRaw()); + measurements.update(Measurements::NOx, ag.sgp41.getNoxIndex()); + measurements.update(Measurements::NOxRaw, ag.sgp41.getNoxRaw()); } static void updatePm(void) { if (ag.pms5003.connected()) { - measurements.pm01_1 = ag.pms5003.getPm01Ae(); - measurements.pm25_1 = ag.pms5003.getPm25Ae(); - measurements.pm10_1 = ag.pms5003.getPm10Ae(); - measurements.pm03PCount_1 = ag.pms5003.getPm03ParticleCount(); - - Serial.println(); - Serial.printf("PM1 ug/m3: %d\r\n", measurements.pm01_1); - Serial.printf("PM2.5 ug/m3: %d\r\n", measurements.pm25_1); - Serial.printf("PM10 ug/m3: %d\r\n", measurements.pm10_1); - Serial.printf("PM0.3 Count: %d\r\n", measurements.pm03PCount_1); - Serial.printf("PM firmware version: %d\r\n", ag.pms5003.getFirmwareVersion()); - ag.pms5003.resetFailCount(); + measurements.update(Measurements::PM01, ag.pms5003.getPm01Ae()); + measurements.update(Measurements::PM25, ag.pms5003.getPm25Ae()); + measurements.update(Measurements::PM10, ag.pms5003.getPm10Ae()); + measurements.update(Measurements::PM03_PC, ag.pms5003.getPm03ParticleCount()); } else { - ag.pms5003.updateFailCount(); - Serial.printf("PMS read failed %d times\r\n", ag.pms5003.getFailCount()); - if (ag.pms5003.getFailCount() >= PMS_FAIL_COUNT_SET_INVALID) { - measurements.pm01_1 = utils::getInvalidPmValue(); - measurements.pm25_1 = utils::getInvalidPmValue(); - measurements.pm10_1 = utils::getInvalidPmValue(); - measurements.pm03PCount_1 = utils::getInvalidPmValue(); - } - - if(ag.pms5003.getFailCount() >= ag.pms5003.getFailCountMax()) { - Serial.printf("PMS failure count reach to max set %d, restarting...", ag.pms5003.getFailCountMax()); - ESP.restart(); - } + measurements.update(Measurements::PM01, utils::getInvalidPmValue()); + measurements.update(Measurements::PM25, utils::getInvalidPmValue()); + measurements.update(Measurements::PM10, utils::getInvalidPmValue()); + measurements.update(Measurements::PM03_PC, utils::getInvalidPmValue()); } } @@ -633,8 +616,7 @@ static void sendDataToServer(void) { return; } - String syncData = measurements.toString(false, fwMode, wifiConnector.RSSI(), - &ag, &configuration); + String syncData = measurements.toString(false, fwMode, wifiConnector.RSSI(), ag, configuration); if (apiClient.postToServer(syncData)) { Serial.println(); Serial.println( @@ -645,26 +627,54 @@ static void sendDataToServer(void) { } static void tempHumUpdate(void) { - delay(100); if (ag.sht.measure()) { - measurements.Temperature = ag.sht.getTemperature(); - measurements.Humidity = ag.sht.getRelativeHumidity(); + float temp = ag.sht.getTemperature(); + float rhum = ag.sht.getRelativeHumidity(); - Serial.printf("Temperature in C: %0.2f\r\n", measurements.Temperature); - Serial.printf("Relative Humidity: %d\r\n", measurements.Humidity); - Serial.printf("Temperature compensated in C: %0.2f\r\n", - measurements.Temperature); - Serial.printf("Relative Humidity compensated: %d\r\n", - measurements.Humidity); + measurements.update(Measurements::Temperature, temp); + measurements.update(Measurements::Humidity, rhum); // Update compensation temperature and humidity for SGP41 if (configuration.hasSensorSGP) { - ag.sgp41.setCompensationTemperatureHumidity(measurements.Temperature, - measurements.Humidity); + ag.sgp41.setCompensationTemperatureHumidity(temp, rhum); } } else { + measurements.update(Measurements::Temperature, utils::getInvalidTemperature()); + measurements.update(Measurements::Humidity, utils::getInvalidHumidity()); Serial.println("SHT read failed"); - measurements.Temperature = utils::getInvalidTemperature(); - measurements.Humidity = utils::getInvalidHumidity(); } } + +/* Set max period for each measurement type based on sensor update interval*/ +void setMeasurementMaxPeriod() { + /// Max period for S8 sensors measurements + measurements.maxPeriod(Measurements::CO2, calculateMaxPeriod(SENSOR_CO2_UPDATE_INTERVAL)); + /// Max period for SGP sensors measurements + measurements.maxPeriod(Measurements::TVOC, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::TVOCRaw, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::NOx, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::NOxRaw, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); + /// Max period for PMS sensors measurements + measurements.maxPeriod(Measurements::PM25, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::PM01, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::PM10, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::PM03_PC, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + // Temperature and Humidity + if (configuration.hasSensorSHT) { + /// Max period for SHT sensors measurements + measurements.maxPeriod(Measurements::Temperature, + calculateMaxPeriod(SENSOR_TEMP_HUM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::Humidity, + calculateMaxPeriod(SENSOR_TEMP_HUM_UPDATE_INTERVAL)); + } else { + /// Temp and hum data retrieved from PMS5003T sensor + measurements.maxPeriod(Measurements::Temperature, + calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + measurements.maxPeriod(Measurements::Humidity, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + } +} + +int calculateMaxPeriod(int updateInterval) { + // 0.5 is 50% reduced interval for max period + return (SERVER_SYNC_INTERVAL - (SERVER_SYNC_INTERVAL * 0.5)) / updateInterval; +} \ No newline at end of file diff --git a/examples/DiyProIndoorV4_2/LocalServer.cpp b/examples/DiyProIndoorV4_2/LocalServer.cpp index 8970ece..61a6dfb 100644 --- a/examples/DiyProIndoorV4_2/LocalServer.cpp +++ b/examples/DiyProIndoorV4_2/LocalServer.cpp @@ -53,9 +53,8 @@ void LocalServer::_GET_metrics(void) { } void LocalServer::_GET_measure(void) { - server.send( - 200, "application/json", - measure.toString(true, fwMode, wifiConnector.RSSI(), ag, &config)); + String toSend = measure.toString(true, fwMode, wifiConnector.RSSI(), *ag, config); + server.send(200, "application/json", toSend); } void LocalServer::setFwMode(AgFirmwareMode fwMode) { this->fwMode = fwMode; } diff --git a/examples/DiyProIndoorV4_2/OpenMetrics.cpp b/examples/DiyProIndoorV4_2/OpenMetrics.cpp index cffd2c6..ddf2d4c 100644 --- a/examples/DiyProIndoorV4_2/OpenMetrics.cpp +++ b/examples/DiyProIndoorV4_2/OpenMetrics.cpp @@ -73,19 +73,30 @@ String OpenMetrics::getPayload(void) { int pm03PCount = utils::getInvalidPmValue(); int atmpCompensated = utils::getInvalidTemperature(); int ahumCompensated = utils::getInvalidHumidity(); + int tvoc = utils::getInvalidVOC(); + int tvoc_raw = utils::getInvalidVOC(); + int nox = utils::getInvalidNOx(); + int nox_raw = utils::getInvalidNOx(); if (config.hasSensorSHT) { - _temp = measure.Temperature; - _hum = measure.Humidity; + _temp = measure.getFloat(Measurements::Temperature); + _hum = measure.getFloat(Measurements::Humidity); atmpCompensated = _temp; ahumCompensated = _hum; } if (config.hasSensorPMS1) { - pm01 = measure.pm01_1; - pm25 = measure.pm25_1; - pm10 = measure.pm10_1; - pm03PCount = measure.pm03PCount_1; + pm01 = measure.get(Measurements::PM01); + pm25 = measure.get(Measurements::PM25); + pm10 = measure.get(Measurements::PM10); + pm03PCount = measure.get(Measurements::PM03_PC); + } + + if (config.hasSensorSGP) { + tvoc = measure.get(Measurements::TVOC); + tvoc_raw = measure.get(Measurements::TVOCRaw); + nox = measure.get(Measurements::NOx); + nox_raw = measure.get(Measurements::NOxRaw); } if (config.hasSensorPMS1) { @@ -120,33 +131,33 @@ String OpenMetrics::getPayload(void) { } if (config.hasSensorSGP) { - if (utils::isValidVOC(measure.TVOC)) { + if (utils::isValidVOC(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)); + add_metric_point("", String(tvoc)); } - if (utils::isValidVOC(measure.TVOCRaw)) { + if (utils::isValidVOC(tvoc_raw)) { 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)); + add_metric_point("", String(tvoc_raw)); } - if (utils::isValidNOx(measure.NOx)) { + if (utils::isValidNOx(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)); + add_metric_point("", String(nox)); } - if (utils::isValidNOx(measure.NOxRaw)) { + if (utils::isValidNOx(nox_raw)) { add_metric("nox_raw", "The raw input value to the Nitrous Oxide (NOx) index as " "measured by the AirGradient SGP sensor", "gauge"); - add_metric_point("", String(measure.NOxRaw)); + add_metric_point("", String(nox_raw)); } } diff --git a/examples/OneOpenAir/OneOpenAir.ino b/examples/OneOpenAir/OneOpenAir.ino index 4db7022..ee34f76 100644 --- a/examples/OneOpenAir/OneOpenAir.ino +++ b/examples/OneOpenAir/OneOpenAir.ino @@ -89,7 +89,6 @@ static LocalServer localServer(Serial, openMetrics, measurements, configuration, wifiConnector); static uint32_t factoryBtnPressTime = 0; -static int getCO2FailCount = 0; static AgFirmwareMode fwMode = FW_MODE_I_9PSL; static bool ledBarButtonTest = false; @@ -324,14 +323,13 @@ void loop() { static void co2Update(void) { if (!configuration.hasSensorS8) { - // Device don't have SHT sensor + // Device don't have S8 sensor return; } int value = ag->s8.getCo2(); if (utils::isValidCO2(value)) { measurements.update(Measurements::CO2, value); - // Serial.printf("CO2 (ppm): %d\r\n", measurements.CO2); } else { measurements.update(Measurements::CO2, utils::getInvalidCO2()); } @@ -996,12 +994,6 @@ static void updateTvoc(void) { measurements.update(Measurements::TVOCRaw, ag->sgp41.getTvocRaw()); measurements.update(Measurements::NOx, ag->sgp41.getNoxIndex()); measurements.update(Measurements::NOxRaw, ag->sgp41.getNoxRaw()); - - // Serial.println(); - // Serial.printf("TVOC index: %d\r\n", measurements.TVOC); - // Serial.printf("TVOC raw: %d\r\n", measurements.TVOCRaw); - // Serial.printf("NOx index: %d\r\n", measurements.NOx); - // Serial.printf("NOx raw: %d\r\n", measurements.NOxRaw); } static void updatePMS5003() { @@ -1010,13 +1002,6 @@ static void updatePMS5003() { measurements.update(Measurements::PM25, ag->pms5003.getPm25Ae()); measurements.update(Measurements::PM10, ag->pms5003.getPm10Ae()); measurements.update(Measurements::PM03_PC, ag->pms5003.getPm03ParticleCount()); - - // Serial.println(); - // Serial.printf("PM1 ug/m3: %d\r\n", measurements.pm01_1); - // Serial.printf("PM2.5 ug/m3: %d\r\n", measurements.pm25_1); - // Serial.printf("PM10 ug/m3: %d\r\n", measurements.pm10_1); - // Serial.printf("PM0.3 Count: %d\r\n", measurements.pm03PCount_1); - // Serial.printf("PM firmware version: %d\r\n", ag->pms5003.getFirmwareVersion()); } else { measurements.update(Measurements::PM01, utils::getInvalidPmValue()); measurements.update(Measurements::PM25, utils::getInvalidPmValue()); @@ -1133,11 +1118,6 @@ static void tempHumUpdate(void) { measurements.update(Measurements::Temperature, temp); measurements.update(Measurements::Humidity, rhum); - // Serial.printf("Temperature in C: %0.2f\n", temp); - // Serial.printf("Relative Humidity: %d\n", rhum); - // Serial.printf("Temperature compensated in C: %0.2f\n", temp); - // Serial.printf("Relative Humidity compensated: %0.2f\n", rhum); - // Update compensation temperature and humidity for SGP41 if (configuration.hasSensorSGP) { ag->sgp41.setCompensationTemperatureHumidity(temp, rhum); diff --git a/src/AgValue.h b/src/AgValue.h index 236589a..8c26bf2 100644 --- a/src/AgValue.h +++ b/src/AgValue.h @@ -42,14 +42,14 @@ public: Temperature, Humidity, CO2, - TVOC, + TVOC, // index value TVOCRaw, - NOx, + NOx, // index value NOxRaw, PM25, PM01, PM10, - PM03_PC, + PM03_PC, // Particle count }; /** @@ -125,9 +125,9 @@ private: FloatValue _temperature[2]; FloatValue _humidity[2]; IntegerValue _co2; - IntegerValue _tvoc; + IntegerValue _tvoc; // Index value IntegerValue _tvoc_raw; - IntegerValue _nox; + IntegerValue _nox; // Index value IntegerValue _nox_raw; IntegerValue _pm_25[2]; IntegerValue _pm_01[2];