Merge branch 'develop' into hotfix/remove-wifi-qrcode

This commit is contained in:
Phat Nguyen
2024-05-02 09:19:14 +07:00
committed by GitHub
9 changed files with 306 additions and 136 deletions

View File

@ -18,7 +18,7 @@ jobs:
core: "esp8266:esp8266@3.1.2" core: "esp8266:esp8266@3.1.2"
core_url: "https://arduino.esp8266.com/stable/package_esp8266com_index.json" core_url: "https://arduino.esp8266.com/stable/package_esp8266com_index.json"
- fqbn: "esp32:esp32:esp32c3" - fqbn: "esp32:esp32:esp32c3"
board_options: "JTAGAdapter=default,CDCOnBoot=cdc,PartitionScheme=default,CPUFreq=160,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,DebugLevel=verbose,EraseFlash=none" board_options: "JTAGAdapter=default,CDCOnBoot=cdc,PartitionScheme=min_spiffs,CPUFreq=160,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,DebugLevel=verbose,EraseFlash=none"
core: "esp32:esp32@2.0.11" core: "esp32:esp32@2.0.11"
exclude: exclude:
- example: "BASIC" - example: "BASIC"

View File

@ -414,6 +414,7 @@ static void wdgFeedUpdate(void) {
static void ledBarEnabledUpdate(void) { static void ledBarEnabledUpdate(void) {
if (ag->isOne()) { if (ag->isOne()) {
ag->ledBar.setBrighness(configuration.getLedBarBrightness());
ag->ledBar.setEnable(configuration.getLedBarMode() != LedBarModeOff); ag->ledBar.setEnable(configuration.getLedBarMode() != LedBarModeOff);
} }
} }
@ -721,6 +722,17 @@ static void configUpdateHandle() {
} }
} }
if (configuration.isLedBarBrightnessChanged()) {
ag->ledBar.setBrighness(configuration.getLedBarBrightness());
Serial.println("Set 'LedBarBrightness' brightness: " +
String(configuration.getLedBarBrightness()));
}
if (configuration.isDisplayBrightnessChanged()) {
oledDisplay.setBrightness(configuration.getDisplayBrightness());
Serial.println("Set 'DisplayBrightness' brightness: " +
String(configuration.getDisplayBrightness()));
}
appDispHandler(); appDispHandler();
appLedHandler(); appLedHandler();
} }

View File

@ -1,10 +1,10 @@
#ifndef _OTA_HANDLER_H_ #ifndef _OTA_HANDLER_H_
#define _OTA_HANDLER_H_ #define _OTA_HANDLER_H_
#include <esp_ota_ops.h>
#include <esp_http_client.h>
#include <esp_err.h>
#include <Arduino.h> #include <Arduino.h>
#include <esp_err.h>
#include <esp_http_client.h>
#include <esp_ota_ops.h>
#define OTA_BUF_SIZE 512 #define OTA_BUF_SIZE 512
#define URL_BUF_SIZE 256 #define URL_BUF_SIZE 256
@ -16,13 +16,12 @@ enum OtaUpdateOutcome {
UDPATE_SKIPPED UDPATE_SKIPPED
}; };
class OtaHandler { class OtaHandler {
public: public:
void updateFirmwareIfOutdated(String deviceId) { void updateFirmwareIfOutdated(String deviceId) {
String url = "http://hw.airgradient.com/sensors/airgradient:" String url = "http://hw.airgradient.com/sensors/airgradient:" + deviceId +
+ deviceId + "/generic/os/firmware.bin"; "/generic/os/firmware.bin";
url += "?current_firmware="; url += "?current_firmware=";
url += GIT_VERSION; url += GIT_VERSION;
char urlAsChar[URL_BUF_SIZE]; char urlAsChar[URL_BUF_SIZE];
@ -40,7 +39,6 @@ public:
} }
private: private:
OtaUpdateOutcome attemptToPerformOta(const esp_http_client_config_t *config) { OtaUpdateOutcome attemptToPerformOta(const esp_http_client_config_t *config) {
esp_http_client_handle_t client = esp_http_client_init(config); esp_http_client_handle_t client = esp_http_client_init(config);
if (client == NULL) { if (client == NULL) {
@ -51,7 +49,8 @@ private:
esp_err_t err = esp_http_client_open(client, 0); esp_err_t err = esp_http_client_open(client, 0);
if (err != ESP_OK) { if (err != ESP_OK) {
esp_http_client_cleanup(client); esp_http_client_cleanup(client);
Serial.printf("Failed to open HTTP connection: %s\n", esp_err_to_name(err)); Serial.printf("Failed to open HTTP connection: %s\n",
esp_err_to_name(err));
return OtaUpdateOutcome::UPDATE_FAILED; return OtaUpdateOutcome::UPDATE_FAILED;
} }
esp_http_client_fetch_headers(client); esp_http_client_fetch_headers(client);
@ -62,7 +61,8 @@ private:
cleanupHttp(client); cleanupHttp(client);
return OtaUpdateOutcome::ALREADY_UP_TO_DATE; return OtaUpdateOutcome::ALREADY_UP_TO_DATE;
} else if (httpStatusCode != 200) { } else if (httpStatusCode != 200) {
Serial.printf("Firmware update skipped, the server returned %d\n", httpStatusCode); Serial.printf("Firmware update skipped, the server returned %d\n",
httpStatusCode);
cleanupHttp(client); cleanupHttp(client);
return OtaUpdateOutcome::UDPATE_SKIPPED; return OtaUpdateOutcome::UDPATE_SKIPPED;
} }
@ -95,7 +95,8 @@ private:
int binary_file_len = 0; int binary_file_len = 0;
while (1) { while (1) {
int data_read = esp_http_client_read(client, upgrade_data_buf, OTA_BUF_SIZE); int data_read =
esp_http_client_read(client, upgrade_data_buf, OTA_BUF_SIZE);
if (data_read == 0) { if (data_read == 0) {
Serial.println("Connection closed, all data received"); Serial.println("Connection closed, all data received");
break; break;
@ -105,7 +106,8 @@ private:
break; break;
} }
if (data_read > 0) { if (data_read > 0) {
ota_write_err = esp_ota_write( update_handle, (const void *)upgrade_data_buf, data_read); ota_write_err = esp_ota_write(
update_handle, (const void *)upgrade_data_buf, data_read);
if (ota_write_err != ESP_OK) { if (ota_write_err != ESP_OK) {
break; break;
} }
@ -122,7 +124,8 @@ private:
Serial.printf("Error: esp_ota_write failed! err=0x%d\n", err); Serial.printf("Error: esp_ota_write failed! err=0x%d\n", err);
return OtaUpdateOutcome::UPDATE_FAILED; return OtaUpdateOutcome::UPDATE_FAILED;
} else if (ota_end_err != ESP_OK) { } else if (ota_end_err != ESP_OK) {
Serial.printf("Error: esp_ota_end failed! err=0x%d. Image is invalid", ota_end_err); Serial.printf("Error: esp_ota_end failed! err=0x%d. Image is invalid",
ota_end_err);
return OtaUpdateOutcome::UPDATE_FAILED; return OtaUpdateOutcome::UPDATE_FAILED;
} }
@ -138,7 +141,6 @@ private:
esp_http_client_close(client); esp_http_client_close(client);
esp_http_client_cleanup(client); esp_http_client_cleanup(client);
} }
}; };
#endif #endif

View File

@ -8,7 +8,7 @@
; Please visit documentation for the other options and examples ; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html ; https://docs.platformio.org/page/projectconf.html
[env:esp32-c3-devkitm-1] [env:esp32-c3]
platform = espressif32 platform = espressif32
board = esp32-c3-devkitm-1 board = esp32-c3-devkitm-1
framework = arduino framework = arduino
@ -17,8 +17,34 @@ board_build.partitions = partitions.csv
monitor_speed = 115200 monitor_speed = 115200
lib_deps = lib_deps =
aglib=symlink://../arduino aglib=symlink://../arduino
EEPROM
WebServer
ESPmDNS
FS
SPIFFS
HTTPClient
WiFiClientSecure
Update
DNSServer
monitor_filters = time
[env:esp8266]
platform = espressif8266
board = d1_mini
framework = arduino
monitor_speed = 115200
lib_deps =
aglib=symlink://../arduino
EEPROM
ESP8266HTTPClient
ESP8266WebServer
DNSServer
monitor_filters = time monitor_filters = time
[platformio] [platformio]
src_dir = examples/OneOpenAir src_dir = examples/OneOpenAir
; src_dir = examples/BASIC
; src_dir = examples/TestCO2
; src_dir = examples/TestPM
; src_dir = examples/TestSht

View File

@ -1,6 +1,14 @@
#include "AgConfigure.h" #include "AgConfigure.h"
#include "EEPROM.h"
#include "Libraries/Arduino_JSON/src/Arduino_JSON.h" #include "Libraries/Arduino_JSON/src/Arduino_JSON.h"
#if ESP32
#include "FS.h"
#include "SPIFFS.h"
#else
#include "EEPROM.h"
#endif
#define EEPROM_CONFIG_SIZE 512
#define CONFIG_FILE_NAME "/cfg.bin"
const char *CONFIGURATION_CONTROL_NAME[] = { const char *CONFIGURATION_CONTROL_NAME[] = {
[ConfigurationControlLocal] = "local", [ConfigurationControlLocal] = "local",
@ -54,10 +62,19 @@ void Configuration::saveConfig(void) {
for (int i = 0; i < sizeof(config); i++) { for (int i = 0; i < sizeof(config); i++) {
EEPROM.write(i, data[i]); EEPROM.write(i, data[i]);
} }
#else
EEPROM.writeBytes(0, &config, sizeof(config));
#endif
EEPROM.commit(); EEPROM.commit();
#else
File file = SPIFFS.open(CONFIG_FILE_NAME, "w", true);
if (file && !file.isDirectory()) {
if (file.write((const uint8_t *)&config, sizeof(config)) !=
sizeof(config)) {
logError("Write SPIFFS file failed");
}
file.close();
} else {
logError("Open SPIFFS file to write failed");
}
#endif
logInfo("Save Config"); logInfo("Save Config");
} }
@ -70,9 +87,13 @@ void Configuration::loadConfig(void) {
} }
readSuccess = true; readSuccess = true;
#else #else
if (EEPROM.readBytes(0, &config, sizeof(config)) == sizeof(config)) { File file = SPIFFS.open(CONFIG_FILE_NAME);
if (file && !file.isDirectory()) {
if (file.readBytes((char *)&config, sizeof(config)) == sizeof(config)) {
readSuccess = true; readSuccess = true;
} }
file.close();
}
#endif #endif
if (!readSuccess) { if (!readSuccess) {
@ -104,6 +125,15 @@ void Configuration::loadConfig(void) {
changed = true; changed = true;
logError("LedBarMode invalid, set default: co2"); logError("LedBarMode invalid, set default: co2");
} }
if (config.ledBarBrightness > 100) {
config.ledBarBrightness = 100;
changed = true;
}
if (config.displayBrightness > 100) {
config.displayBrightness = 100;
changed = true;
}
if (changed) { if (changed) {
saveConfig(); saveConfig();
} }
@ -131,6 +161,8 @@ void Configuration::defaultConfig(void) {
config.tvocLearningOffset = 12; config.tvocLearningOffset = 12;
config.noxLearningOffset = 12; config.noxLearningOffset = 12;
config.temperatureUnit = 'c'; config.temperatureUnit = 'c';
config.ledBarBrightness = 100;
config.displayBrightness = 100;
saveConfig(); saveConfig();
} }
@ -162,7 +194,20 @@ Configuration::~Configuration() {}
* @return false Failure * @return false Failure
*/ */
bool Configuration::begin(void) { bool Configuration::begin(void) {
EEPROM.begin(512); if (sizeof(config) > EEPROM_CONFIG_SIZE) {
logError("Configuration over EEPROM_CONFIG_SIZE");
return false;
}
#ifdef ESP32
if (!SPIFFS.begin(true)) {
logError("Init SPIFFS failed");
return false;
}
#else
EEPROM.begin(EEPROM_CONFIG_SIZE);
#endif
loadConfig(); loadConfig();
printConfig(); printConfig();
@ -298,7 +343,8 @@ bool Configuration::parse(String data, bool isLocal) {
} }
if (inUSAQI != config.inUSAQI) { if (inUSAQI != config.inUSAQI) {
configLogInfo("pmStandard", getPMStandardString(config.inUSAQI), pmStandard); configLogInfo("pmStandard", getPMStandardString(config.inUSAQI),
pmStandard);
config.inUSAQI = inUSAQI; config.inUSAQI = inUSAQI;
changed = true; changed = true;
} }
@ -312,7 +358,7 @@ bool Configuration::parse(String data, bool isLocal) {
if (JSON.typeof_(root["co2CalibrationRequested"]) == "boolean") { if (JSON.typeof_(root["co2CalibrationRequested"]) == "boolean") {
co2CalibrationRequested = root["co2CalibrationRequested"]; co2CalibrationRequested = root["co2CalibrationRequested"];
if(co2CalibrationRequested) { if (co2CalibrationRequested) {
logInfo("co2CalibrationRequested: " + logInfo("co2CalibrationRequested: " +
String(co2CalibrationRequested ? "True" : "False")); String(co2CalibrationRequested ? "True" : "False"));
} }
@ -327,7 +373,7 @@ bool Configuration::parse(String data, bool isLocal) {
if (JSON.typeof_(root["ledBarTestRequested"]) == "boolean") { if (JSON.typeof_(root["ledBarTestRequested"]) == "boolean") {
ledBarTestRequested = root["ledBarTestRequested"]; ledBarTestRequested = root["ledBarTestRequested"];
if(ledBarTestRequested){ if (ledBarTestRequested) {
logInfo("ledBarTestRequested: " + logInfo("ledBarTestRequested: " +
String(ledBarTestRequested ? "True" : "False")); String(ledBarTestRequested ? "True" : "False"));
} }
@ -384,7 +430,8 @@ bool Configuration::parse(String data, bool isLocal) {
if (displayMode != config.displayMode) { if (displayMode != config.displayMode) {
changed = true; changed = true;
configLogInfo("displayMode", getDisplayModeString(config.displayMode), mode); configLogInfo("displayMode", getDisplayModeString(config.displayMode),
mode);
config.displayMode = displayMode; config.displayMode = displayMode;
} }
} else { } else {
@ -476,9 +523,9 @@ bool Configuration::parse(String data, bool isLocal) {
if (JSON.typeof_(root["temperatureUnit"]) == "string") { if (JSON.typeof_(root["temperatureUnit"]) == "string") {
String unit = root["temperatureUnit"]; String unit = root["temperatureUnit"];
unit.toLowerCase(); unit.toLowerCase();
if ((unit == "c") || (unit == "celsius")) { if (unit == "c") {
temperatureUnit = 'c'; temperatureUnit = 'c';
} else if ((unit == "f") || (unit == "fahrenheit")) { } else if (unit == "f") {
temperatureUnit = 'f'; temperatureUnit = 'f';
} else { } else {
failedMessage = "'temperatureUnit' value '" + unit + "' invalid"; failedMessage = "'temperatureUnit' value '" + unit + "' invalid";
@ -545,6 +592,52 @@ bool Configuration::parse(String data, bool isLocal) {
} }
} }
if (JSON.typeof_(root["ledbarBrightness"]) == "number") {
int brightnress = root["ledbarBrightness"];
if (brightnress != config.ledBarBrightness) {
if (brightnress <= 100) {
changed = true;
configLogInfo("ledbarBrightness", String(config.ledBarBrightness),
String(brightnress));
ledBarBrightnessChanged = true;
config.ledBarBrightness = (uint8_t)brightnress;
} else {
failedMessage =
"\"ledbarBrightness\" value invalid: " + String(brightnress);
return false;
}
}
} else {
if (jsonTypeInvalid(root["ledbarBrightness"], "number")) {
failedMessage = jsonTypeInvalidMessage("ledbarBrightness", "number");
jsonInvalid();
return false;
}
}
if (JSON.typeof_(root["displayBrightness"]) == "number") {
int brightness = root["displayBrightness"];
if (brightness != config.displayBrightness) {
if (brightness <= 100) {
changed = true;
displayBrightnessChanged = true;
configLogInfo("displayBrightness", String(config.displayBrightness),
String(brightness));
config.displayBrightness = (uint8_t)brightness;
} else {
failedMessage =
"\"displayBrightness\" value invalid: " + String(brightness);
return false;
}
}
} else {
if (jsonTypeInvalid(root["displayBrightness"], "number")) {
failedMessage = jsonTypeInvalidMessage("displayBrightness", "number");
jsonInvalid();
return false;
}
}
if (changed) { if (changed) {
udpated = true; udpated = true;
saveConfig(); saveConfig();
@ -607,6 +700,12 @@ String Configuration::toString(void) {
/** "postDataToAirGradient" */ /** "postDataToAirGradient" */
root["postDataToAirGradient"] = config.postDataToAirGradient; root["postDataToAirGradient"] = config.postDataToAirGradient;
/** Led bar brightness */
root["ledbarBrightness"] = config.ledBarBrightness;
/** Display brightness */
root["displayBrightness"] = config.displayBrightness;
return JSON.stringify(root); return JSON.stringify(root);
} }
@ -771,14 +870,14 @@ String Configuration::getPMStandardString(bool usaqi) {
} }
String Configuration::getDisplayModeString(bool dispMode) { String Configuration::getDisplayModeString(bool dispMode) {
if(dispMode){ if (dispMode) {
return String("on"); return String("on");
} }
return String("off"); return String("off");
} }
String Configuration::getAbcDayString(int value) { String Configuration::getAbcDayString(int value) {
if(value <= 0){ if (value <= 0) {
return String("off"); return String("off");
} }
return String(value); return String(value);
@ -816,10 +915,26 @@ int Configuration::getNoxLearningOffset(void) {
return config.noxLearningOffset; return config.noxLearningOffset;
} }
String Configuration::wifiSSID(void) { String Configuration::wifiSSID(void) { return "airgradient-" + ag->deviceId(); }
return "airgradient-" + ag->deviceId();
}
String Configuration::wifiPass(void) { return String("cleanair"); } String Configuration::wifiPass(void) { return String("cleanair"); }
void Configuration::setAirGradient(AirGradient *ag) { this->ag = ag;} void Configuration::setAirGradient(AirGradient *ag) { this->ag = ag; }
int Configuration::getLedBarBrightness(void) { return config.ledBarBrightness; }
bool Configuration::isLedBarBrightnessChanged(void) {
bool changed = ledBarBrightnessChanged;
ledBarBrightnessChanged = false;
return changed;
}
int Configuration::getDisplayBrightness(void) {
return config.displayBrightness;
}
bool Configuration::isDisplayBrightnessChanged(void) {
bool changed = displayBrightnessChanged;
displayBrightnessChanged = false;
return changed;
}

View File

@ -23,6 +23,8 @@ private:
bool displayMode; /** true if enable display */ bool displayMode; /** true if enable display */
uint8_t useRGBLedBar; uint8_t useRGBLedBar;
uint8_t abcDays; uint8_t abcDays;
uint8_t ledBarBrightness;
uint8_t displayBrightness;
int tvocLearningOffset; int tvocLearningOffset;
int noxLearningOffset; int noxLearningOffset;
char temperatureUnit; // 'f' or 'c' char temperatureUnit; // 'f' or 'c'
@ -36,6 +38,8 @@ private:
String failedMessage; String failedMessage;
bool _noxLearnOffsetChanged; bool _noxLearnOffsetChanged;
bool _tvocLearningOffsetChanged; bool _tvocLearningOffsetChanged;
bool ledBarBrightnessChanged = false;
bool displayBrightnessChanged = false;
AirGradient* ag; AirGradient* ag;
@ -89,6 +93,10 @@ public:
String wifiSSID(void); String wifiSSID(void);
String wifiPass(void); String wifiPass(void);
void setAirGradient(AirGradient *ag); void setAirGradient(AirGradient *ag);
bool isLedBarBrightnessChanged(void);
int getLedBarBrightness(void);
bool isDisplayBrightnessChanged(void);
int getDisplayBrightness(void);
}; };
#endif /** _AG_CONFIG_H_ */ #endif /** _AG_CONFIG_H_ */

View File

@ -93,6 +93,8 @@ bool OledDisplay::begin(void) {
return false; return false;
} }
setBrightness(config.getDisplayBrightness());
isBegin = true; isBegin = true;
logInfo("begin"); logInfo("begin");
return true; return true;
@ -285,3 +287,7 @@ void OledDisplay::showDashboard(const char *status) {
DISP()->drawStr(85, 63, strBuf); DISP()->drawStr(85, 63, strBuf);
} while (DISP()->nextPage()); } while (DISP()->nextPage());
} }
void OledDisplay::setBrightness(int percent) {
DISP()->setContrast((127 * percent) / 100);
}

View File

@ -31,6 +31,7 @@ public:
const char *line4); const char *line4);
void showDashboard(void); void showDashboard(void);
void showDashboard(const char *status); void showDashboard(const char *status);
void setBrightness(int percent);
}; };
#endif /** _AG_OLED_DISPLAY_H_ */ #endif /** _AG_OLED_DISPLAY_H_ */

View File

@ -62,13 +62,13 @@ void LedBar::setColor(uint8_t red, uint8_t green, uint8_t blue, int ledNum) {
/** /**
* @brief Set LED brightness apply for all LED bar * @brief Set LED brightness apply for all LED bar
* *
* @param brightness Brightness (0 - 255) * @param brightness Brightness (0 - 100)%
*/ */
void LedBar::setBrighness(uint8_t brightness) { void LedBar::setBrighness(uint8_t brightness) {
if (this->isBegin() == false) { if (this->isBegin() == false) {
return; return;
} }
pixel()->setBrightness(brightness); pixel()->setBrightness((brightness * 0xff) / 100);
} }
/** /**