mirror of
https://github.com/airgradienthq/arduino.git
synced 2025-12-17 02:58:44 +01:00
Compare commits
47 Commits
fix/openme
...
3.4.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5802cf17f6 | ||
|
|
4a4ce89f00 | ||
|
|
8985e08a00 | ||
|
|
e984aced18 | ||
|
|
73edf56c97 | ||
|
|
e54c62a2ef | ||
|
|
5c95f011e4 | ||
|
|
bed448e7d6 | ||
|
|
eb8378adfa | ||
|
|
f94ed5c5f5 | ||
|
|
9471f3e323 | ||
|
|
e6d90372c2 | ||
|
|
fabf0550fc | ||
|
|
ce0af5bf60 | ||
|
|
93bdbd85d5 | ||
|
|
29f583f20d | ||
|
|
0f6a2fe908 | ||
|
|
e3ce2c41be | ||
|
|
92b3c69b98 | ||
|
|
f4d518aa87 | ||
|
|
831c844c24 | ||
|
|
060a7f6815 | ||
|
|
d8eb6b3c1a | ||
|
|
77859bea22 | ||
|
|
969858b5cb | ||
|
|
09b5805686 | ||
|
|
b09b753339 | ||
|
|
ddb3dba131 | ||
|
|
e780b0ace6 | ||
|
|
e82da5401e | ||
|
|
50a98acde4 | ||
|
|
7049d21a41 | ||
|
|
d5cdeaa9f3 | ||
|
|
09207c6923 | ||
|
|
0a64424196 | ||
|
|
5b38ca222b | ||
|
|
9ee35341a5 | ||
|
|
cec0514444 | ||
|
|
21b9ddb2ed | ||
|
|
1ee05da5d1 | ||
|
|
626a2240fa | ||
|
|
174ec6568f | ||
|
|
6b55719399 | ||
|
|
e2084f0738 | ||
|
|
5e07923690 | ||
|
|
04049439b1 | ||
|
|
c148d256d7 |
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,6 +1,6 @@
|
||||
[submodule "src/Libraries/airgradient-client"]
|
||||
path = src/Libraries/airgradient-client
|
||||
url = git@github.com:airgradienthq/airgradient-client.git
|
||||
url = ../../airgradienthq/airgradient-client.git
|
||||
[submodule "src/Libraries/airgradient-ota"]
|
||||
path = src/Libraries/airgradient-ota
|
||||
url = git@github.com:airgradienthq/airgradient-ota.git
|
||||
url = ../../airgradienthq/airgradient-ota.git
|
||||
|
||||
23
README.md
23
README.md
@@ -20,13 +20,32 @@ Make sure you have exactly the versions of libraries and boards installed as des
|
||||
|
||||
If you have an older version of the AirGradient PCB not mentioned in the example files, please downgrade this library to version 2.4.15 to support these legacy boards.
|
||||
|
||||
### Release Process
|
||||
|
||||
Releases published on GitHub are **not immediately deployed to all devices in the market**. Each release first goes through internal testing, including limited deployments in select locations to verify stability and functionality.
|
||||
|
||||
If the tests pass, the firmware is then made available for:
|
||||
- **FOTA (Firmware Over-The-Air) updates** from AirGradient dashboard
|
||||
- **Manual flashing** via [Airgradient](https://www.airgradient.com/documentation/firmwares/) website
|
||||
|
||||
Each GitHub release note will also include the planned rollout date for wider availability.
|
||||
|
||||
## Help & Support
|
||||
|
||||
If you have any questions or problems, check out [our forum](https://forum.airgradient.com/).
|
||||
|
||||
## Documentation
|
||||
## Development
|
||||
|
||||
Local server API documentation is available in [/docs/local-server.md](/docs/local-server.md) and AirGradient server API on [https://api.airgradient.com/public/docs/api/v1/](https://api.airgradient.com/public/docs/api/v1/).
|
||||
* See [compilation instructions](/docs/howto-compile.md) for details about how to customize AirGradient's firmware and flash it to your device.
|
||||
|
||||
## Over the air (OTA) updates
|
||||
|
||||
* See the [OTA Updates documentation](/docs/ota-updates.md) for details about how AirGradient monitors receive over the air updates.
|
||||
|
||||
## API documentation
|
||||
|
||||
* [Local server API documentation](/docs/local-server.md)
|
||||
* [AirGradient Cloud server API documentation](https://api.airgradient.com/public/docs/api/v1/).
|
||||
|
||||
## The following libraries have been integrated into this library for ease of use
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ Choose based on how python installed on your machine. But most user, using `apt`
|
||||
|
||||
## How to contribute
|
||||
|
||||
The instructions above are the instructions for how to build an official release of the AirGradient firmware using the Arduino IDE. If you intend to make changes that will you intent to contribute back to the main project, instead of installing the AirGradient library, check out the repo at `Documents/Arduino/libraries` (for Windows and Mac), or `~/Arduino/Libraries` (Linux). If you installed the library, you can remove it from the library manager in the Arduino IDE, or just delete the directory.
|
||||
The instructions above are the instructions for how to build an official release of the AirGradient firmware using the Arduino IDE. If you intend to make changes which you plan to contribute back to the main project, instead of installing the AirGradient library, check out the repository at Documents/Arduino/libraries (for Windows and Mac) or ~/Arduino/libraries (for Linux). If you installed the library, you can remove it from the library manager in the Arduino IDE, or just delete the directory.
|
||||
|
||||
**NOTE:** When cloning the repository, for version >= 3.3.0 it has submodule, please use `--recursive` flag like this: `git clone --recursive https://github.com/airgradienthq/arduino.git AirGradient_Air_Quality_Sensor`
|
||||
|
||||
@@ -100,6 +100,3 @@ There are 2 environment options to compile this project, PlatformIO and ArduinoI
|
||||
|
||||
- For PlatformIO, it should work out of the box
|
||||
- For arduino, files in `src` folder and also from `Examples` can be modified at `Documents/Arduino/libraries` for Windows and Mac, and `~/Arduino/Libraries` for Linux
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -106,7 +106,6 @@ Compensated values apply correction algorithms to make the sensor values more ac
|
||||
"pm02": {
|
||||
"correctionAlgorithm": "epa_2021",
|
||||
"slr": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +143,7 @@ static void updatePm(void);
|
||||
static void sendDataToServer(void);
|
||||
static void tempHumUpdate(void);
|
||||
static void co2Update(void);
|
||||
static void printMeasurements();
|
||||
static void mdnsInit(void);
|
||||
static void createMqttTask(void);
|
||||
static void initMqtt(void);
|
||||
@@ -172,6 +173,7 @@ AgSchedule tvocSchedule(SENSOR_TVOC_UPDATE_INTERVAL, updateTvoc);
|
||||
AgSchedule watchdogFeedSchedule(60000, wdgFeedUpdate);
|
||||
AgSchedule checkForUpdateSchedule(FIRMWARE_CHECK_FOR_UPDATE_MS, checkForFirmwareUpdate);
|
||||
AgSchedule networkSignalCheckSchedule(10000, networkSignalCheck);
|
||||
AgSchedule printMeasurementsSchedule(6000, printMeasurements);
|
||||
|
||||
void setup() {
|
||||
/** Serial for print debug message */
|
||||
@@ -191,6 +193,7 @@ void setup() {
|
||||
|
||||
/** Initialize local configure */
|
||||
configuration.begin();
|
||||
configuration.setConfigurationUpdatedCallback(configUpdateHandle);
|
||||
|
||||
/** Init I2C */
|
||||
Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
|
||||
@@ -218,9 +221,6 @@ void setup() {
|
||||
boardInit();
|
||||
setMeasurementMaxPeriod();
|
||||
|
||||
// Comment below line to disable debug measurement readings
|
||||
measurements.setDebug(true);
|
||||
|
||||
bool connectToNetwork = true;
|
||||
if (ag->isOne()) { // Offline mode only available for indoor monitor
|
||||
/** Show message confirm offline mode, should me perform if LED bar button
|
||||
@@ -271,6 +271,7 @@ void setup() {
|
||||
|
||||
Serial.println("Display brightness: " + String(configuration.getDisplayBrightness()));
|
||||
oledDisplay.setBrightness(configuration.getDisplayBrightness());
|
||||
delay(DISPLAY_DELAY_SHOW_CONTENT_MS);
|
||||
}
|
||||
|
||||
|
||||
@@ -364,11 +365,17 @@ void loop() {
|
||||
}
|
||||
}
|
||||
|
||||
/* Run measurement schedule */
|
||||
printMeasurementsSchedule.run();
|
||||
|
||||
/** factory reset handle */
|
||||
factoryConfigReset();
|
||||
|
||||
/** check that local configuration changed then do some action */
|
||||
configUpdateHandle();
|
||||
if (configuration.isCommandRequested()) {
|
||||
// Each state machine already has an independent request command check
|
||||
stateMachine.executeCo2Calibration();
|
||||
stateMachine.executeLedBarTest();
|
||||
}
|
||||
}
|
||||
|
||||
static void co2Update(void) {
|
||||
@@ -385,6 +392,10 @@ static void co2Update(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void printMeasurements() {
|
||||
measurements.printCurrentAverage();
|
||||
}
|
||||
|
||||
static void mdnsInit(void) {
|
||||
if (!MDNS.begin(localServer.getHostname().c_str())) {
|
||||
Serial.println("Init mDNS failed");
|
||||
@@ -555,11 +566,16 @@ static bool sgp41Init(void) {
|
||||
}
|
||||
|
||||
void checkForFirmwareUpdate(void) {
|
||||
if (configuration.isCloudConnectionDisabled()) {
|
||||
Serial.println("Cloud connection is disabled, skip firmware update");
|
||||
return;
|
||||
}
|
||||
|
||||
AirgradientOTA *agOta;
|
||||
if (networkOption == UseWifi) {
|
||||
agOta = new AirgradientOTAWifi;
|
||||
} else {
|
||||
agOta = new AirgradientOTACellular(cellularCard);
|
||||
agOta = new AirgradientOTACellular(cellularCard, agClient->getICCID());
|
||||
}
|
||||
|
||||
// Indicate main task that firmware update is in progress
|
||||
@@ -1027,10 +1043,17 @@ void initializeNetwork() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send data for the first time to AG server at boot
|
||||
sendDataToAg();
|
||||
// Send data for the first time to AG server at boot only if postDataToAirgradient is enabled
|
||||
if (configuration.isPostDataToAirGradient()) {
|
||||
sendDataToAg();
|
||||
}
|
||||
}
|
||||
|
||||
// Skip fetch configuration if configuration control is set to "local" only
|
||||
if (configuration.getConfigurationControl() == ConfigurationControl::ConfigurationControlLocal) {
|
||||
ledBarEnabledUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string config = agClient->httpFetchConfig();
|
||||
configSchedule.update();
|
||||
@@ -1062,8 +1085,8 @@ static void configurationUpdateSchedule(void) {
|
||||
}
|
||||
|
||||
std::string config = agClient->httpFetchConfig();
|
||||
if (agClient->isLastFetchConfigSucceed() && configuration.parse(config.c_str(), false)) {
|
||||
configUpdateHandle();
|
||||
if (agClient->isLastFetchConfigSucceed()) {
|
||||
configuration.parse(config.c_str(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1072,8 +1095,6 @@ static void configUpdateHandle() {
|
||||
return;
|
||||
}
|
||||
|
||||
stateMachine.executeCo2Calibration();
|
||||
|
||||
String mqttUri = configuration.getMqttBrokerUri();
|
||||
if (mqttClient.isCurrentUri(mqttUri) == false) {
|
||||
mqttClient.end();
|
||||
@@ -1145,11 +1166,6 @@ static void configUpdateHandle() {
|
||||
if (configuration.isDisplayBrightnessChanged()) {
|
||||
oledDisplay.setBrightness(configuration.getDisplayBrightness());
|
||||
}
|
||||
|
||||
stateMachine.executeLedBarTest();
|
||||
}
|
||||
else if(ag->isOpenAir()) {
|
||||
stateMachine.executeLedBarTest();
|
||||
}
|
||||
|
||||
// Update display and led bar notification based on updated configuration
|
||||
@@ -1417,13 +1433,17 @@ void postUsingCellular(bool forcePost) {
|
||||
|
||||
// Post success, remove the data that previously sent from queue
|
||||
xSemaphoreTake(mutexMeasurementCycleQueue, portMAX_DELAY);
|
||||
measurementCycleQueue.erase(measurementCycleQueue.begin(),
|
||||
measurementCycleQueue.begin() + queueSize);
|
||||
|
||||
if (measurementCycleQueue.capacity() > RESERVED_MEASUREMENT_CYCLE_CAPACITY) {
|
||||
Serial.println("measurementCycleQueue capacity more than reserved space, resizing..");
|
||||
measurementCycleQueue.resize(RESERVED_MEASUREMENT_CYCLE_CAPACITY);
|
||||
std::vector<Measurements::Measures> tmp;
|
||||
tmp.reserve(RESERVED_MEASUREMENT_CYCLE_CAPACITY);
|
||||
measurementCycleQueue.swap(tmp);
|
||||
} else {
|
||||
// If not more than the capacity, then just clear all the values
|
||||
measurementCycleQueue.clear();
|
||||
}
|
||||
|
||||
xSemaphoreGive(mutexMeasurementCycleQueue);
|
||||
}
|
||||
|
||||
@@ -1562,27 +1582,29 @@ void restartIfCeClientIssueOverTwoHours() {
|
||||
}
|
||||
|
||||
void networkingTask(void *args) {
|
||||
// OTA check on boot
|
||||
// If cloud connection enabled, run first transmission to server at boot
|
||||
if (configuration.isCloudConnectionDisabled() == false) {
|
||||
// OTA check on boot
|
||||
#ifndef ESP8266
|
||||
checkForFirmwareUpdate();
|
||||
checkForUpdateSchedule.update();
|
||||
checkForFirmwareUpdate();
|
||||
checkForUpdateSchedule.update();
|
||||
#endif
|
||||
|
||||
// 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);
|
||||
networkSignalCheck();
|
||||
newMeasurementCycle();
|
||||
postUsingCellular(true);
|
||||
measurementSchedule.update();
|
||||
// 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);
|
||||
networkSignalCheck();
|
||||
newMeasurementCycle();
|
||||
postUsingCellular(true);
|
||||
measurementSchedule.update();
|
||||
}
|
||||
// Reset scheduler
|
||||
configSchedule.update();
|
||||
transmissionSchedule.update();
|
||||
}
|
||||
|
||||
// Reset scheduler
|
||||
configSchedule.update();
|
||||
transmissionSchedule.update();
|
||||
|
||||
while (1) {
|
||||
// Handle reconnection based on mode
|
||||
if (networkOption == UseWifi) {
|
||||
@@ -1637,16 +1659,16 @@ void networkingTask(void *args) {
|
||||
// If connection to AirGradient server disable don't run config and transmission schedule
|
||||
if (configuration.isCloudConnectionDisabled()) {
|
||||
delay(1000);
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Run scheduler
|
||||
networkSignalCheckSchedule.run();
|
||||
configSchedule.run();
|
||||
transmissionSchedule.run();
|
||||
configSchedule.run();
|
||||
checkForUpdateSchedule.run();
|
||||
|
||||
delay(1000);
|
||||
delay(50);
|
||||
}
|
||||
|
||||
vTaskDelete(handleNetworkTask);
|
||||
|
||||
@@ -202,14 +202,14 @@ String OpenMetrics::getPayload(void) {
|
||||
}
|
||||
if (utils::isValidNOx(nox)) {
|
||||
add_metric("nox_index",
|
||||
"The processed Nitrous Oxide (NOx) index as measured by the "
|
||||
"The processed Nitrogen Oxide (NOx) index as measured by the "
|
||||
"AirGradient SGP sensor",
|
||||
"gauge");
|
||||
add_metric_point("", String(nox));
|
||||
}
|
||||
if (utils::isValidNOx(noxRaw)) {
|
||||
add_metric("nox_raw",
|
||||
"The raw input value to the Nitrous Oxide (NOx) index as "
|
||||
"The raw input value to the Nitrogen Oxide (NOx) index as "
|
||||
"measured by the AirGradient SGP sensor",
|
||||
"gauge");
|
||||
add_metric_point("", String(noxRaw));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name=AirGradient Air Quality Sensor
|
||||
version=3.3.6
|
||||
version=3.3.9
|
||||
author=AirGradient <support@airgradient.com>
|
||||
maintainer=AirGradient <support@airgradient.com>
|
||||
sentence=ESP32-C3 / ESP8266 library for air quality monitor measuring PM, CO2, Temperature, TVOC and Humidity with OLED display.
|
||||
|
||||
@@ -456,6 +456,10 @@ bool Configuration::begin(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Configuration::setConfigurationUpdatedCallback(ConfigurationUpdatedCallback_t callback) {
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse JSON configura string to local configure
|
||||
*
|
||||
@@ -951,15 +955,18 @@ bool Configuration::parse(String data, bool isLocal) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (ledBarTestRequested || co2CalibrationRequested) {
|
||||
commandRequested = true;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
updated = true;
|
||||
saveConfig();
|
||||
printConfig();
|
||||
} else {
|
||||
if (ledBarTestRequested || co2CalibrationRequested) {
|
||||
updated = true;
|
||||
}
|
||||
_callback();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1159,6 +1166,12 @@ bool Configuration::isUpdated(void) {
|
||||
return updated;
|
||||
}
|
||||
|
||||
bool Configuration::isCommandRequested(void) {
|
||||
bool oldState = this->commandRequested;
|
||||
this->commandRequested = false;
|
||||
return oldState;
|
||||
}
|
||||
|
||||
String Configuration::jsonTypeInvalidMessage(String name, String type) {
|
||||
return "'" + name + "' type is invalid, expecting '" + type + "'";
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ private:
|
||||
bool co2CalibrationRequested;
|
||||
bool ledBarTestRequested;
|
||||
bool updated;
|
||||
bool commandRequested = false;
|
||||
String failedMessage;
|
||||
bool _noxLearnOffsetChanged;
|
||||
bool _tvocLearningOffsetChanged;
|
||||
@@ -70,6 +71,9 @@ public:
|
||||
bool hasSensorSGP = true;
|
||||
bool hasSensorSHT = true;
|
||||
|
||||
typedef void (*ConfigurationUpdatedCallback_t)();
|
||||
void setConfigurationUpdatedCallback(ConfigurationUpdatedCallback_t callback);
|
||||
|
||||
bool begin(void);
|
||||
bool parse(String data, bool isLocal);
|
||||
String toString(void);
|
||||
@@ -90,6 +94,7 @@ public:
|
||||
void reset(void);
|
||||
String getModel(void);
|
||||
bool isUpdated(void);
|
||||
bool isCommandRequested(void);
|
||||
String getFailedMesage(void);
|
||||
void setPostToAirGradient(bool enable);
|
||||
bool noxLearnOffsetChanged(void);
|
||||
@@ -116,6 +121,8 @@ public:
|
||||
PMCorrection getPMCorrection(void);
|
||||
TempHumCorrection getTempCorrection(void);
|
||||
TempHumCorrection getHumCorrection(void);
|
||||
private:
|
||||
ConfigurationUpdatedCallback_t _callback;
|
||||
};
|
||||
|
||||
#endif /** _AG_CONFIG_H_ */
|
||||
|
||||
@@ -8,8 +8,8 @@ AgSchedule::~AgSchedule() {}
|
||||
void AgSchedule::run(void) {
|
||||
uint32_t ms = (uint32_t)(millis() - count);
|
||||
if (ms >= period) {
|
||||
handler();
|
||||
count = millis();
|
||||
handler();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
#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 /** Orange */
|
||||
#define RGB_COLOR_Y 255, 255, 0 /** Yellow */
|
||||
#define RGB_COLOR_O 255, 128, 0 /** Orange */
|
||||
#define RGB_COLOR_P 180, 0, 255 /** Purple */
|
||||
#define RGB_COLOR_CLEAR 0, 0, 0 /** No color */
|
||||
|
||||
|
||||
157
src/AgValue.cpp
157
src/AgValue.cpp
@@ -5,7 +5,7 @@
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
||||
#define json_prop_pmFirmware "firmware"
|
||||
#define json_prop_pmFirmware "firmware"
|
||||
#define json_prop_pm01Ae "pm01"
|
||||
#define json_prop_pm25Ae "pm02"
|
||||
#define json_prop_pm10Ae "pm10"
|
||||
@@ -33,7 +33,7 @@ Measurements::Measurements(Configuration &config) : config(config) {
|
||||
#ifndef ESP8266
|
||||
_resetReason = (int)ESP_RST_UNKNOWN;
|
||||
#endif
|
||||
|
||||
|
||||
/* Set invalid value for each measurements as default value when initialized*/
|
||||
_temperature[0].update.avg = utils::getInvalidTemperature();
|
||||
_temperature[1].update.avg = utils::getInvalidTemperature();
|
||||
@@ -51,7 +51,7 @@ Measurements::Measurements(Configuration &config) : config(config) {
|
||||
_pm_05_pc[1].update.avg = utils::getInvalidPmValue();
|
||||
_pm_5_pc[0].update.avg = utils::getInvalidPmValue();
|
||||
_pm_5_pc[1].update.avg = utils::getInvalidPmValue();
|
||||
|
||||
|
||||
_pm_01[0].update.avg = utils::getInvalidPmValue();
|
||||
_pm_01_sp[0].update.avg = utils::getInvalidPmValue();
|
||||
_pm_01_pc[0].update.avg = utils::getInvalidPmValue();
|
||||
@@ -76,6 +76,86 @@ Measurements::Measurements(Configuration &config) : config(config) {
|
||||
|
||||
void Measurements::setAirGradient(AirGradient *ag) { this->ag = ag; }
|
||||
|
||||
void Measurements::printCurrentAverage() {
|
||||
Serial.println();
|
||||
if (config.hasSensorS8) {
|
||||
if (utils::isValidCO2(_co2.update.avg)) {
|
||||
Serial.printf("CO2 = %.2f ppm\n", _co2.update.avg);
|
||||
} else {
|
||||
Serial.printf("CO2 = -\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (config.hasSensorSHT) {
|
||||
if (utils::isValidTemperature(_temperature[0].update.avg)) {
|
||||
Serial.printf("Temperature = %.2f C\n", _temperature[0].update.avg);
|
||||
} else {
|
||||
Serial.printf("Temperature = -\n");
|
||||
}
|
||||
if (utils::isValidHumidity(_humidity[0].update.avg)) {
|
||||
Serial.printf("Relative Humidity = %.2f\n", _humidity[0].update.avg);
|
||||
} else {
|
||||
Serial.printf("Relative Humidity = -\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (config.hasSensorSGP) {
|
||||
if (utils::isValidVOC(_tvoc.update.avg)) {
|
||||
Serial.printf("TVOC Index = %.1f\n", _tvoc.update.avg);
|
||||
} else {
|
||||
Serial.printf("TVOC Index = -\n");
|
||||
}
|
||||
if (utils::isValidVOC(_tvoc_raw.update.avg)) {
|
||||
Serial.printf("TVOC Raw = %.1f\n", _tvoc_raw.update.avg);
|
||||
} else {
|
||||
Serial.printf("TVOC Raw = -\n");
|
||||
}
|
||||
if (utils::isValidNOx(_nox.update.avg)) {
|
||||
Serial.printf("NOx Index = %.1f\n", _nox.update.avg);
|
||||
} else {
|
||||
Serial.printf("NOx Index = -\n");
|
||||
}
|
||||
if (utils::isValidNOx(_nox_raw.update.avg)) {
|
||||
Serial.printf("NOx Raw = %.1f\n", _nox_raw.update.avg);
|
||||
} else {
|
||||
Serial.printf("NOx Raw = -\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (config.hasSensorPMS1) {
|
||||
printCurrentPMAverage(1);
|
||||
if (!config.hasSensorSHT) {
|
||||
if (utils::isValidTemperature(_temperature[0].update.avg)) {
|
||||
Serial.printf("[1] Temperature = %.2f C\n", _temperature[0].update.avg);
|
||||
} else {
|
||||
Serial.printf("[1] Temperature = -\n");
|
||||
}
|
||||
if (utils::isValidHumidity(_humidity[0].update.avg)) {
|
||||
Serial.printf("[1] Relative Humidity = %.2f\n", _humidity[0].update.avg);
|
||||
} else {
|
||||
Serial.printf("[1] Relative Humidity = -\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (config.hasSensorPMS2) {
|
||||
printCurrentPMAverage(2);
|
||||
if (!config.hasSensorSHT) {
|
||||
if (utils::isValidTemperature(_temperature[1].update.avg)) {
|
||||
Serial.printf("[2] Temperature = %.2f C\n", _temperature[1].update.avg);
|
||||
} else {
|
||||
Serial.printf("[2] Temperature = -\n");
|
||||
}
|
||||
if (utils::isValidHumidity(_humidity[1].update.avg)) {
|
||||
Serial.printf("[2] Relative Humidity = %.2f\n", _humidity[1].update.avg);
|
||||
} else {
|
||||
Serial.printf("[2] Relative Humidity = -\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void Measurements::maxPeriod(MeasurementType type, int max) {
|
||||
switch (type) {
|
||||
case Temperature:
|
||||
@@ -570,6 +650,77 @@ String Measurements::measurementTypeStr(MeasurementType type) {
|
||||
return str;
|
||||
}
|
||||
|
||||
void Measurements::printCurrentPMAverage(int ch) {
|
||||
int idx = ch - 1;
|
||||
|
||||
if (utils::isValidPm(_pm_01[idx].update.avg)) {
|
||||
Serial.printf("[%d] Atmospheric PM 1.0 = %.2f ug/m3\n", ch, _pm_01[idx].update.avg);
|
||||
} else {
|
||||
Serial.printf("[%d] Atmospheric PM 1.0 = -\n", ch);
|
||||
}
|
||||
if (utils::isValidPm(_pm_25[idx].update.avg)) {
|
||||
Serial.printf("[%d] Atmospheric PM 2.5 = %.2f ug/m3\n", ch, _pm_25[idx].update.avg);
|
||||
} else {
|
||||
Serial.printf("[%d] Atmospheric PM 2.5 = -\n", ch);
|
||||
}
|
||||
if (utils::isValidPm(_pm_10[idx].update.avg)) {
|
||||
Serial.printf("[%d] Atmospheric PM 10 = %.2f ug/m3\n", ch, _pm_10[idx].update.avg);
|
||||
} else {
|
||||
Serial.printf("[%d] Atmospheric PM 10 = -\n", ch);
|
||||
}
|
||||
if (utils::isValidPm(_pm_01_sp[idx].update.avg)) {
|
||||
Serial.printf("[%d] Standard Particle PM 1.0 = %.2f ug/m3\n", ch, _pm_01_sp[idx].update.avg);
|
||||
} else {
|
||||
Serial.printf("[%d] Standard Particle PM 1.0 = -\n", ch);
|
||||
}
|
||||
if (utils::isValidPm(_pm_25_sp[idx].update.avg)) {
|
||||
Serial.printf("[%d] Standard Particle PM 2.5 = %.2f ug/m3\n", ch, _pm_25_sp[idx].update.avg);
|
||||
} else {
|
||||
Serial.printf("[%d] Standard Particle PM 2.5 = -\n", ch);
|
||||
}
|
||||
if (utils::isValidPm(_pm_10_sp[idx].update.avg)) {
|
||||
Serial.printf("[%d] Standard Particle PM 10 = %.2f ug/m3\n", ch, _pm_10_sp[idx].update.avg);
|
||||
} else {
|
||||
Serial.printf("[%d] Standard Particle PM 10 = -\n", ch);
|
||||
}
|
||||
if (utils::isValidPm03Count(_pm_03_pc[idx].update.avg)) {
|
||||
Serial.printf("[%d] Particle Count 0.3 = %.1f\n", ch, _pm_03_pc[idx].update.avg);
|
||||
} else {
|
||||
Serial.printf("[%d] Particle Count 0.3 = -\n", ch);
|
||||
}
|
||||
if (utils::isValidPm03Count(_pm_05_pc[idx].update.avg)) {
|
||||
Serial.printf("[%d] Particle Count 0.5 = %.1f\n", ch, _pm_05_pc[idx].update.avg);
|
||||
} else {
|
||||
Serial.printf("[%d] Particle Count 0.5 = -\n", ch);
|
||||
}
|
||||
if (utils::isValidPm03Count(_pm_01_pc[idx].update.avg)) {
|
||||
Serial.printf("[%d] Particle Count 1.0 = %.1f\n", ch, _pm_01_pc[idx].update.avg);
|
||||
} else {
|
||||
Serial.printf("[%d] Particle Count 1.0 = -\n", ch);
|
||||
}
|
||||
if (utils::isValidPm03Count(_pm_25_pc[idx].update.avg)) {
|
||||
Serial.printf("[%d] Particle Count 2.5 = %.1f\n", ch, _pm_25_pc[idx].update.avg);
|
||||
} else {
|
||||
Serial.printf("[%d] Particle Count 2.5 = -\n", ch);
|
||||
}
|
||||
|
||||
if (_pm_5_pc[idx].listValues.empty() == false) {
|
||||
if (utils::isValidPm03Count(_pm_5_pc[idx].update.avg)) {
|
||||
Serial.printf("[%d] Particle Count 5.0 = %.1f\n", ch, _pm_5_pc[idx].update.avg);
|
||||
} else {
|
||||
Serial.printf("[%d] Particle Count 5.0 = -\n", ch);
|
||||
}
|
||||
}
|
||||
|
||||
if (_pm_10_pc[idx].listValues.empty() == false) {
|
||||
if (utils::isValidPm03Count(_pm_10_pc[idx].update.avg)) {
|
||||
Serial.printf("[%d] Particle Count 10 = %.1f\n", ch, _pm_10_pc[idx].update.avg);
|
||||
} else {
|
||||
Serial.printf("[%d] Particle Count 10 = -\n", ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Measurements::validateChannel(int ch) {
|
||||
if (ch != 1 && ch != 2) {
|
||||
Serial.printf("ERROR! Channel %d is undefined. Only channel 1 or 2 is the optional value!", ch);
|
||||
|
||||
@@ -88,6 +88,8 @@ public:
|
||||
PM10_PC, // Particle 10 count
|
||||
};
|
||||
|
||||
void printCurrentAverage();
|
||||
|
||||
/**
|
||||
* @brief Set each MeasurementType maximum period length for moving average
|
||||
*
|
||||
@@ -258,6 +260,8 @@ private:
|
||||
*/
|
||||
void validateChannel(int ch);
|
||||
|
||||
void printCurrentPMAverage(int ch);
|
||||
|
||||
JSONVar buildOutdoor(bool localServer, AgFirmwareMode fwMode);
|
||||
JSONVar buildIndoor(bool localServer);
|
||||
JSONVar buildPMS(int ch, bool allCh, bool withTempHum, bool compensate);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "Main/utils.h"
|
||||
|
||||
#ifndef GIT_VERSION
|
||||
#define GIT_VERSION "3.3.6-snap"
|
||||
#define GIT_VERSION "3.3.9-snap"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Submodule src/Libraries/airgradient-client updated: a4ac14936e...c23bb2ceac
Submodule src/Libraries/airgradient-ota updated: c772392427...7b103e9073
@@ -260,13 +260,14 @@ bool MqttClient::connect(String id) {
|
||||
connected = false;
|
||||
if (user.isEmpty()) {
|
||||
logInfo("Connect without auth");
|
||||
if(CLIENT()->connect(id.c_str())) {
|
||||
connected = true;
|
||||
}
|
||||
return connected;
|
||||
connected = CLIENT()->connect(id.c_str());
|
||||
} else {
|
||||
logInfo("Connect with auth");
|
||||
connected = CLIENT()->connect(id.c_str(), user.c_str(), password.c_str());
|
||||
}
|
||||
return CLIENT()->connect(id.c_str(), user.c_str(), password.c_str());
|
||||
return connected;
|
||||
}
|
||||
|
||||
void MqttClient::handle(void) {
|
||||
if (isBegin == false) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user