From 7c57477238bce486002f71dcd2ebab36456ff5ca Mon Sep 17 00:00:00 2001 From: samuelbles07 Date: Wed, 2 Apr 2025 02:12:13 +0700 Subject: [PATCH 1/5] Add local configuration to set http domain change http domain by PUT from local server request --- examples/OneOpenAir/OneOpenAir.ino | 16 +++++++++ src/AgConfigure.cpp | 55 ++++++++++++++++++++++++++++-- src/AgConfigure.h | 1 + src/Libraries/airgradient-client | 2 +- 4 files changed, 71 insertions(+), 3 deletions(-) diff --git a/examples/OneOpenAir/OneOpenAir.ino b/examples/OneOpenAir/OneOpenAir.ino index 0424336..9d98010 100644 --- a/examples/OneOpenAir/OneOpenAir.ino +++ b/examples/OneOpenAir/OneOpenAir.ino @@ -944,6 +944,12 @@ void initializeNetwork() { agSerial->setDebug(true); } + String httpDomain = configuration.getHttpDomain(); + if (httpDomain != "") { + agClient->setHttpDomain(httpDomain.c_str()); + Serial.printf("HTTP request domain set to: %s\n", httpDomain.c_str()); + } + if (!agClient->begin(ag->deviceId().c_str())) { oledDisplay.setText("Client", "initialization", "failed"); delay(5000); @@ -1041,6 +1047,16 @@ static void configUpdateHandle() { initMqtt(); } + String httpDomain = configuration.getHttpDomain(); + if (httpDomain != "") { + Serial.printf("HTTP request domain set to: %s\n", httpDomain.c_str()); + agClient->setHttpDomain(httpDomain.c_str()); + } else { + // Its empty, set to default + Serial.println("HTTP domain from configuration empty, set to default"); + agClient->setHttpDomainDefault(); + } + if (configuration.hasSensorSGP) { if (configuration.noxLearnOffsetChanged() || configuration.tvocLearnOffsetChanged()) { diff --git a/src/AgConfigure.cpp b/src/AgConfigure.cpp index 9f931c0..1f9b87c 100644 --- a/src/AgConfigure.cpp +++ b/src/AgConfigure.cpp @@ -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; diff --git a/src/AgConfigure.h b/src/AgConfigure.h index 8a453d6..49785d4 100644 --- a/src/AgConfigure.h +++ b/src/AgConfigure.h @@ -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); diff --git a/src/Libraries/airgradient-client b/src/Libraries/airgradient-client index 938a928..f8a455c 160000 --- a/src/Libraries/airgradient-client +++ b/src/Libraries/airgradient-client @@ -1 +1 @@ -Subproject commit 938a92830d090bbd3ae100007040fb404220c551 +Subproject commit f8a455c548a18570ad845c121dd1252939c3439f From 4886163cda758d8c9626a391e07a0b9cfbf8b480 Mon Sep 17 00:00:00 2001 From: samuelbles07 Date: Wed, 2 Apr 2025 02:33:24 +0700 Subject: [PATCH 2/5] Show on oled when httpDomain is set --- examples/OneOpenAir/OneOpenAir.ino | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/OneOpenAir/OneOpenAir.ino b/examples/OneOpenAir/OneOpenAir.ino index 9d98010..c657149 100644 --- a/examples/OneOpenAir/OneOpenAir.ino +++ b/examples/OneOpenAir/OneOpenAir.ino @@ -947,7 +947,9 @@ void initializeNetwork() { String httpDomain = configuration.getHttpDomain(); if (httpDomain != "") { agClient->setHttpDomain(httpDomain.c_str()); - Serial.printf("HTTP request domain set to: %s\n", 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())) { @@ -1049,11 +1051,11 @@ static void configUpdateHandle() { String httpDomain = configuration.getHttpDomain(); if (httpDomain != "") { - Serial.printf("HTTP request domain set to: %s\n", httpDomain.c_str()); + 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 from configuration empty, set to default"); + Serial.println("HTTP domain name from configuration empty, set to default"); agClient->setHttpDomainDefault(); } From 55710dd4d9d3c414eddf24b4d8e446fb4eab187e Mon Sep 17 00:00:00 2001 From: samuelbles07 Date: Wed, 2 Apr 2025 16:18:55 +0700 Subject: [PATCH 3/5] Update docs for new configuration http domain --- docs/local-server.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/local-server.md b/docs/local-server.md index 59b8e51..361b4d2 100644 --- a/docs/local-server.md +++ b/docs/local-server.md @@ -147,6 +147,7 @@ If the monitor is set up on the AirGradient dashboard, it will also receive the | `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"}` | +| `httpDomain` | Domain name for http request. | String | | `{"httpDomain": "sub.domain.com"}` | `temperatureUnit` | Temperature unit shown on the display. | String | `c` or `C`: Degree Celsius °C
`f` or `F`: Degree Fahrenheit °F | `{"temperatureUnit": "c"}` | | `configurationControl` | The configuration source of the device. | String | `both`: Accept local and cloud configuration
`local`: Accept only local configuration
`cloud`: Accept only cloud configuration | `{"configurationControl": "both"}` | | `postDataToAirGradient` | Send data to AirGradient cloud. | Boolean | `true`: Enabled
`false`: Disabled | `{"postDataToAirGradient": true}` | From 029457c3fa33e437755ffdce363a204b52df4469 Mon Sep 17 00:00:00 2001 From: samuelbles07 Date: Wed, 2 Apr 2025 16:26:07 +0700 Subject: [PATCH 4/5] Add accepted value to http domain --- docs/local-server.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/local-server.md b/docs/local-server.md index 361b4d2..9795b85 100644 --- a/docs/local-server.md +++ b/docs/local-server.md @@ -146,8 +146,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"}` | -| `httpDomain` | Domain name for http request. | String | | `{"httpDomain": "sub.domain.com"}` +| `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
`f` or `F`: Degree Fahrenheit °F | `{"temperatureUnit": "c"}` | | `configurationControl` | The configuration source of the device. | String | `both`: Accept local and cloud configuration
`local`: Accept only local configuration
`cloud`: Accept only cloud configuration | `{"configurationControl": "both"}` | | `postDataToAirGradient` | Send data to AirGradient cloud. | Boolean | `true`: Enabled
`false`: Disabled | `{"postDataToAirGradient": true}` | @@ -155,8 +155,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)
`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)
`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** From a91747e379cabfe6819f43c41590d4c000ef00cf Mon Sep 17 00:00:00 2001 From: samuelbles07 Date: Wed, 2 Apr 2025 16:30:13 +0700 Subject: [PATCH 5/5] Update config sample --- docs/local-server.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/local-server.md b/docs/local-server.md index 9795b85..e7d76e4 100644 --- a/docs/local-server.md +++ b/docs/local-server.md @@ -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,