diff --git a/examples/OneOpenAir/OneOpenAir.ino b/examples/OneOpenAir/OneOpenAir.ino index 85db0da..3619c75 100644 --- a/examples/OneOpenAir/OneOpenAir.ino +++ b/examples/OneOpenAir/OneOpenAir.ino @@ -38,7 +38,6 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License #include "Arduino.h" #include "EEPROM.h" #include "ESPmDNS.h" -#include "Libraries/airgradient-ota/src/airgradientOta.h" #include "LocalServer.h" #include "MqttClient.h" #include "OpenMetrics.h" @@ -54,6 +53,7 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License #include "Libraries/airgradient-client/src/cellularModuleA7672xx.h" #include "Libraries/airgradient-client/src/airgradientCellularClient.h" #include "Libraries/airgradient-client/src/airgradientWifiClient.h" +#include "Libraries/airgradient-ota/src/airgradientOta.h" #include "Libraries/airgradient-ota/src/airgradientOtaWifi.h" #include "Libraries/airgradient-ota/src/airgradientOtaCellular.h" #include "esp_system.h" @@ -147,6 +147,7 @@ static void displayExecuteOta(AirgradientOTA::OtaResult result, String msg, int static int calculateMaxPeriod(int updateInterval); static void setMeasurementMaxPeriod(); static void newMeasurementCycle(); +static void networkSignalCheck(); static void networkingTask(void *args); AgSchedule dispLedSchedule(DISP_UPDATE_INTERVAL, updateDisplayAndLedBar); @@ -160,6 +161,7 @@ AgSchedule tempHumSchedule(SENSOR_TEMP_HUM_UPDATE_INTERVAL, tempHumUpdate); AgSchedule tvocSchedule(SENSOR_TVOC_UPDATE_INTERVAL, updateTvoc); AgSchedule watchdogFeedSchedule(60000, wdgFeedUpdate); AgSchedule checkForUpdateSchedule(FIRMWARE_CHECK_FOR_UPDATE_MS, checkForFirmwareUpdate); +AgSchedule networkSignalCheckSchedule(10000, networkSignalCheck); void setup() { /** Serial for print debug message */ @@ -575,6 +577,7 @@ void otaHandlerCallback(AirgradientOTA::OtaResult result, const char *msg) { displayExecuteOta(result, fwNewVersion, 0); break; case AirgradientOTA::InProgress: + Serial.printf("OTA progress: %s", msg); displayExecuteOta(result, "", std::stoi(msg)); break; case AirgradientOTA::Failed: @@ -1329,8 +1332,8 @@ void postUsingCellular() { } // Build payload include all measurements from queue - String payload; - payload += String(CELLULAR_MEASUREMENT_INTERVAL / 1000); // Convert to seconds + std::string payload; + payload += std::to_string(CELLULAR_MEASUREMENT_INTERVAL / 1000); // Convert to seconds for (int i = 0; i < queueSize; i++) { auto mc = measurementCycleQueue.at(i); payload += ","; @@ -1341,8 +1344,7 @@ void postUsingCellular() { xSemaphoreGive(mutexMeasurementCycleQueue); // Attempt to send - Serial.println(payload); - if (agClient->httpPostMeasures(payload.c_str()) == false) { + if (agClient->httpPostMeasures(payload) == false) { // Consider network has a problem, retry in next schedule Serial.println("Post measures failed, retry in next schedule"); return; @@ -1364,7 +1366,7 @@ void sendDataToServer(void) { if (networkOption == UseWifi) { postUsingWifi(); - } else { + } else if (networkOption == UseCellular) { postUsingCellular(); } } @@ -1443,6 +1445,20 @@ int calculateMaxPeriod(int updateInterval) { } } + +void networkSignalCheck() { + if (networkOption == UseWifi) { + Serial.printf("WiFi RSSI %d\n", wifiConnector.RSSI()); + } else if (networkOption == UseCellular) { + auto result = cell->retrieveSignal(); + if (result.status != CellReturnStatus::Ok) { + // TODO: Need to do something when get signal failed + return; + } + Serial.printf("Cellular signal strength %d\n", result.data); + } +} + void networkingTask(void *args) { // OTA check on boot #ifdef ESP8266 @@ -1453,7 +1469,15 @@ void networkingTask(void *args) { checkForUpdateSchedule.update(); #endif - // TODO: Need to better define delay value + // Because cellular interval is longer, needs to send first measures cycle on + // boot to indicate that its online + if (networkOption == UseCellular) { + Serial.println("Prepare first measures cycle to send on boot for 20s"); + delay(20000); + newMeasurementCycle(); + sendDataToServer(); + measurementSchedule.update(); + } // Reset scheduler configSchedule.update(); @@ -1489,6 +1513,7 @@ void networkingTask(void *args) { } // Run scheduler + networkSignalCheckSchedule.run(); configSchedule.run(); transmissionSchedule.run(); checkForUpdateSchedule.run(); diff --git a/src/AgValue.cpp b/src/AgValue.cpp index dc3f58f..fd5e5f0 100644 --- a/src/AgValue.cpp +++ b/src/AgValue.cpp @@ -3,6 +3,7 @@ #include "AirGradient.h" #include "App/AppDef.h" #include +#include #define json_prop_pmFirmware "firmware" #define json_prop_pm01Ae "pm01" @@ -733,90 +734,104 @@ Measurements::MeasurementCycle Measurements::getMeasurementCycle() { return mc; } -String Measurements::buildMeasurementPayload(MeasurementCycle &mc) { - String result; - - int co2 = utils::getInvalidCO2(); - float temp = utils::getInvalidTemperature(); - float hum = utils::getInvalidHumidity(); - float pm01 = utils::getInvalidPmValue(); - float pm25 = utils::getInvalidPmValue(); - float pm10 = utils::getInvalidPmValue(); - int nox = utils::getInvalidNOx(); - int pm003Count = utils::getInvalidPmValue(); +std::string Measurements::buildMeasurementPayload(MeasurementCycle &mc) { + std::ostringstream oss; // CO2 if (utils::isValidCO2(mc.co2)) { - co2 = std::round(mc.co2); + oss << std::round(mc.co2); } - // NOx - if (utils::isValidNOx(mc.nox)) { - nox = std::round(mc.nox); - } + oss << ","; - /// Temperature + // Temperature if (utils::isValidTemperature(mc.temperature[0]) && utils::isValidTemperature(mc.temperature[1])) { - temp = ag->round2((mc.temperature[0] + mc.temperature[1]) / 2.0f); + float temp = (mc.temperature[0] + mc.temperature[1]) / 2.0f; + oss << std::round(temp * 10); } else if (utils::isValidTemperature(mc.temperature[0])) { - temp = ag->round2(mc.temperature[0]); + oss << std::round(mc.temperature[0] * 10); } else if (utils::isValidTemperature(mc.temperature[1])) { - temp = ag->round2(mc.temperature[1]); + oss << std::round(mc.temperature[1] * 10); } + oss << ","; + // Humidity if (utils::isValidHumidity(mc.humidity[0]) && utils::isValidHumidity(mc.humidity[1])) { - hum = ag->round2((mc.humidity[0] + mc.humidity[1]) / 2.0f); + float hum = (mc.humidity[0] + mc.humidity[1]) / 2.0f; + oss << std::round(hum * 10); } else if (utils::isValidHumidity(mc.humidity[0])) { - hum = ag->round2(mc.humidity[0]); + oss << std::round(mc.humidity[0] * 10); } else if (utils::isValidHumidity(mc.humidity[1])) { - hum = ag->round2(mc.humidity[1]); + oss << std::round(mc.humidity[1] * 10); } + oss << ","; + /// PM1.0 atmospheric environment if (utils::isValidPm(mc.pm_01[0]) && utils::isValidPm(mc.pm_01[1])) { - pm01 = ag->round2((mc.pm_01[0] + mc.pm_01[1]) / 2.0f); + float pm01 = (mc.pm_01[0] + mc.pm_01[1]) / 2.0f; + oss << std::round(pm01 * 10); } else if (utils::isValidPm(mc.pm_01[0])) { - pm01 = ag->round2(mc.pm_01[0]); + oss << std::round(mc.pm_01[0] * 10); } else if (utils::isValidPm(mc.pm_01[1])) { - pm01 = ag->round2(mc.pm_01[1]); + oss << std::round(mc.pm_01[1] * 10); } + oss << ","; + /// PM2.5 atmospheric environment if (utils::isValidPm(mc.pm_25[0]) && utils::isValidPm(mc.pm_25[1])) { - pm25 = ag->round2((mc.pm_25[0] + mc.pm_25[1]) / 2.0f); + float pm25 = (mc.pm_25[0] + mc.pm_25[1]) / 2.0f; + oss << std::round(pm25 * 10); } else if (utils::isValidPm(mc.pm_25[0])) { - pm25 = ag->round2(mc.pm_25[0]); + oss << std::round(mc.pm_25[0] * 10); } else if (utils::isValidPm(mc.pm_25[1])) { - pm25 = ag->round2(mc.pm_25[1]); + oss << std::round(mc.pm_25[1] * 10); } + oss << ","; + /// PM10 atmospheric environment if (utils::isValidPm(mc.pm_10[0]) && utils::isValidPm(mc.pm_10[1])) { - pm10 = ag->round2((mc.pm_10[0] + mc.pm_10[1]) / 2.0f); + float pm10 = (mc.pm_10[0] + mc.pm_10[1]) / 2.0f; + oss << std::round(pm10 * 10); } else if (utils::isValidPm(mc.pm_10[0])) { - pm10 = ag->round2(mc.pm_10[0]); + oss << std::round(mc.pm_10[0] * 10); } else if (utils::isValidPm(mc.pm_10[1])) { - pm10 = ag->round2(mc.pm_10[1]); + oss << std::round(mc.pm_10[1] * 10); } + oss << ","; + + // NOx + if (utils::isValidNOx(mc.nox)) { + oss << std::round(mc.nox); + } + + oss << ","; + + // TVOC + if (utils::isValidVOC(mc.tvoc)) { + oss << std::round(mc.tvoc); + } + + oss << ","; + /// PM 0.3 particle count if (utils::isValidPm03Count(mc.pm_03_pc[0]) && utils::isValidPm03Count(mc.pm_03_pc[1])) { - pm003Count = std::round((mc.pm_03_pc[0] + mc.pm_03_pc[1]) / 2.0f); + oss << std::round((mc.pm_03_pc[0] + mc.pm_03_pc[1]) / 2.0f); } else if (utils::isValidPm03Count(mc.pm_03_pc[0])) { - pm003Count = std::round(mc.pm_03_pc[0]); + oss << std::round(mc.pm_03_pc[0]); } else if (utils::isValidPm03Count(mc.pm_03_pc[1])) { - pm003Count = std::round(mc.pm_03_pc[1]); + oss << std::round(mc.pm_03_pc[1]); } - char datapoint[128] = {0}; - Serial.printf(datapoint, 128, "%d,%.0f,%.0f,%.0f,%.0f,%.0f,%d,%d\n", co2, - temp * 10, hum * 10, pm01 * 10, pm25 * 10, pm10 * 10, nox, - pm003Count); - snprintf(datapoint, 128, "%d,%.0f,%.0f,%.0f,%.0f,%.0f,%d,%d", co2, temp * 10, - hum * 10, pm01 * 10, pm25 * 10, pm10 * 10, nox, pm003Count); + // char datapoint[128] = {0}; + // snprintf(datapoint, 128, "%d,%.0f,%.0f,%.0f,%.0f,%.0f,%d,%d,%d", co2, temp * 10, + // hum * 10, pm01 * 10, pm25 * 10, pm10 * 10, tvoc, nox, pm003Count); - return String(datapoint); + return oss.str(); } diff --git a/src/AgValue.h b/src/AgValue.h index a0378ab..5edec72 100644 --- a/src/AgValue.h +++ b/src/AgValue.h @@ -182,7 +182,7 @@ public: MeasurementCycle getMeasurementCycle(); - String buildMeasurementPayload(MeasurementCycle &mc); + std::string buildMeasurementPayload(MeasurementCycle &mc); /** * Set to true if want to debug every update value