From 5275f5a810d9efbd38815193f5a5aff9bfc29d95 Mon Sep 17 00:00:00 2001 From: nick-4711 Date: Mon, 22 Apr 2024 19:52:13 +0700 Subject: [PATCH 1/5] compile git version into firmware --- .gitignore | 1 + examples/OneOpenAir/OneOpenAir.ino | 2 ++ platformio.ini | 6 +++--- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index fb4b0b5..a1ec5b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.DS_Store build .vscode +/.idea/ .pio diff --git a/examples/OneOpenAir/OneOpenAir.ino b/examples/OneOpenAir/OneOpenAir.ino index b6ac178..7de2027 100644 --- a/examples/OneOpenAir/OneOpenAir.ino +++ b/examples/OneOpenAir/OneOpenAir.ino @@ -467,6 +467,8 @@ static void oneIndoorInit(void) { /** Show boot display */ Serial.println("Firmware Version: " + ag->getVersion()); + Serial.printf("Firmware version: %s\n", GIT_VERSION); + oledDisplay.setText("AirGradient ONE", "FW Version: ", ag->getVersion().c_str()); delay(DISPLAY_DELAY_SHOW_CONTENT_MS); diff --git a/platformio.ini b/platformio.ini index 184ca66..a102edd 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,13 +12,13 @@ platform = espressif32 board = esp32-c3-devkitm-1 framework = arduino -build_flags = - -DARDUINO_USB_CDC_ON_BOOT=1 - -DARDUINO_USB_MODE=1 +build_flags = '-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 -D GIT_VERSION=\\"'$(git describe --tags --always --dirty)'\\"' board_build.partitions = partitions.csv monitor_speed = 115200 lib_deps = aglib=symlink://../arduino +monitor_filters = time + [platformio] src_dir = examples/OneOpenAir From 12f03aff30c906b5bbd616ade31ed7834f3170c8 Mon Sep 17 00:00:00 2001 From: nick-4711 Date: Tue, 23 Apr 2024 05:59:58 +0700 Subject: [PATCH 2/5] ota handler added, wip --- examples/OneOpenAir/OneOpenAir.ino | 10 ++++++++-- examples/OneOpenAir/OpenMetrics.h | 2 +- examples/OneOpenAir/OtaHandler.h | 12 ++++++++++++ platformio.ini | 2 +- src/AirGradient.cpp | 4 +--- 5 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 examples/OneOpenAir/OtaHandler.h diff --git a/examples/OneOpenAir/OneOpenAir.ino b/examples/OneOpenAir/OneOpenAir.ino index 7de2027..58c5509 100644 --- a/examples/OneOpenAir/OneOpenAir.ino +++ b/examples/OneOpenAir/OneOpenAir.ino @@ -37,7 +37,7 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License */ #include - +#include "OtaHandler.h" #include "AgApiClient.h" #include "AgConfigure.h" #include "AgSchedule.h" @@ -81,6 +81,7 @@ static StateMachine stateMachine(oledDisplay, Serial, measurements, static WifiConnector wifiConnector(oledDisplay, Serial, stateMachine, configuration); static OpenMetrics openMetrics(measurements, configuration, wifiConnector, apiClient); +static OtaHandler otaHandler; static LocalServer localServer(Serial, openMetrics, measurements, configuration, wifiConnector); @@ -178,6 +179,12 @@ void setup() { initMqtt(); sendDataToAg(); + #ifdef ESP8266 + // ota not supported + #else + otaHandler.updateFirmwareIfOutdated(); + #endif + apiClient.fetchServerConfiguration(); configSchedule.update(); if (apiClient.isFetchConfigureFailed()) { @@ -467,7 +474,6 @@ static void oneIndoorInit(void) { /** Show boot display */ Serial.println("Firmware Version: " + ag->getVersion()); - Serial.printf("Firmware version: %s\n", GIT_VERSION); oledDisplay.setText("AirGradient ONE", "FW Version: ", ag->getVersion().c_str()); diff --git a/examples/OneOpenAir/OpenMetrics.h b/examples/OneOpenAir/OpenMetrics.h index 5df2349..ed890f5 100644 --- a/examples/OneOpenAir/OpenMetrics.h +++ b/examples/OneOpenAir/OpenMetrics.h @@ -7,7 +7,7 @@ #include "AirGradient.h" #include "AgApiClient.h" -class OpenMetrics{ +class OpenMetrics { private: AirGradient *ag; Measurements &measure; diff --git a/examples/OneOpenAir/OtaHandler.h b/examples/OneOpenAir/OtaHandler.h new file mode 100644 index 0000000..2e88dc4 --- /dev/null +++ b/examples/OneOpenAir/OtaHandler.h @@ -0,0 +1,12 @@ +#ifndef _OTA_HANDLER_H_ +#define _OTA_HANDLER_H_ + + +class OtaHandler { +public: + void updateFirmwareIfOutdated() { + + } +}; + +#endif diff --git a/platformio.ini b/platformio.ini index a102edd..af8e14f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,7 +12,7 @@ platform = espressif32 board = esp32-c3-devkitm-1 framework = arduino -build_flags = '-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 -D GIT_VERSION=\\"'$(git describe --tags --always --dirty)'\\"' +build_flags = !echo '-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 -D GIT_VERSION=\\"'$(git describe --tags --always --dirty)'\\"' board_build.partitions = partitions.csv monitor_speed = 115200 lib_deps = diff --git a/src/AirGradient.cpp b/src/AirGradient.cpp index 9be7f72..9c24a97 100644 --- a/src/AirGradient.cpp +++ b/src/AirGradient.cpp @@ -5,8 +5,6 @@ #include "WiFi.h" #endif -#define AG_LIB_VER "3.0.10beta2" - AirGradient::AirGradient(BoardType type) : pms5003(type), pms5003t_1(type), pms5003t_2(type), s8(type), sgp41(type), display(type), boardType(type), button(type), statusLed(type), @@ -38,7 +36,7 @@ int AirGradient::getI2cSclPin(void) { return bsp->I2C.scl_pin; } -String AirGradient::getVersion(void) { return AG_LIB_VER; } +String AirGradient::getVersion(void) { return GIT_VERSION; } BoardType AirGradient::getBoardType(void) { return boardType; } From e12a1542359010864593e75c632c6ea1651dcad9 Mon Sep 17 00:00:00 2001 From: nick-4711 Date: Tue, 23 Apr 2024 06:35:21 +0700 Subject: [PATCH 3/5] ota handling code added, wip --- examples/OneOpenAir/OtaHandler.h | 116 ++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/examples/OneOpenAir/OtaHandler.h b/examples/OneOpenAir/OtaHandler.h index 2e88dc4..a7dfa9c 100644 --- a/examples/OneOpenAir/OtaHandler.h +++ b/examples/OneOpenAir/OtaHandler.h @@ -1,12 +1,126 @@ #ifndef _OTA_HANDLER_H_ #define _OTA_HANDLER_H_ +#include +#include +#include +#include + +#define OTA_BUF_SIZE 256 + class OtaHandler { public: void updateFirmwareIfOutdated() { - + + char url[] = "http://todo"; + Serial.printf("checking for new ota @ %s\n", url ); + + esp_http_client_config_t config = {}; + config.url = url; + esp_err_t ret = attemptToPerformOta(&config); + Serial.println(ret); + if (ret == 0) { + Serial.println("OTA completed"); + esp_restart(); + } else { + Serial.println("OTA failed, maybe already up to date"); + } } + +private: + + // TODO: return some enum? + int attemptToPerformOta(const esp_http_client_config_t *config) { + + esp_http_client_handle_t client = esp_http_client_init(config); + if (client == NULL) { + Serial.println("Failed to initialize HTTP connection"); + return -1; + } + + esp_err_t err = esp_http_client_open(client, 0); + if (err != ESP_OK) { + esp_http_client_cleanup(client); + Serial.printf("Failed to open HTTP connection: %s\n", esp_err_to_name(err)); + return -1; + } + esp_http_client_fetch_headers(client); + + esp_ota_handle_t update_handle = 0; + const esp_partition_t *update_partition = NULL; + Serial.println("Starting ota ..."); + update_partition = esp_ota_get_next_update_partition(NULL); + if (update_partition == NULL) { + Serial.println("Passive OTA partition not found"); + cleanupHttp(client); + return ESP_FAIL; + } + Serial.printf("Writing to partition subtype %d at offset 0x%x\n", + update_partition->subtype, update_partition->address); + + err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle); + if (err != ESP_OK) { + Serial.printf("esp_ota_begin failed, error=%d\n", err); + cleanupHttp(client); + return err; + } + + + esp_err_t ota_write_err = ESP_OK; + char *upgrade_data_buf = (char *)malloc(OTA_BUF_SIZE); + if (!upgrade_data_buf) { + Serial.println("Couldn't allocate memory to upgrade data buffer"); + return ESP_ERR_NO_MEM; + } + int binary_file_len = 0; + while (1) { + int data_read = esp_http_client_read(client, upgrade_data_buf, OTA_BUF_SIZE); + if (data_read == 0) { + Serial.println("Connection closed,all data received"); + break; + } + if (data_read < 0) { + Serial.println("Error: SSL data read error"); + 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) { + break; + } + binary_file_len += data_read; + Serial.printf("Written image length %d\n", binary_file_len); + } + } + free(upgrade_data_buf); + cleanupHttp(client); + Serial.printf("Total binary data length writen: %d\n", binary_file_len); + + esp_err_t ota_end_err = esp_ota_end(update_handle); + if (ota_write_err != ESP_OK) { + Serial.printf("Error: esp_ota_write failed! err=0x%d\n", err); + return ota_write_err; + } else if (ota_end_err != ESP_OK) { + Serial.printf("Error: esp_ota_end failed! err=0x%d. Image is invalid", ota_end_err); + return ota_end_err; + } + + err = esp_ota_set_boot_partition(update_partition); + if (err != ESP_OK) { + Serial.printf("esp_ota_set_boot_partition failed! err=0x%d\n", err); + return err; + } + + return 0; + + } + + void cleanupHttp(esp_http_client_handle_t client) { + esp_http_client_close(client); + esp_http_client_cleanup(client); + } + }; #endif From 1c8d7b04e9d397ba0fd28ef783ccd358856fcf6d Mon Sep 17 00:00:00 2001 From: nick-4711 Date: Wed, 24 Apr 2024 19:56:37 +0700 Subject: [PATCH 4/5] ota handling implemented --- examples/OneOpenAir/OneOpenAir.ino | 2 +- examples/OneOpenAir/OtaHandler.h | 34 ++++++++++++++++-------------- src/AirGradient.cpp | 4 ++++ 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/examples/OneOpenAir/OneOpenAir.ino b/examples/OneOpenAir/OneOpenAir.ino index 58c5509..d730d9b 100644 --- a/examples/OneOpenAir/OneOpenAir.ino +++ b/examples/OneOpenAir/OneOpenAir.ino @@ -182,7 +182,7 @@ void setup() { #ifdef ESP8266 // ota not supported #else - otaHandler.updateFirmwareIfOutdated(); + otaHandler.updateFirmwareIfOutdated(ag->deviceId()); #endif apiClient.fetchServerConfiguration(); diff --git a/examples/OneOpenAir/OtaHandler.h b/examples/OneOpenAir/OtaHandler.h index a7dfa9c..e26848f 100644 --- a/examples/OneOpenAir/OtaHandler.h +++ b/examples/OneOpenAir/OtaHandler.h @@ -6,18 +6,24 @@ #include #include -#define OTA_BUF_SIZE 256 +#define OTA_BUF_SIZE 512 +#define URL_BUF_SIZE 256 class OtaHandler { public: - void updateFirmwareIfOutdated() { + void updateFirmwareIfOutdated(String deviceId) { - char url[] = "http://todo"; - Serial.printf("checking for new ota @ %s\n", url ); + String url = "http://hw.airgradient.com/sensors/airgradient:" + + deviceId + "/generic/os/firmware.bin"; + url += "?current_firmware="; + url += GIT_VERSION; + char urlAsChar[URL_BUF_SIZE]; + url.toCharArray(urlAsChar, URL_BUF_SIZE); + Serial.printf("checking for new ota @ %s\n", urlAsChar); esp_http_client_config_t config = {}; - config.url = url; + config.url = urlAsChar; esp_err_t ret = attemptToPerformOta(&config); Serial.println(ret); if (ret == 0) { @@ -30,9 +36,7 @@ public: private: - // TODO: return some enum? int attemptToPerformOta(const esp_http_client_config_t *config) { - esp_http_client_handle_t client = esp_http_client_init(config); if (client == NULL) { Serial.println("Failed to initialize HTTP connection"); @@ -49,7 +53,7 @@ private: esp_ota_handle_t update_handle = 0; const esp_partition_t *update_partition = NULL; - Serial.println("Starting ota ..."); + Serial.println("Starting OTA ..."); update_partition = esp_ota_get_next_update_partition(NULL); if (update_partition == NULL) { Serial.println("Passive OTA partition not found"); @@ -66,22 +70,22 @@ private: return err; } - esp_err_t ota_write_err = ESP_OK; char *upgrade_data_buf = (char *)malloc(OTA_BUF_SIZE); if (!upgrade_data_buf) { - Serial.println("Couldn't allocate memory to upgrade data buffer"); + Serial.println("Couldn't allocate memory for data buffer"); return ESP_ERR_NO_MEM; } + int binary_file_len = 0; while (1) { int data_read = esp_http_client_read(client, upgrade_data_buf, OTA_BUF_SIZE); if (data_read == 0) { - Serial.println("Connection closed,all data received"); + Serial.println("Connection closed, all data received"); break; } if (data_read < 0) { - Serial.println("Error: SSL data read error"); + Serial.println("Data read error"); break; } if (data_read > 0) { @@ -90,12 +94,12 @@ private: break; } binary_file_len += data_read; - Serial.printf("Written image length %d\n", binary_file_len); + // Serial.printf("Written image length %d\n", binary_file_len); } } free(upgrade_data_buf); cleanupHttp(client); - Serial.printf("Total binary data length writen: %d\n", binary_file_len); + Serial.printf("# of bytes written: %d\n", binary_file_len); esp_err_t ota_end_err = esp_ota_end(update_handle); if (ota_write_err != ESP_OK) { @@ -111,9 +115,7 @@ private: Serial.printf("esp_ota_set_boot_partition failed! err=0x%d\n", err); return err; } - return 0; - } void cleanupHttp(esp_http_client_handle_t client) { diff --git a/src/AirGradient.cpp b/src/AirGradient.cpp index 9c24a97..83eb0d2 100644 --- a/src/AirGradient.cpp +++ b/src/AirGradient.cpp @@ -5,6 +5,10 @@ #include "WiFi.h" #endif +#ifndef GIT_VERSION +#define GIT_VERSION "snapshot" +#endif + AirGradient::AirGradient(BoardType type) : pms5003(type), pms5003t_1(type), pms5003t_2(type), s8(type), sgp41(type), display(type), boardType(type), button(type), statusLed(type), From 5078b353410190fe119a082f53624a812516193b Mon Sep 17 00:00:00 2001 From: nick-4711 Date: Wed, 24 Apr 2024 20:27:45 +0700 Subject: [PATCH 5/5] moved fallback GIT_VERSION to AirGradient.h --- examples/OneOpenAir/OneOpenAir.ino | 2 +- src/AirGradient.cpp | 4 ---- src/AirGradient.h | 4 ++++ 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/OneOpenAir/OneOpenAir.ino b/examples/OneOpenAir/OneOpenAir.ino index bb2451b..9d88ab5 100644 --- a/examples/OneOpenAir/OneOpenAir.ino +++ b/examples/OneOpenAir/OneOpenAir.ino @@ -37,6 +37,7 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License */ #include +#include "AirGradient.h" #include "OtaHandler.h" #include "AgApiClient.h" #include "AgConfigure.h" @@ -49,7 +50,6 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License #include "MqttClient.h" #include "OpenMetrics.h" #include "WebServer.h" -#include #include #define LED_BAR_ANIMATION_PERIOD 100 /** ms */ diff --git a/src/AirGradient.cpp b/src/AirGradient.cpp index 83eb0d2..9c24a97 100644 --- a/src/AirGradient.cpp +++ b/src/AirGradient.cpp @@ -5,10 +5,6 @@ #include "WiFi.h" #endif -#ifndef GIT_VERSION -#define GIT_VERSION "snapshot" -#endif - AirGradient::AirGradient(BoardType type) : pms5003(type), pms5003t_1(type), pms5003t_2(type), s8(type), sgp41(type), display(type), boardType(type), button(type), statusLed(type), diff --git a/src/AirGradient.h b/src/AirGradient.h index e056173..6c4eb88 100644 --- a/src/AirGradient.h +++ b/src/AirGradient.h @@ -13,6 +13,10 @@ #include "Sgp41/Sgp41.h" #include "Sht/Sht.h" +#ifndef GIT_VERSION +#define GIT_VERSION "snapshot" +#endif + /** * @brief Class with define all the sensor has supported by Airgradient. Each * sensor usage must be init before use.