Merge branch 'develop' into feature/press-button-for-offline-mode

This commit is contained in:
Phat Nguyen
2024-05-09 14:48:30 +07:00
committed by GitHub
8 changed files with 283 additions and 8 deletions

View File

@ -51,6 +51,7 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
#include "OpenMetrics.h"
#include "WebServer.h"
#include <WebServer.h>
#include <WiFi.h>
#define LED_BAR_ANIMATION_PERIOD 100 /** ms */
#define DISP_UPDATE_INTERVAL 2500 /** ms */
@ -92,6 +93,7 @@ static int getCO2FailCount = 0;
static AgFirmwareMode fwMode = FW_MODE_I_9PSL;
static bool ledBarButtonTest = false;
static String fwNewVersion;
static void boardInit(void);
static void failedHandler(String msg);
@ -111,6 +113,9 @@ static void factoryConfigReset(void);
static void wdgFeedUpdate(void);
static void ledBarEnabledUpdate(void);
static bool sgp41Init(void);
static void otaHandlerCallback(OtaState state, String mesasge);
static void displayExecuteOta(OtaState state, String msg,
int processing);
AgSchedule dispLedSchedule(DISP_UPDATE_INTERVAL, oledDisplayLedBarSchedule);
AgSchedule configSchedule(SERVER_CONFIG_UPDATE_INTERVAL,
@ -162,6 +167,11 @@ void setup() {
if (ag->isOne()) {
if (ledBarButtonTest) {
stateMachine.executeLedBarPowerUpTest();
if (ag->button.getState() == PushButton::BUTTON_PRESSED) {
WiFi.begin("airgradient", "cleanair");
Serial.println("WiFi Credential reset to factory defaults");
ESP.restart();
}
} else {
ledBarEnabledUpdate();
}
@ -205,7 +215,7 @@ void setup() {
#ifdef ESP8266
// ota not supported
#else
otaHandler.updateFirmwareIfOutdated(ag->deviceId());
// otaHandler.updateFirmwareIfOutdated(ag->deviceId());
#endif
apiClient.fetchServerConfiguration();
@ -452,6 +462,80 @@ static bool sgp41Init(void) {
return false;
}
static void otaHandlerCallback(OtaState state, String mesasge) {
switch (state) {
case OtaState::OTA_STATE_BEGIN:
displayExecuteOta(state, fwNewVersion, 0);
break;
case OtaState::OTA_STATE_FAIL:
displayExecuteOta(state, "", 0);
break;
case OtaState::OTA_STATE_PROCESSING:
displayExecuteOta(state, "", mesasge.toInt());
break;
case OtaState::OTA_STATE_SUCCESS:
displayExecuteOta(state, "", mesasge.toInt());
break;
default:
break;
}
}
static void displayExecuteOta(OtaState state, String msg, int processing) {
switch (state) {
case OtaState::OTA_STATE_BEGIN: {
if (ag->isOne()) {
oledDisplay.showNewFirmwareVersion(msg);
} else {
Serial.println("New firmware: " + msg);
}
delay(2500);
break;
}
case OtaState::OTA_STATE_FAIL: {
if (ag->isOne()) {
oledDisplay.showNewFirmwareFailed();
} else {
Serial.println("Error: Firmware update: failed");
}
delay(2500);
break;
}
case OtaState::OTA_STATE_PROCESSING: {
if (ag->isOne()) {
oledDisplay.showNewFirmwareUpdating(String(processing));
} else {
Serial.println("Firmware update: " + String(processing) + String("%"));
}
break;
}
case OtaState::OTA_STATE_SUCCESS: {
int i = 6;
while(i != 0) {
i = i - 1;
Serial.println("OTA update performed, restarting ...");
int i = 6;
while (i != 0) {
i = i - 1;
if (ag->isOne()) {
oledDisplay.showNewFirmwareSuccess(String(i));
} else {
Serial.println("Rebooting... " + String(i));
}
delay(1000);
}
esp_restart();
}
break;
}
default:
break;
}
}
static void sendDataToAg() {
/** Change oledDisplay and led state */
if (ag->isOne()) {
@ -752,6 +836,20 @@ static void configUpdateHandle() {
String(configuration.getDisplayBrightness()));
}
fwNewVersion = configuration.newFirmwareVersion();
if (fwNewVersion.length()) {
int lastOta = configuration.getLastOta();
if (lastOta != 0 && lastOta < (60 * 60 * 24)) {
Serial.println("Ignore OTA cause last update is " + String(lastOta) +
String("sec"));
Serial.println("Retry again after 24h");
} else {
configuration.updateLastOta();
otaHandler.setHandlerCallback(otaHandlerCallback);
otaHandler.updateFirmwareIfOutdated(ag->deviceId());
}
}
appDispHandler();
appLedHandler();
}

View File

@ -1,12 +1,11 @@
#ifndef _OTA_HANDLER_H_
#define _OTA_HANDLER_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 1024
#define URL_BUF_SIZE 256
enum OtaUpdateOutcome {
@ -16,10 +15,19 @@ enum OtaUpdateOutcome {
UDPATE_SKIPPED
};
enum OtaState {
OTA_STATE_BEGIN,
OTA_STATE_FAIL,
OTA_STATE_PROCESSING,
OTA_STATE_SUCCESS
};
typedef void(*OtaHandlerCallback_t)(OtaState state,
String message);
class OtaHandler {
public:
void updateFirmwareIfOutdated(String deviceId) {
String url = "http://hw.airgradient.com/sensors/airgradient:" + deviceId +
"/generic/os/firmware.bin";
url += "?current_firmware=";
@ -30,15 +38,26 @@ public:
esp_http_client_config_t config = {};
config.url = urlAsChar;
esp_err_t ret = attemptToPerformOta(&config);
OtaUpdateOutcome ret = attemptToPerformOta(&config);
Serial.println(ret);
if (ret == OtaUpdateOutcome::UPDATE_PERFORMED) {
Serial.println("OTA update performed, restarting ...");
esp_restart();
if (this->callback) {
this->callback(OtaState::OTA_STATE_SUCCESS, "");
}
} else {
if(this->callback) {
this->callback(OtaState::OTA_STATE_FAIL, "");
}
}
}
void setHandlerCallback(OtaHandlerCallback_t callback) {
this->callback = callback;
}
private:
OtaHandlerCallback_t callback;
OtaUpdateOutcome attemptToPerformOta(const esp_http_client_config_t *config) {
esp_http_client_handle_t client = esp_http_client_init(config);
if (client == NULL) {
@ -94,6 +113,16 @@ private:
}
int binary_file_len = 0;
int totalSize = esp_http_client_get_content_length(client);
Serial.println("File size: " + String(totalSize) + String(" bytes"));
// Show display start update new firmware.
if (this->callback) {
this->callback(OtaState::OTA_STATE_BEGIN, "");
}
// Download file and write new firmware to OTA partition
uint32_t lastUpdate = millis();
while (1) {
int data_read =
esp_http_client_read(client, upgrade_data_buf, OTA_BUF_SIZE);
@ -103,16 +132,33 @@ private:
}
if (data_read < 0) {
Serial.println("Data read error");
if (this->callback) {
this->callback(OtaState::OTA_STATE_FAIL, "");
}
break;
}
if (data_read > 0) {
ota_write_err = esp_ota_write(
update_handle, (const void *)upgrade_data_buf, data_read);
if (ota_write_err != ESP_OK) {
if (this->callback) {
this->callback(OtaState::OTA_STATE_FAIL, "");
}
break;
}
binary_file_len += data_read;
// Serial.printf("Written image length %d\n", binary_file_len);
int percent = (binary_file_len * 100) / totalSize;
uint32_t ms = (uint32_t)(millis() - lastUpdate);
if (ms >= 250) {
// sm.executeOTA(StateMachine::OtaState::OTA_STATE_PROCESSING, "",
// percent);
if (this->callback) {
this->callback(OtaState::OTA_STATE_PROCESSING,
String(percent));
}
lastUpdate = millis();
}
}
}
free(upgrade_data_buf);