diff --git a/Kconfig b/Kconfig index df04b0a..9baaa32 100644 --- a/Kconfig +++ b/Kconfig @@ -44,8 +44,11 @@ menu "WebGUIApp" menu "OTA settings" config WEBGUIAPP_OTA_AUTOUPDATE_ENABLE bool "Enabled OTA autoupdate firmware" - default y - + default n + + config WEBGUIAPP_OTA_RESET_ENABLE + bool "Enabled reset config on OTA update" + default n config WEBGUIAPP_OTA_HOST string "URL of firmware for OTA update" diff --git a/include/NetTransport.h b/include/NetTransport.h index 3062f36..f93cf7e 100644 --- a/include/NetTransport.h +++ b/include/NetTransport.h @@ -100,6 +100,8 @@ void GetRFC3339Time(char *t); void StartTimeGet(void); esp_err_t StartOTA(void); +char* GetAvailVersion(); +char* GetUpdateStatus(); void StartSystemTimer(void); uint32_t GetUpTime(void); diff --git a/include/WebGUIAppMain.h b/include/WebGUIAppMain.h index 5445041..c906d99 100644 --- a/include/WebGUIAppMain.h +++ b/include/WebGUIAppMain.h @@ -45,6 +45,7 @@ char SysName[32]; ///< User Name char SysPass[32]; ///< User Password char OTAURL[64]; ///< OTA URL + int OTAAutoInt; char SN[11]; ///< String of serial number (decimal ID) char ID[9]; ///< String of ID ( last 4 bytes of MAC) @@ -52,10 +53,10 @@ struct { char bIsOTAEnabled :1; + char bIsResetOTAEnabled :1; char bIsLedsEnabled :1; ///< Indication LEDs enable char bIsLoRaConfirm :1; ///< Enable send back confirmation in LoRa channel char bIsTCPConfirm :1; ///< Enable send back confirmation in TCP channel - char bit4 :1; char bit5 :1; char bit6 :1; char bit7 :1; diff --git a/src/HTTPPostSystem.c b/src/HTTPPostSystem.c index 7c170b4..bdd72f2 100644 --- a/src/HTTPPostSystem.c +++ b/src/HTTPPostSystem.c @@ -105,26 +105,26 @@ static HTTP_IO_RESULT HTTPPostAdaptersSettings(httpd_req_t *req, char *PostData) if (httpd_query_key_value(PostData, "ethen", tmp, sizeof(tmp)) == ESP_OK) { if (!strcmp((const char*) tmp, (const char*) "1")) - TempIsETHEnabled = true; + TempIsETHEnabled = true; } if (httpd_query_key_value(PostData, "dhcp", tmp, sizeof(tmp)) == ESP_OK) { if (!strcmp((const char*) tmp, (const char*) "1")) - TempIsETHDHCPEnabled = true; + TempIsETHDHCPEnabled = true; } if (httpd_query_key_value(PostData, "ipa", tmp, 15) == ESP_OK) - esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.IPAddr); + esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.IPAddr); if (httpd_query_key_value(PostData, "mas", tmp, 15) == ESP_OK) - esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.Mask); + esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.Mask); if (httpd_query_key_value(PostData, "gte", tmp, 15) == ESP_OK) - esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.Gateway); + esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.Gateway); if (httpd_query_key_value(PostData, "dns1", tmp, 15) == ESP_OK) - esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.DNSAddr1); + esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.DNSAddr1); if (httpd_query_key_value(PostData, "dns2", tmp, 15) == ESP_OK) - esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.DNSAddr2); + esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.DNSAddr2); if (httpd_query_key_value(PostData, "dns3", tmp, 15) == ESP_OK) - esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.DNSAddr3); + esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.DNSAddr3); #endif @@ -297,29 +297,29 @@ static HTTP_IO_RESULT HTTPPostServicesSettings(httpd_req_t *req, char *PostData) #if CONFIG_WEBGUIAPP_MQTT_CLIENTS_NUM == 2 httpd_query_key_value(PostData, "mqurl2", GetSysConf()->mqttStation[1].ServerAddr, - sizeof(GetSysConf()->mqttStation[1].ServerAddr)); + sizeof(GetSysConf()->mqttStation[1].ServerAddr)); httpd_query_key_value(PostData, "mqid2", GetSysConf()->mqttStation[1].ClientID, - sizeof(GetSysConf()->mqttStation[1].ClientID)); + sizeof(GetSysConf()->mqttStation[1].ClientID)); httpd_query_key_value(PostData, "mqsys2", GetSysConf()->mqttStation[1].SystemName, - sizeof(GetSysConf()->mqttStation[1].SystemName)); + sizeof(GetSysConf()->mqttStation[1].SystemName)); httpd_query_key_value(PostData, "mqgrp2", GetSysConf()->mqttStation[1].GroupName, - sizeof(GetSysConf()->mqttStation[1].GroupName)); + sizeof(GetSysConf()->mqttStation[1].GroupName)); httpd_query_key_value(PostData, "mqname2", GetSysConf()->mqttStation[1].UserName, - sizeof(GetSysConf()->mqttStation[1].UserName)); + sizeof(GetSysConf()->mqttStation[1].UserName)); if (httpd_query_key_value(PostData, "mqen2", tmp, sizeof(tmp)) == ESP_OK) { if (!strcmp((const char*) tmp, (const char*) "1")) - TempIsMQTT2Enabled = true; + TempIsMQTT2Enabled = true; } if (httpd_query_key_value(PostData, "mqport2", tmp, sizeof(tmp)) == ESP_OK) - if (httpd_query_key_value(PostData, "mqport2", tmp, sizeof(tmp)) == ESP_OK) - { - uint16_t tp = atoi((const char*) tmp); - if (tp < 65535 && tp >= 1000) - GetSysConf()->mqttStation[1].ServerPort = tp; - } + if (httpd_query_key_value(PostData, "mqport2", tmp, sizeof(tmp)) == ESP_OK) + { + uint16_t tp = atoi((const char*) tmp); + if (tp < 65535 && tp >= 1000) + GetSysConf()->mqttStation[1].ServerPort = tp; + } if (httpd_query_key_value(PostData, "mqpass2", tmp, sizeof(tmp)) == ESP_OK && strcmp(tmp, (const char*) "******")) @@ -379,7 +379,7 @@ static HTTP_IO_RESULT HTTPPostSystemSettings(httpd_req_t *req, char *PostData) { char tmp[64]; bool TempIsOTAEnabled = false; - + bool TempIsRstEnabled = false; if (httpd_query_key_value(PostData, "nam", tmp, sizeof(tmp)) == ESP_OK) { UnencodeURL(tmp); @@ -400,6 +400,19 @@ static HTTP_IO_RESULT HTTPPostSystemSettings(httpd_req_t *req, char *PostData) TempIsOTAEnabled = true; } + if (httpd_query_key_value(PostData, "otarst", tmp, sizeof(tmp)) == ESP_OK) + { + if (!strcmp((const char*) tmp, (const char*) "1")) + TempIsRstEnabled = true; + } + + if (httpd_query_key_value(PostData, "otaint", tmp, sizeof(tmp)) == ESP_OK) + { + uint16_t tp = atoi((const char*) tmp); + if (tp < 65535 && tp >= 1) + GetSysConf()->OTAAutoInt = tp; + } + if (httpd_query_key_value(PostData, "otaurl", tmp, sizeof(tmp)) == ESP_OK) { UnencodeURL(tmp); @@ -430,6 +443,7 @@ static HTTP_IO_RESULT HTTPPostSystemSettings(httpd_req_t *req, char *PostData) if (!strcmp(tmp, (const char*) "syst")) { GetSysConf()->Flags1.bIsOTAEnabled = TempIsOTAEnabled; + GetSysConf()->Flags1.bIsResetOTAEnabled = TempIsRstEnabled; } if (httpd_query_key_value(PostData, "apply", tmp, 5) == ESP_OK) @@ -450,7 +464,7 @@ static HTTP_IO_RESULT HTTPPostSystemSettings(httpd_req_t *req, char *PostData) { if (!strcmp(tmp, (const char*) "1")) { - WiFiScan(); + WiFiScan(); return HTTP_IO_DONE_NOREFRESH; } else if (!strcmp(tmp, (const char*) "2")) diff --git a/src/HTTPPrintSystem.c b/src/HTTPPrintSystem.c index de694b3..0098d0c 100644 --- a/src/HTTPPrintSystem.c +++ b/src/HTTPPrintSystem.c @@ -152,6 +152,15 @@ static void HTTPPrint_ota(char *VarData, void *arg) { PrintCheckbox(VarData, arg, GetSysConf()->Flags1.bIsOTAEnabled); } +static void HTTPPrint_otarst(char *VarData, void *arg) +{ + PrintCheckbox(VarData, arg, GetSysConf()->Flags1.bIsResetOTAEnabled); +} + +static void HTTPPrint_otaint(char *VarData, void *arg) +{ + snprintf(VarData, MAX_DYNVAR_LENGTH, "%d", GetSysConf()->OTAAutoInt); +} static void HTTPPrint_serial(char *VarData, void *arg) { @@ -170,6 +179,18 @@ static void HTTPPrint_fver(char *VarData, void *arg) snprintf(VarData, MAX_DYNVAR_LENGTH, "%s", cur_app_info.version); } } + +static void HTTPPrint_fverav(char *VarData, void *arg) +{ + snprintf(VarData, MAX_DYNVAR_LENGTH, "%s", GetAvailVersion()); +} + +static void HTTPPrint_updstat(char *VarData, void *arg) +{ + snprintf(VarData, MAX_DYNVAR_LENGTH, "%s", GetUpdateStatus()); +} + + static void HTTPPrint_idfver(char *VarData, void *arg) { esp_app_desc_t cur_app_info; @@ -668,7 +689,13 @@ dyn_var_handler_t HANDLERS_ARRAY[] = { { "login", sizeof("login") - 1, &HTTPPrint_login }, { "pass", sizeof("pass") - 1, &HTTPPrint_pass }, { "ota", sizeof("ota") - 1, &HTTPPrint_ota }, + { "otarst", sizeof("otarst") - 1, &HTTPPrint_otarst }, + { "otaint", sizeof("otaint") - 1, &HTTPPrint_otaint }, { "fver", sizeof("fver") - 1, &HTTPPrint_fver }, + { "fverav", sizeof("fverav") - 1, &HTTPPrint_fverav }, + { "updstat", sizeof("updstat") - 1, &HTTPPrint_updstat }, + + { "idfver", sizeof("idfver") - 1, &HTTPPrint_idfver }, { "builddate", sizeof("builddate") - 1, &HTTPPrint_builddate }, { "serial", sizeof("serial") - 1, &HTTPPrint_serial }, diff --git a/src/OTA.c b/src/OTA.c index 5e6ce96..a11079f 100644 --- a/src/OTA.c +++ b/src/OTA.c @@ -1,285 +1,300 @@ - /* Copyright 2022 Bogdan Pilyugin - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * File name: OTA.c - * Project: ChargePointMainboard - * Created on: 2022-07-21 - * Author: Bogdan Pilyugin - * Description: - */ - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_system.h" -#include "esp_event.h" -#include "esp_log.h" -#include "esp_ota_ops.h" -#include "esp_http_client.h" -#include "esp_https_ota.h" -#include -#include "sdkconfig.h" -#include "romfs.h" - -#include -#include -#include "NetTransport.h" - -TaskHandle_t ota_task_handle; -static const char *TAG = "OTAmodule"; -extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start"); -extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end"); - -#define HASH_LEN 32 -//#define CONFIG_FIRMWARE_UPGRADE_URL "https://iotronic.cloud:443/firmware/MStation2.bin" -#define REPORT_PACKETS_EVERY 100 - -esp_err_t _http_event_handler(esp_http_client_event_t *evt) -{ - switch (evt->event_id) - { - case HTTP_EVENT_ERROR: - ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); - break; - case HTTP_EVENT_ON_CONNECTED: - ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); - break; - case HTTP_EVENT_HEADER_SENT: - ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); - break; - case HTTP_EVENT_ON_HEADER: - ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); - break; - case HTTP_EVENT_ON_DATA: - ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); - break; - case HTTP_EVENT_ON_FINISH: - ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); - break; - case HTTP_EVENT_DISCONNECTED: - ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED"); - break; - } - return ESP_OK; -} - -static void print_sha256(const uint8_t *image_hash, const char *label) -{ - char hash_print[HASH_LEN * 2 + 1]; - hash_print[HASH_LEN * 2] = 0; - for (int i = 0; i < HASH_LEN; ++i) - { - sprintf(&hash_print[i * 2], "%02x", image_hash[i]); - } - ESP_LOGI(TAG, "%s %s", label, hash_print); -} - -static int GetBuildNumber(char *version) -{ - char *p = version; - int C = 0, P = 0; - while (*(p++) != 0x00 && ++C < 32) - { - if (*p == '.') - ++P; - if (P == 3) - return atoi(++p); - } - return 0; -} - -esp_err_t my_esp_https_ota(const esp_http_client_config_t *config) -{ - esp_app_desc_t cur_app_info; - esp_app_desc_t new_app_info; - - if (esp_ota_get_partition_description(esp_ota_get_running_partition(), &cur_app_info) == ESP_OK) - { - ESP_LOGI(TAG, "Current firmware"); - ESP_LOGI(TAG, "********************************"); - print_sha256(cur_app_info.app_elf_sha256, "SHA-256 for current firmware: "); - ESP_LOGI(TAG, "IDF ver %s", cur_app_info.idf_ver); - ESP_LOGI(TAG, "Version %s", cur_app_info.version); - ESP_LOGI(TAG, "Build date %s", cur_app_info.date); - ESP_LOGI(TAG, "Build time %s", cur_app_info.time); - ESP_LOGI(TAG, "********************************"); - } - else - return ESP_FAIL; - - if (!config) - { - ESP_LOGE(TAG, "esp_http_client config not found"); - return ESP_ERR_INVALID_ARG; - } - - esp_https_ota_config_t ota_config = { - .http_config = config, - }; - - esp_https_ota_handle_t https_ota_handle = NULL; - esp_err_t err = esp_https_ota_begin(&ota_config, &https_ota_handle); - if (https_ota_handle == NULL) - { - return ESP_FAIL; - } - - int size = esp_https_ota_get_image_size(https_ota_handle); - if (size < 0) - { - return ESP_FAIL; - } - ESP_LOGI(TAG, "Image size %d bytes", size); - - err = esp_https_ota_get_img_desc(https_ota_handle, &new_app_info); - if (err != ESP_OK) - { - return ESP_FAIL; - } - ESP_LOGI(TAG, "********************************"); - ESP_LOGI(TAG, "New firmware"); - print_sha256(new_app_info.app_elf_sha256, "SHA-256 for new firmware: "); - ESP_LOGI(TAG, "IDF ver %s", new_app_info.idf_ver); - ESP_LOGI(TAG, "Version %s", new_app_info.version); - ESP_LOGI(TAG, "Build date %s", new_app_info.date); - ESP_LOGI(TAG, "Build time %s", new_app_info.time); - ESP_LOGI(TAG, "********************************"); - - //Here compare new and old firmware and make decision of update needed - ESP_LOGI(TAG, "Compare versions: current build is %d, update build is :%d", - GetBuildNumber(cur_app_info.version), - GetBuildNumber(new_app_info.version)); - bool need_to_update = GetBuildNumber(new_app_info.version) > GetBuildNumber(cur_app_info.version); - - if (need_to_update) - { - ESP_LOGW(TAG, "New firmware has newer build, START update firmware"); - int countPackets = 0; - while (1) - { - err = esp_https_ota_perform(https_ota_handle); - if (err != ESP_ERR_HTTPS_OTA_IN_PROGRESS) - { - break; - } - if (++countPackets >= REPORT_PACKETS_EVERY) - { - ESP_LOGI(TAG, "Updated %d bytes", esp_https_ota_get_image_len_read(https_ota_handle)); - countPackets = 0; - } - } - - if (err != ESP_OK) - { - esp_https_ota_abort(https_ota_handle); - return err; - } - } - else - { - ESP_LOGI(TAG, "New firmware has NOT newer build, SKIP update firmware"); - } - - esp_err_t ota_finish_err = esp_https_ota_finish(https_ota_handle); - if (ota_finish_err != ESP_OK) - { - return ota_finish_err; - } - if (need_to_update) - { - ESP_LOGI(TAG, "Firmware updated and now restarting..."); - esp_restart(); - } - return ESP_OK; -} - -static void OTATask(void *pvParameter) -{ - - espfs_file_t *file; - struct espfs_stat_t stat; - - //open file - file = espfs_fopen(fs, "res/ca_cert.pem"); - if (!file) - { - ESP_LOGE(TAG, "Failed to read certificate file"); - goto update_error; - } - //get file info - espfs_stat(fs, "res/ca_cert.pem", &stat); - uint32_t fileSize; - fileSize = stat.size; - char *certbuf = (char*) malloc(fileSize); - if (certbuf) - { - espfs_fread(file, certbuf, fileSize); - } - else - { - ESP_LOGE(TAG, "Failed to allocate memory"); - espfs_fclose(file); - goto update_error; - } - - esp_http_client_config_t config = { - .url = GetSysConf()->OTAURL, - .cert_pem = (char*) certbuf, - .event_handler = _http_event_handler, - .keep_alive_enable = true, - .skip_cert_common_name_check = true, - }; - -#ifdef CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK - config.skip_cert_common_name_check = true; -#endif - esp_err_t ret = my_esp_https_ota(&config); - if (ret == ESP_OK) - { - ESP_LOGI(TAG, "Firmware upgrade completed"); - } - else - { - ESP_LOGE(TAG, "Firmware upgrade failed"); - } - free(certbuf); - espfs_fclose(file); - update_error: - - - vTaskDelete(NULL); -} - -/** - * @file - * @brief Start OTA update task - * - * @pre Network is ready - * @post None - * @return ESP_OK on success - * ESP_ERR_NOT_FINISHED on attempt rerun existing thread - */ - -esp_err_t StartOTA(void) -{ - if (xTaskGetHandle("OTATask") != NULL) - { - ESP_LOGW(TAG, "OTA task is already running"); - return ESP_ERR_NOT_FINISHED; - } - ESP_LOGI(TAG, "Starting OTA Task"); - xTaskCreate(OTATask, "OTATask", 1024 * 8, (void*) 0, 3, NULL); - return ESP_OK; -} - - + /* Copyright 2022 Bogdan Pilyugin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * File name: OTA.c + * Project: ChargePointMainboard + * Created on: 2022-07-21 + * Author: Bogdan Pilyugin + * Description: + */ + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_event.h" +#include "esp_log.h" +#include "esp_ota_ops.h" +#include "esp_http_client.h" +#include "esp_https_ota.h" +#include +#include "sdkconfig.h" +#include "romfs.h" + +#include +#include +#include "NetTransport.h" + +TaskHandle_t ota_task_handle; +static const char *TAG = "OTAmodule"; +extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start"); +extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end"); + +char AvailFwVersion[32] = "Unknown"; +char FwUpdStatus[32] = "Updated"; + +#define HASH_LEN 32 +#define REPORT_PACKETS_EVERY 100 + +esp_err_t _http_event_handler(esp_http_client_event_t *evt) +{ + switch (evt->event_id) + { + case HTTP_EVENT_ERROR: + ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); + break; + case HTTP_EVENT_ON_CONNECTED: + ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); + break; + case HTTP_EVENT_HEADER_SENT: + ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); + break; + case HTTP_EVENT_ON_HEADER: + ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); + break; + case HTTP_EVENT_ON_DATA: + ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); + break; + case HTTP_EVENT_ON_FINISH: + ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); + break; + case HTTP_EVENT_DISCONNECTED: + ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED"); + break; + } + return ESP_OK; +} + +static void print_sha256(const uint8_t *image_hash, const char *label) +{ + char hash_print[HASH_LEN * 2 + 1]; + hash_print[HASH_LEN * 2] = 0; + for (int i = 0; i < HASH_LEN; ++i) + { + sprintf(&hash_print[i * 2], "%02x", image_hash[i]); + } + ESP_LOGI(TAG, "%s %s", label, hash_print); +} + +static int GetBuildNumber(char *version) +{ + char *p = version; + int C = 0, P = 0; + while (*(p++) != 0x00 && ++C < 32) + { + if (*p == '.') + ++P; + if (P == 3) + return atoi(++p); + } + return 0; +} + +esp_err_t my_esp_https_ota(const esp_http_client_config_t *config) +{ + esp_app_desc_t cur_app_info; + esp_app_desc_t new_app_info; + + if (esp_ota_get_partition_description(esp_ota_get_running_partition(), &cur_app_info) == ESP_OK) + { + ESP_LOGI(TAG, "Current firmware"); + ESP_LOGI(TAG, "********************************"); + print_sha256(cur_app_info.app_elf_sha256, "SHA-256 for current firmware: "); + ESP_LOGI(TAG, "IDF ver %s", cur_app_info.idf_ver); + ESP_LOGI(TAG, "Version %s", cur_app_info.version); + ESP_LOGI(TAG, "Build date %s", cur_app_info.date); + ESP_LOGI(TAG, "Build time %s", cur_app_info.time); + ESP_LOGI(TAG, "********************************"); + } + else + return ESP_FAIL; + + if (!config) + { + ESP_LOGE(TAG, "esp_http_client config not found"); + return ESP_ERR_INVALID_ARG; + } + + esp_https_ota_config_t ota_config = { + .http_config = config, + }; + + esp_https_ota_handle_t https_ota_handle = NULL; + esp_err_t err = esp_https_ota_begin(&ota_config, &https_ota_handle); + if (https_ota_handle == NULL) + { + return ESP_FAIL; + } + + int size = esp_https_ota_get_image_size(https_ota_handle); + if (size < 0) + { + return ESP_FAIL; + } + ESP_LOGI(TAG, "Image size %d bytes", size); + + err = esp_https_ota_get_img_desc(https_ota_handle, &new_app_info); + if (err != ESP_OK) + { + return ESP_FAIL; + } + ESP_LOGI(TAG, "********************************"); + ESP_LOGI(TAG, "New firmware"); + print_sha256(new_app_info.app_elf_sha256, "SHA-256 for new firmware: "); + ESP_LOGI(TAG, "IDF ver %s", new_app_info.idf_ver); + ESP_LOGI(TAG, "Version %s", new_app_info.version); + ESP_LOGI(TAG, "Build date %s", new_app_info.date); + ESP_LOGI(TAG, "Build time %s", new_app_info.time); + ESP_LOGI(TAG, "********************************"); + + //Here compare new and old firmware and make decision of update needed + strcpy(AvailFwVersion, new_app_info.version); + ESP_LOGI(TAG, "Compare versions: current build is %d, update build is :%d", + GetBuildNumber(cur_app_info.version), + GetBuildNumber(new_app_info.version)); + bool need_to_update = GetBuildNumber(new_app_info.version) > GetBuildNumber(cur_app_info.version); + + if (need_to_update) + { + ESP_LOGW(TAG, "New firmware has newer build, START update firmware"); + int countPackets = 0; + while (1) + { + err = esp_https_ota_perform(https_ota_handle); + if (err != ESP_ERR_HTTPS_OTA_IN_PROGRESS) + { + break; + } + if (++countPackets >= REPORT_PACKETS_EVERY) + { + sprintf(FwUpdStatus, "Updated %d bytes", esp_https_ota_get_image_len_read(https_ota_handle)); + ESP_LOGI(TAG, "%s", FwUpdStatus); + countPackets = 0; + } + } + + if (err != ESP_OK) + { + esp_https_ota_abort(https_ota_handle); + strcpy(FwUpdStatus,"Error update"); + return err; + } + } + else + { + ESP_LOGI(TAG, "New firmware has NOT newer build, SKIP update firmware"); + strcpy(FwUpdStatus,"Updated actual"); + } + + esp_err_t ota_finish_err = esp_https_ota_finish(https_ota_handle); + if (ota_finish_err != ESP_OK) + { + return ota_finish_err; + } + if (need_to_update) + { + ESP_LOGI(TAG, "Firmware updated and now restarting..."); + + esp_restart(); + } + return ESP_OK; +} + +static void OTATask(void *pvParameter) +{ + + espfs_file_t *file; + struct espfs_stat_t stat; + + //open file + file = espfs_fopen(fs, "res/ca_cert.pem"); + if (!file) + { + ESP_LOGE(TAG, "Failed to read certificate file"); + goto update_error; + } + //get file info + espfs_stat(fs, "res/ca_cert.pem", &stat); + uint32_t fileSize; + fileSize = stat.size; + char *certbuf = (char*) malloc(fileSize); + if (certbuf) + { + espfs_fread(file, certbuf, fileSize); + } + else + { + ESP_LOGE(TAG, "Failed to allocate memory"); + espfs_fclose(file); + goto update_error; + } + + esp_http_client_config_t config = { + .url = GetSysConf()->OTAURL, + .cert_pem = (char*) certbuf, + .event_handler = _http_event_handler, + .keep_alive_enable = true, + .skip_cert_common_name_check = true, + }; + +#ifdef CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK + config.skip_cert_common_name_check = true; +#endif + esp_err_t ret = my_esp_https_ota(&config); + if (ret == ESP_OK) + { + ESP_LOGI(TAG, "Firmware upgrade completed"); + } + else + { + ESP_LOGE(TAG, "Firmware upgrade failed"); + } + free(certbuf); + espfs_fclose(file); + update_error: + + + vTaskDelete(NULL); +} + +/** + * @file + * @brief Start OTA update task + * + * @pre Network is ready + * @post None + * @return ESP_OK on success + * ESP_ERR_NOT_FINISHED on attempt rerun existing thread + */ + +esp_err_t StartOTA(void) +{ + if (xTaskGetHandle("OTATask") != NULL) + { + ESP_LOGW(TAG, "OTA task is already running"); + return ESP_ERR_NOT_FINISHED; + } + ESP_LOGI(TAG, "Starting OTA Task"); + xTaskCreate(OTATask, "OTATask", 1024 * 8, (void*) 0, 3, NULL); + return ESP_OK; +} + +char* GetAvailVersion() +{ + return AvailFwVersion; +} +char* GetUpdateStatus() +{ + return FwUpdStatus; +} + diff --git a/src/WebGUIAppMain.c b/src/WebGUIAppMain.c index de18387..ecc8d9a 100644 --- a/src/WebGUIAppMain.c +++ b/src/WebGUIAppMain.c @@ -271,6 +271,19 @@ static void ResetSysConfig(SYS_CONFIG *Conf) sizeof(CONFIG_WEBGUIAPP_USERPASS)); memcpy(Conf->OTAURL, CONFIG_WEBGUIAPP_OTA_HOST, sizeof(CONFIG_WEBGUIAPP_OTA_HOST)); + Conf->OTAAutoInt = CONFIG_WEBGUIAPP_OTA_AUTOUPDATE_PERIOD; + +#if CONFIG_WEBGUIAPP_OTA_AUTOUPDATE_ENABLE + Conf->Flags1.bIsOTAEnabled = true; +#else + Conf->Flags1.bIsOTAEnabled = false; +#endif + +#if CONFIG_WEBGUIAPP_OTA_RESET_ENABLE + Conf->Flags1.bIsResetOTAEnabled = true; +#else + Conf->Flags1.bIsResetOTAEnabled = false; +#endif #if CONFIG_WEBGUIAPP_WIFI_ENABLE Conf->wifiSettings.Flags1.bIsWiFiEnabled = CONFIG_WEBGUIAPP_WIFI_ON;