mirror of
https://github.com/airgradienthq/arduino.git
synced 2025-06-28 17:20:57 +02:00
Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
9fb01d42f4 | |||
7bb013939c | |||
0da21155e7 | |||
7a153cc0ea | |||
b079c35e6b | |||
6051e183b8 | |||
c95379b957 | |||
0cae8bc185 | |||
5902a4c8e4 | |||
66818cd075 | |||
c1a6ddc68f | |||
20a32dd22c | |||
263dc9934e | |||
61b863b7f1 | |||
e01c1029fe | |||
ba5d817739 | |||
a91747e379 | |||
029457c3fa | |||
55710dd4d9 | |||
4886163cda | |||
7c57477238 |
@ -93,6 +93,7 @@ Compensated values apply correction algorithms to make the sensor values more ac
|
||||
"tvocLearningOffset": 12,
|
||||
"noxLearningOffset": 12,
|
||||
"mqttBrokerUrl": "",
|
||||
"httpDomain": "",
|
||||
"temperatureUnit": "c",
|
||||
"configurationControl": "local",
|
||||
"postDataToAirGradient": true,
|
||||
@ -146,7 +147,8 @@ If the monitor is set up on the AirGradient dashboard, it will also receive the
|
||||
| `displayBrightness` | Brightness of the Display. | Number | 0-100 | `{"displayBrightness": 50}` |
|
||||
| `ledBarBrightness` | Brightness of the LEDBar. | Number | 0-100 | `{"ledBarBrightness": 40}` |
|
||||
| `abcDays` | Number of days for CO2 automatic baseline calibration. | Number | Maximum 200 days. Default 8 days. | `{"abcDays": 8}` |
|
||||
| `mqttBrokerUrl` | MQTT broker URL. | String | | `{"mqttBrokerUrl": "mqtt://192.168.0.18:1883"}` |
|
||||
| `mqttBrokerUrl` | MQTT broker URL. | String | Maximum 255 characters. Set value to empty string to disable mqtt connection. | `{"mqttBrokerUrl": "mqtt://192.168.0.18:1883"}` |
|
||||
| `httpDomain` | Domain name for http request. (version > 3.3.2) | String | Maximum 255 characters. Set value to empty string to set http domain to default airgradient | `{"httpDomain": "sub.domain.com"}` |
|
||||
| `temperatureUnit` | Temperature unit shown on the display. | String | `c` or `C`: Degree Celsius °C <br>`f` or `F`: Degree Fahrenheit °F | `{"temperatureUnit": "c"}` |
|
||||
| `configurationControl` | The configuration source of the device. | String | `both`: Accept local and cloud configuration <br>`local`: Accept only local configuration <br>`cloud`: Accept only cloud configuration | `{"configurationControl": "both"}` |
|
||||
| `postDataToAirGradient` | Send data to AirGradient cloud. | Boolean | `true`: Enabled <br>`false`: Disabled | `{"postDataToAirGradient": true}` |
|
||||
@ -154,8 +156,8 @@ If the monitor is set up on the AirGradient dashboard, it will also receive the
|
||||
| `ledBarTestRequested` | Can be set to trigger a test. | Boolean | `true` : LEDs will run test sequence | `{"ledBarTestRequested": true}` |
|
||||
| `noxLearningOffset` | Set NOx learning gain offset. | Number | 0-720 (default 12) | `{"noxLearningOffset": 12}` |
|
||||
| `tvocLearningOffset` | Set VOC learning gain offset. | Number | 0-720 (default 12) | `{"tvocLearningOffset": 12}` |
|
||||
| `monitorDisplayCompensatedValues` | Set the display show the PM value with/without compensate value (only on [3.1.9]()) | Boolean | `false`: Without compensate (default) <br> `true`: with compensate | `{"monitorDisplayCompensatedValues": false }` |
|
||||
| `corrections` | Sets correction options to display and measurement values on local server response. (version >= [3.1.11]()) | Object | _see corrections section_ | _see corrections section_ |
|
||||
| `monitorDisplayCompensatedValues` | Set the display show the PM value with/without compensate value (only on 3.1.9) | Boolean | `false`: Without compensate (default) <br> `true`: with compensate | `{"monitorDisplayCompensatedValues": false }` |
|
||||
| `corrections` | Sets correction options to display and measurement values on local server response. (version >= 3.1.11) | Object | _see corrections section_ | _see corrections section_ |
|
||||
|
||||
|
||||
**Notes**
|
||||
|
@ -117,6 +117,7 @@ static uint32_t factoryBtnPressTime = 0;
|
||||
static AgFirmwareMode fwMode = FW_MODE_I_9PSL;
|
||||
static bool ledBarButtonTest = false;
|
||||
static String fwNewVersion;
|
||||
static int lastCellSignalQuality = 99; // CSQ
|
||||
|
||||
SemaphoreHandle_t mutexMeasurementCycleQueue;
|
||||
static std::vector<Measurements::Measures> measurementCycleQueue;
|
||||
@ -813,8 +814,6 @@ static void openAirInit(void) {
|
||||
Serial.println("CO2 S8 sensor not found");
|
||||
Serial.println("Can not detect S8 run mode 'PPT'");
|
||||
fwMode = FW_MODE_O_1PPT;
|
||||
|
||||
Serial0.end();
|
||||
delay(200);
|
||||
} else {
|
||||
Serial.println("Found S8 on Serial0");
|
||||
@ -944,6 +943,14 @@ void initializeNetwork() {
|
||||
agSerial->setDebug(true);
|
||||
}
|
||||
|
||||
String httpDomain = configuration.getHttpDomain();
|
||||
if (httpDomain != "") {
|
||||
agClient->setHttpDomain(httpDomain.c_str());
|
||||
Serial.printf("HTTP domain name is set to: %s\n", httpDomain.c_str());
|
||||
oledDisplay.setText("HTTP domain name", "using local", "configuration");
|
||||
delay(2500);
|
||||
}
|
||||
|
||||
if (!agClient->begin(ag->deviceId().c_str())) {
|
||||
oledDisplay.setText("Client", "initialization", "failed");
|
||||
delay(5000);
|
||||
@ -1041,6 +1048,16 @@ static void configUpdateHandle() {
|
||||
initMqtt();
|
||||
}
|
||||
|
||||
String httpDomain = configuration.getHttpDomain();
|
||||
if (httpDomain != "") {
|
||||
Serial.printf("HTTP domain name set to: %s\n", httpDomain.c_str());
|
||||
agClient->setHttpDomain(httpDomain.c_str());
|
||||
} else {
|
||||
// Its empty, set to default
|
||||
Serial.println("HTTP domain name from configuration empty, set to default");
|
||||
agClient->setHttpDomainDefault();
|
||||
}
|
||||
|
||||
if (configuration.hasSensorSGP) {
|
||||
if (configuration.noxLearnOffsetChanged() ||
|
||||
configuration.tvocLearnOffsetChanged()) {
|
||||
@ -1447,12 +1464,8 @@ void setMeasurementMaxPeriod() {
|
||||
|
||||
int calculateMaxPeriod(int updateInterval) {
|
||||
// 0.8 is 80% reduced interval for max period
|
||||
if (networkOption == UseWifi) {
|
||||
return (WIFI_MEASUREMENT_INTERVAL - (WIFI_MEASUREMENT_INTERVAL * 0.8)) / updateInterval;
|
||||
} else {
|
||||
// Cellular
|
||||
return (CELLULAR_MEASUREMENT_INTERVAL - (CELLULAR_MEASUREMENT_INTERVAL * 0.8)) / updateInterval;
|
||||
}
|
||||
// NOTE: Both network option use the same measurement interval
|
||||
return (WIFI_MEASUREMENT_INTERVAL - (WIFI_MEASUREMENT_INTERVAL * 0.8)) / updateInterval;
|
||||
}
|
||||
|
||||
|
||||
@ -1463,14 +1476,20 @@ void networkSignalCheck() {
|
||||
auto result = cell->retrieveSignal();
|
||||
if (result.status != CellReturnStatus::Ok) {
|
||||
agClient->setClientReady(false);
|
||||
lastCellSignalQuality = 99;
|
||||
return;
|
||||
}
|
||||
|
||||
// Save last signal quality
|
||||
lastCellSignalQuality = result.data;
|
||||
|
||||
if (result.data == 99) {
|
||||
// 99 indicate cellular not attached to network
|
||||
agClient->setClientReady(false);
|
||||
return;
|
||||
}
|
||||
Serial.printf("Cellular signal strength %d\n", result.data);
|
||||
|
||||
Serial.printf("Cellular signal quality %d\n", result.data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1489,6 +1508,7 @@ void networkingTask(void *args) {
|
||||
if (networkOption == UseCellular) {
|
||||
Serial.println("Prepare first measures cycle to send on boot for 20s");
|
||||
delay(20000);
|
||||
networkSignalCheck();
|
||||
newMeasurementCycle();
|
||||
sendDataToServer();
|
||||
measurementSchedule.update();
|
||||
@ -1546,7 +1566,10 @@ void newMeasurementCycle() {
|
||||
measurementCycleQueue.erase(measurementCycleQueue.begin());
|
||||
}
|
||||
|
||||
// Get current measures
|
||||
auto mc = measurements.getMeasures();
|
||||
mc.signal = cell->csqToDbm(lastCellSignalQuality); // convert to RSSI
|
||||
|
||||
measurementCycleQueue.push_back(mc);
|
||||
Serial.println("New measurement cycle added to queue");
|
||||
// Release mutex
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=AirGradient Air Quality Sensor
|
||||
version=3.3.2
|
||||
version=3.3.4
|
||||
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.
|
||||
|
@ -12,7 +12,7 @@
|
||||
platform = espressif32
|
||||
board = esp32-c3-devkitm-1
|
||||
framework = arduino
|
||||
build_flags = !echo '-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 -D CORE_DEBUG_LEVEL=3 -D GIT_VERSION=\\"'$(git describe --tags --always --dirty)'\\"'
|
||||
build_flags = !echo '-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 -D AG_LOG_LEVEL=AG_LOG_LEVEL_INFO -D GIT_VERSION=\\"'$(git describe --tags --always --dirty)'\\"'
|
||||
board_build.partitions = partitions.csv
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
|
@ -46,6 +46,7 @@ JSON_PROP_DEF(abcDays);
|
||||
JSON_PROP_DEF(tvocLearningOffset);
|
||||
JSON_PROP_DEF(noxLearningOffset);
|
||||
JSON_PROP_DEF(mqttBrokerUrl);
|
||||
JSON_PROP_DEF(httpDomain);
|
||||
JSON_PROP_DEF(temperatureUnit);
|
||||
JSON_PROP_DEF(configurationControl);
|
||||
JSON_PROP_DEF(postDataToAirGradient);
|
||||
@ -68,6 +69,7 @@ JSON_PROP_DEF(rhum);
|
||||
#define jprop_tvocLearningOffset_default 12
|
||||
#define jprop_noxLearningOffset_default 12
|
||||
#define jprop_mqttBrokerUrl_default ""
|
||||
#define jprop_httpDomain_default ""
|
||||
#define jprop_temperatureUnit_default "c"
|
||||
#define jprop_configurationControl_default String(CONFIGURATION_CONTROL_NAME[ConfigurationControl::ConfigurationControlBoth])
|
||||
#define jprop_postDataToAirGradient_default true
|
||||
@ -377,6 +379,7 @@ void Configuration::defaultConfig(void) {
|
||||
|
||||
jconfig[jprop_country] = jprop_country_default;
|
||||
jconfig[jprop_mqttBrokerUrl] = jprop_mqttBrokerUrl_default;
|
||||
jconfig[jprop_httpDomain] = jprop_httpDomain_default;
|
||||
jconfig[jprop_configurationControl] = jprop_configurationControl_default;
|
||||
jconfig[jprop_pmStandard] = jprop_pmStandard_default;
|
||||
jconfig[jprop_temperatureUnit] = jprop_temperatureUnit_default;
|
||||
@ -735,7 +738,7 @@ bool Configuration::parse(String data, bool isLocal) {
|
||||
jconfig[jprop_mqttBrokerUrl] = broker;
|
||||
}
|
||||
} else {
|
||||
failedMessage = "\"mqttBrokerUrl\" length should <= 255";
|
||||
failedMessage = "\"mqttBrokerUrl\" length should less than 255 character";
|
||||
jsonInvalid();
|
||||
return false;
|
||||
}
|
||||
@ -754,6 +757,32 @@ bool Configuration::parse(String data, bool isLocal) {
|
||||
}
|
||||
}
|
||||
|
||||
if (isLocal) {
|
||||
if (JSON.typeof_(root[jprop_httpDomain]) == "string") {
|
||||
String httpDomain = root[jprop_httpDomain];
|
||||
String oldHttpDomain = jconfig[jprop_httpDomain];
|
||||
if (httpDomain.length() <= 255) {
|
||||
if (httpDomain != oldHttpDomain) {
|
||||
changed = true;
|
||||
configLogInfo(String(jprop_httpDomain), oldHttpDomain, httpDomain);
|
||||
jconfig[jprop_httpDomain] = httpDomain;
|
||||
}
|
||||
} else {
|
||||
failedMessage = "\"httpDomain\" length should less than 255 character";
|
||||
jsonInvalid();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (jsonTypeInvalid(root[jprop_httpDomain], "string")) {
|
||||
failedMessage =
|
||||
jsonTypeInvalidMessage(String(jprop_httpDomain), "string");
|
||||
jsonInvalid();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (JSON.typeof_(root[jprop_temperatureUnit]) == "string") {
|
||||
String unit = root[jprop_temperatureUnit];
|
||||
String oldUnit = jconfig[jprop_temperatureUnit];
|
||||
@ -1036,6 +1065,16 @@ String Configuration::getMqttBrokerUri(void) {
|
||||
return broker;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get HTTP domain for post measures and get configuration
|
||||
*
|
||||
* @return String http domain, might be empty string
|
||||
*/
|
||||
String Configuration::getHttpDomain(void) {
|
||||
String httpDomain = jconfig[jprop_httpDomain];
|
||||
return httpDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get configuratoin post data to AirGradient cloud
|
||||
*
|
||||
@ -1121,7 +1160,7 @@ bool Configuration::isUpdated(void) {
|
||||
}
|
||||
|
||||
String Configuration::jsonTypeInvalidMessage(String name, String type) {
|
||||
return "'" + name + "' type invalid, it's should '" + type + "'";
|
||||
return "'" + name + "' type is invalid, expecting '" + type + "'";
|
||||
}
|
||||
|
||||
String Configuration::jsonValueInvalidMessage(String name, String value) {
|
||||
@ -1275,6 +1314,18 @@ void Configuration::toConfig(const char *buf) {
|
||||
logInfo("toConfig: mqttBroker changed");
|
||||
}
|
||||
|
||||
/** validate http domain */
|
||||
if (JSON.typeof_(jconfig[jprop_httpDomain]) != "string") {
|
||||
isConfigFieldInvalid = true;
|
||||
} else {
|
||||
isConfigFieldInvalid = false;
|
||||
}
|
||||
if (isConfigFieldInvalid) {
|
||||
changed = true;
|
||||
jconfig[jprop_httpDomain] = jprop_httpDomain_default;
|
||||
logInfo("toConfig: httpDomain changed");
|
||||
}
|
||||
|
||||
/** Validate temperature unit */
|
||||
if (JSON.typeof_(jconfig[jprop_temperatureUnit]) != "string") {
|
||||
isConfigFieldInvalid = true;
|
||||
|
@ -82,6 +82,7 @@ public:
|
||||
String getLedBarModeName(void);
|
||||
bool getDisplayMode(void);
|
||||
String getMqttBrokerUri(void);
|
||||
String getHttpDomain(void);
|
||||
bool isPostDataToAirGradient(void);
|
||||
ConfigurationControl getConfigurationControl(void);
|
||||
bool isCo2CalibrationRequested(void);
|
||||
|
@ -827,6 +827,12 @@ std::string Measurements::buildMeasuresPayload(Measures &mc) {
|
||||
oss << std::round(mc.pm_03_pc[1]);
|
||||
}
|
||||
|
||||
oss << ",";
|
||||
|
||||
if (mc.signal < 0) {
|
||||
oss << mc.signal;
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "Main/utils.h"
|
||||
|
||||
#ifndef GIT_VERSION
|
||||
#define GIT_VERSION "3.3.2-snap"
|
||||
#define GIT_VERSION "3.3.4-snap"
|
||||
#endif
|
||||
|
||||
|
||||
|
Submodule src/Libraries/airgradient-client updated: 938a92830d...d24b369604
Submodule src/Libraries/airgradient-ota updated: 24d2dc537c...fde4380164
Reference in New Issue
Block a user