From 0ab1cd438b85b2d0bfd8dc99df8a87a08c00a80b Mon Sep 17 00:00:00 2001 From: Sebastien Date: Sun, 29 Sep 2019 21:12:02 -0400 Subject: [PATCH] Full OTA refactor and other stability improvement --- components/cmd_system/cmd_system.c | 48 ++-- components/cmd_system/cmd_system.h | 4 +- components/squeezelite-ota/cmd_ota.c | 8 +- components/squeezelite-ota/squeezelite-ota.c | 230 +++++++------------ components/squeezelite-ota/squeezelite-ota.h | 17 +- components/wifi-manager/dns_server.c | 6 +- components/wifi-manager/dns_server.h | 8 +- components/wifi-manager/http_server.c | 22 +- components/wifi-manager/http_server.h | 10 +- components/wifi-manager/wifi_manager.c | 63 +++-- components/wifi-manager/wifi_manager.h | 64 +++--- main/console.c | 116 +++------- main/esp_app_main.c | 59 ++++- main/nvs_utilities.c | 2 +- 14 files changed, 305 insertions(+), 352 deletions(-) diff --git a/components/cmd_system/cmd_system.c b/components/cmd_system/cmd_system.c index a8816e9e..e7f6362b 100644 --- a/components/cmd_system/cmd_system.c +++ b/components/cmd_system/cmd_system.c @@ -101,24 +101,46 @@ static int restart(int argc, char **argv) ESP_LOGI(TAG, "Restarting"); esp_restart(); } -void guided_factory() +esp_err_t guided_factory() { - ESP_LOGI(TAG, "Rebooting to factory."); - +#if RECOVERY_APPLICATION + ESP_LOGW(TAG,"RECOVERY application is already active"); + return ESP_OK; +#else + bool bFound=false; + ESP_LOGI(TAG, "Looking for recovery partition."); const esp_partition_t *partition; - esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, "factory"); - partition = (esp_partition_t *) esp_partition_get(it); - if(partition != NULL){ - esp_ota_set_boot_partition(partition); - } - esp_partition_iterator_release(it); - esp_restart(); + esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); + if(it == NULL){ + ESP_LOGE(TAG,"Unable initialize partition iterator!"); + } + else + { + partition = (esp_partition_t *) esp_partition_get(it); + + if(partition != NULL){ + ESP_LOGI(TAG, "Found recovery partition."); + esp_ota_set_boot_partition(partition); + bFound=true; + } + else + { + ESP_LOGE(TAG,"Recovery partition not found! Unable to reboot to recovery."); + } + esp_partition_iterator_release(it); + if(bFound) { + ESP_LOGI(TAG, "Restarting!."); + esp_restart(); + } + } +#endif + return ESP_OK; } static int restart_factory(int argc, char **argv) { guided_factory(); - return 1; + return 0; // return fail. This should never return... we're rebooting! } static void register_restart() { @@ -134,8 +156,8 @@ static void register_restart() static void register_factory_boot() { const esp_console_cmd_t cmd = { - .command = "factory", - .help = "Resets and boot to factory (if available)", + .command = "recovery", + .help = "Resets and boot to recovery (if available)", .hint = NULL, .func = &restart_factory, }; diff --git a/components/cmd_system/cmd_system.h b/components/cmd_system/cmd_system.h index 6f4fc906..ccfb06de 100644 --- a/components/cmd_system/cmd_system.h +++ b/components/cmd_system/cmd_system.h @@ -7,14 +7,14 @@ CONDITIONS OF ANY KIND, either express or implied. */ #pragma once - +#include "esp_system.h" #ifdef __cplusplus extern "C" { #endif // Register system functions void register_system(); -void guided_factory(); +esp_err_t guided_factory(); #ifdef __cplusplus } diff --git a/components/squeezelite-ota/cmd_ota.c b/components/squeezelite-ota/cmd_ota.c index 527e37e2..bd517d34 100644 --- a/components/squeezelite-ota/cmd_ota.c +++ b/components/squeezelite-ota/cmd_ota.c @@ -7,7 +7,7 @@ CONDITIONS OF ANY KIND, either express or implied. */ -#include "../squeezelite-ota/cmd_ota.h" +#include "cmd_ota.h" #include #include @@ -27,7 +27,7 @@ #include "sdkconfig.h" static const char * TAG = "platform_esp32"; -extern void start_ota(const char * bin_url); +extern esp_err_t start_ota(const char * bin_url, bool bFromAppMain); static struct { struct arg_str *url; struct arg_end *end; @@ -45,9 +45,7 @@ static int perform_ota_update(int argc, char **argv) esp_err_t err=ESP_OK; ESP_LOGI(TAG, "Starting ota: %s", url); - start_ota(url); - - + start_ota(url,false); if (err != ESP_OK) { ESP_LOGE(TAG, "%s", esp_err_to_name(err)); diff --git a/components/squeezelite-ota/squeezelite-ota.c b/components/squeezelite-ota/squeezelite-ota.c index ae0d52e9..fa4ff944 100644 --- a/components/squeezelite-ota/squeezelite-ota.c +++ b/components/squeezelite-ota/squeezelite-ota.c @@ -21,7 +21,9 @@ #include "esp_err.h" #include "tcpip_adapter.h" #include "squeezelite-ota.h" - +#include +#include +#include static const char *TAG = "squeezelite-ota"; extern const uint8_t server_cert_pem_start[] asm("_binary_github_pem_start"); @@ -37,15 +39,33 @@ static struct { bool bRedirectFound; bool bOTAStarted; bool bInitialized; -} ota_status; -uint8_t lastpct=0; -uint8_t newpct=0; + uint8_t lastpct; + uint8_t newpct; + struct timeval OTA_start; + bool bOTAThreadStarted; -static esp_http_client_config_t config; +} ota_status; +struct timeval tv; static esp_http_client_config_t ota_config; -static esp_http_client_handle_t client; -extern void wifi_manager_refresh_ota_json(); -const char * ota_get_status(){ + +extern void CODE_RAM_LOCATION wifi_manager_refresh_ota_json(); + +void CODE_RAM_LOCATION _printMemStats(){ + ESP_LOGI(TAG,"Heap internal:%zu (min:%zu) external:%zu (min:%zu)\n", + heap_caps_get_free_size(MALLOC_CAP_INTERNAL), + heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), + heap_caps_get_free_size(MALLOC_CAP_SPIRAM), + heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM)); +} +void triggerStatusJsonRefresh(const char * status, ...){ + va_list args; + va_start(args, status); + snprintf(ota_status.status_text,sizeof(ota_status.status_text)-1,status, args); + va_end(args); + _printMemStats(); + wifi_manager_refresh_ota_json(); +} +const char * CODE_RAM_LOCATION ota_get_status(){ if(!ota_status.bInitialized) { memset(ota_status.status_text, 0x00,sizeof(ota_status.status_text)); @@ -53,7 +73,7 @@ const char * ota_get_status(){ } return ota_status.status_text; } -uint8_t ota_get_pct_complete(){ +uint8_t CODE_RAM_LOCATION ota_get_pct_complete(){ return ota_status.ota_total_len==0?0: (uint8_t)((float)ota_status.ota_actual_len/(float)ota_status.ota_total_len*100.0f); } @@ -68,7 +88,7 @@ static void __attribute__((noreturn)) task_fatal_error(void) } } #define FREE_RESET(p) if(p!=NULL) { free(p); p=NULL; } -esp_err_t _http_event_handler(esp_http_client_event_t *evt) +esp_err_t CODE_RAM_LOCATION _http_event_handler(esp_http_client_event_t *evt) { // -------------- // Received parameters @@ -88,21 +108,19 @@ 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"); + _printMemStats(); //strncpy(ota_status,"HTTP_EVENT_ERROR",sizeof(ota_status)-1); break; case HTTP_EVENT_ON_CONNECTED: ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); - if(ota_status.bOTAStarted) snprintf(ota_status.status_text,sizeof(ota_status.status_text)-1,"Installing..."); - wifi_manager_refresh_ota_json(); - ota_status.ota_total_len=0; + + if(ota_status.bOTAStarted) triggerStatusJsonRefresh("Installing..."); + ota_status.ota_total_len=0; ota_status.ota_actual_len=0; - lastpct=0; - newpct=0; - ESP_LOGD(TAG,"Heap internal:%zu (min:%zu) external:%zu (min:%zu)\n", - heap_caps_get_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_free_size(MALLOC_CAP_SPIRAM), - heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM)); + ota_status.lastpct=0; + ota_status.newpct=0; + gettimeofday(&ota_status.OTA_start, NULL); + break; case HTTP_EVENT_HEADER_SENT: ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); @@ -121,18 +139,23 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt) } break; case HTTP_EVENT_ON_DATA: + vTaskDelay(5/ portTICK_RATE_MS); if(!ota_status.bOTAStarted) { ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, status_code=%d, len=%d",esp_http_client_get_status_code(evt->client), evt->data_len); } else if(ota_status.bOTAStarted && esp_http_client_get_status_code(evt->client) == 200 ){ ota_status.ota_actual_len+=evt->data_len; - if(ota_get_pct_complete()%2 == 0) newpct = ota_get_pct_complete(); - if(lastpct!=newpct ) + if(ota_get_pct_complete()%2 == 0) ota_status.newpct = ota_get_pct_complete(); + if(ota_status.lastpct!=ota_status.newpct ) { + gettimeofday(&tv, NULL); + + uint32_t elapsed_ms= (tv.tv_sec-ota_status.OTA_start.tv_sec )*1000+(tv.tv_usec-ota_status.OTA_start.tv_usec)/1000; + wifi_manager_refresh_ota_json(); - lastpct=newpct; - ESP_LOGI(TAG,"Receiving OTA data chunk len: %d, %d of %d (%d pct)", evt->data_len, ota_status.ota_actual_len, ota_status.ota_total_len, newpct); + ota_status.lastpct=ota_status.newpct; + ESP_LOGI(TAG,"OTA chunk : %d bytes (%d of %d) (%d pct), %d KB/s", evt->data_len, ota_status.ota_actual_len, ota_status.ota_total_len, ota_status.newpct, elapsed_ms>0?ota_status.ota_actual_len*1000/elapsed_ms/1024:0); ESP_LOGD(TAG,"Heap internal:%zu (min:%zu) external:%zu (min:%zu)\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL), heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), @@ -156,35 +179,11 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt) return ESP_OK; } -static void check_http_redirect(void) -{ - esp_err_t err=ESP_OK; - ESP_LOGD(TAG, "Checking for http redirects. initializing http client"); - client = esp_http_client_init(&config); - if (client == NULL) { - ESP_LOGE(TAG, "Failed to initialise HTTP connection"); - task_fatal_error(); - } - ESP_LOGD(TAG, "opening http connection"); - err = esp_http_client_open(client, 0); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err)); - esp_http_client_cleanup(client); - task_fatal_error(); - } - ESP_LOGD(TAG, "fetching headers"); - esp_http_client_fetch_headers(client); - if (err == ESP_OK) { - ESP_LOGI(TAG, "redirect check retrieved headers"); - } else { - ESP_LOGE(TAG, "redirect check returned %s", esp_err_to_name(err)); - } -} -esp_err_t init_config(esp_http_client_config_t * conf, const char * url){ +esp_err_t CODE_RAM_LOCATION init_config(esp_http_client_config_t * conf, const char * url){ memset(conf, 0x00, sizeof(esp_http_client_config_t)); conf->cert_pem = (char *)server_cert_pem_start; conf->event_handler = _http_event_handler; - conf->buffer_size = 2048; + conf->buffer_size = 1024*2; conf->disable_auto_redirect=true; conf->skip_cert_common_name_check = false; conf->url = strdup(url); @@ -192,14 +191,13 @@ esp_err_t init_config(esp_http_client_config_t * conf, const char * url){ return ESP_OK; } -void ota_task(void *pvParameter) +void CODE_RAM_LOCATION ota_task(void *pvParameter) { char * passedURL=(char *)pvParameter; - memset(&ota_status, 0x00, sizeof(ota_status)); + ota_status.bInitialized = true; ESP_LOGD(TAG, "HTTP ota Thread started"); - snprintf(ota_status.status_text,sizeof(ota_status.status_text)-1,"Initializing..."); - wifi_manager_refresh_ota_json(); + triggerStatusJsonRefresh("Initializing..."); ota_status.bRedirectFound=false; if(passedURL==NULL || strlen(passedURL)==0){ ESP_LOGE(TAG,"HTTP OTA called without a url"); @@ -207,32 +205,17 @@ void ota_task(void *pvParameter) return ; } ota_status.current_url= strdup(passedURL); -// init_config(&config,ota_status.current_url); - FREE_RESET(pvParameter); -// -// snprintf(ota_status.status_text,sizeof(ota_status.status_text)-1,"Checking for redirect..."); -// wifi_manager_refresh_ota_json(); -// check_http_redirect(); -// if(ota_status.bRedirectFound && ota_status.redirected_url== NULL){ -// // OTA Failed miserably. Errors would have been logged somewhere -// ESP_LOGE(TAG,"Redirect check failed to identify target URL. Bailing out"); -// vTaskDelete(NULL); -// } ESP_LOGD(TAG,"Calling esp_https_ota"); init_config(&ota_config,ota_status.bRedirectFound?ota_status.redirected_url:ota_status.current_url); ota_status.bOTAStarted = true; - snprintf(ota_status.status_text,sizeof(ota_status.status_text)-1,"Starting OTA..."); - wifi_manager_refresh_ota_json(); - // pause to let the system catch up - vTaskDelay(500/ portTICK_RATE_MS); + triggerStatusJsonRefresh("Starting OTA..."); esp_err_t err = esp_https_ota(&ota_config); if (err == ESP_OK) { - snprintf(ota_status.status_text,sizeof(ota_status.status_text)-1,"Success!"); - wifi_manager_refresh_ota_json(); + triggerStatusJsonRefresh("Success!"); esp_restart(); } else { - snprintf(ota_status.status_text,sizeof(ota_status.status_text)-1,"Error: %s",esp_err_to_name(err)); + triggerStatusJsonRefresh("Error: %s",esp_err_to_name(err)); wifi_manager_refresh_ota_json(); ESP_LOGE(TAG, "Firmware upgrade failed with error : %s", esp_err_to_name(err)); } @@ -242,97 +225,60 @@ void ota_task(void *pvParameter) vTaskDelete(NULL); } -void start_ota(const char * bin_url) -{ - ESP_LOGW(TAG, "Called to update the firmware from url: %s",bin_url); +esp_err_t process_recovery_ota(const char * bin_url){ #if RECOVERY_APPLICATION // Initialize NVS. int ret=0; - esp_err_t err = nvs_flash_init(); + nvs_handle nvs; + esp_err_t err = nvs_flash_init(); + + if(ota_status.bOTAThreadStarted){ + ESP_LOGE(TAG,"OTA Already started. "); + return ESP_FAIL; + } + memset(&ota_status, 0x00, sizeof(ota_status)); + ota_status.bOTAThreadStarted=true; if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { // todo: If we ever change the size of the nvs partition, we need to figure out a mechanism to enlarge the nvs. // 1.OTA app partition table has a smaller NVS partition size than the non-OTA // partition table. This size mismatch may cause NVS initialization to fail. // 2.NVS partition contains data in new format and cannot be recognized by this version of code. // If this happens, we erase NVS partition and initialize NVS again. - ESP_ERROR_CHECK(nvs_flash_erase()); + ESP_LOGW(TAG,"NVS flash size has changed. Formatting nvs"); + ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } ESP_ERROR_CHECK(err); - char * urlPtr=malloc((strlen(bin_url)+1)*sizeof(char)); - strcpy(urlPtr,bin_url); + char * urlPtr=strdup(bin_url); // the first thing we need to do here is to erase the firmware url // to avoid a boot loop - nvs_handle nvs; - err = nvs_open(current_namespace, NVS_READWRITE, &nvs); - if (err == ESP_OK) { - err = nvs_erase_key(nvs, "fwurl"); - if (err == ESP_OK) { - err = nvs_commit(nvs); - if (err == ESP_OK) { - ESP_LOGI(TAG, "Value with key '%s' erased", "fwurl"); - } - } - nvs_close(nvs); - } - ESP_LOGI(TAG, "Waiting for other processes to start"); - for(int i=0;i<10;i++){ - vTaskDelay(1000/ portTICK_RATE_MS); - } + #ifdef CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 #define OTA_CORE 0 -#warning "Wifi running on core 1" +#warning "OTA will run on core 0" #else +#warning "OTA will run on core 1" #define OTA_CORE 1 - #endif - ESP_LOGI(TAG, "Starting ota: %s", urlPtr); - ret=xTaskCreatePinnedToCore(&ota_task, "ota_task", 1024*40, (void *)urlPtr, tskIDLE_PRIORITY+3, NULL, OTA_CORE); - +#endif + ESP_LOGI(TAG, "Starting ota on core %u for : %s", OTA_CORE,urlPtr); + ret=xTaskCreatePinnedToCore(&ota_task, "ota_task", 1024*40, (void *)urlPtr, ESP_TASK_MAIN_PRIO+3, NULL, OTA_CORE); if (ret != pdPASS) { ESP_LOGI(TAG, "create thread %s failed", "ota_task"); - } -#else - ESP_LOGW(TAG, "Rebooting to recovery to complete the installation"); - guided_factory(); + return ESP_FAIL; + } #endif - + return ESP_OK; } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +esp_err_t start_ota(const char * bin_url, bool bFromAppMain) +{ +#if RECOVERY_APPLICATION + return process_recovery_ota(bin_url); +#else + ESP_LOGW(TAG, "Called to update the firmware from url: %s",bin_url); + ESP_LOGW(TAG, "Rebooting to recovery to complete the installation"); + return guided_factory(); + return ESP_OK; +#endif +} diff --git a/components/squeezelite-ota/squeezelite-ota.h b/components/squeezelite-ota/squeezelite-ota.h index 0c195368..c880b29f 100644 --- a/components/squeezelite-ota/squeezelite-ota.h +++ b/components/squeezelite-ota/squeezelite-ota.h @@ -5,13 +5,16 @@ * Author: sle11 */ -#ifndef COMPONENTS_SQUEEZELITE_OTA_SQUEEZELITE_OTA_H_ -#define COMPONENTS_SQUEEZELITE_OTA_SQUEEZELITE_OTA_H_ +#pragma once +#include "esp_attr.h" +#if RECOVERY_APPLICATION +#define CODE_RAM_LOCATION IRAM_ATTR +#else +#define CODE_RAM_LOCATION +#endif -void start_ota(const char * bin_url); -const char * ota_get_status(); -uint8_t ota_get_pct_complete(); +esp_err_t CODE_RAM_LOCATION start_ota(const char * bin_url, bool bFromAppMain); +const char * CODE_RAM_LOCATION ota_get_status(); +uint8_t CODE_RAM_LOCATION ota_get_pct_complete(); - -#endif /* COMPONENTS_SQUEEZELITE_OTA_SQUEEZELITE_OTA_H_ */ diff --git a/components/wifi-manager/dns_server.c b/components/wifi-manager/dns_server.c index c336290d..c231b701 100644 --- a/components/wifi-manager/dns_server.c +++ b/components/wifi-manager/dns_server.c @@ -59,11 +59,11 @@ static const char TAG[] = "dns_server"; static TaskHandle_t task_dns_server = NULL; int socket_fd; -void dns_server_start() { +void CODE_RAM_LOCATION dns_server_start() { xTaskCreate(&dns_server, "dns_server", 3072, NULL, WIFI_MANAGER_TASK_PRIORITY-1, &task_dns_server); } -void dns_server_stop(){ +void CODE_RAM_LOCATION dns_server_stop(){ if(task_dns_server){ vTaskDelete(task_dns_server); close(socket_fd); @@ -74,7 +74,7 @@ void dns_server_stop(){ -void dns_server(void *pvParameters) { +void CODE_RAM_LOCATION dns_server(void *pvParameters) { diff --git a/components/wifi-manager/dns_server.h b/components/wifi-manager/dns_server.h index 48075699..62548be1 100644 --- a/components/wifi-manager/dns_server.h +++ b/components/wifi-manager/dns_server.h @@ -34,7 +34,7 @@ Contains the freeRTOS task for the DNS server that processes the requests. #define MAIN_DNS_SERVER_H_ #include #include - +#include "squeezelite-ota.h" #ifdef __cplusplus extern "C" { @@ -126,9 +126,9 @@ typedef struct __attribute__((__packed__)) dns_answer_t{ uint32_t RDATA; /* For the sake of simplicity only ipv4 is supported, and as such it's a unsigned 32 bit */ }dns_answer_t; -void dns_server(void *pvParameters); -void dns_server_start(); -void dns_server_stop(); +void CODE_RAM_LOCATION dns_server(void *pvParameters); +void CODE_RAM_LOCATION dns_server_start(); +void CODE_RAM_LOCATION dns_server_stop(); diff --git a/components/wifi-manager/http_server.c b/components/wifi-manager/http_server.c index 96d8d732..a0a4803b 100644 --- a/components/wifi-manager/http_server.c +++ b/components/wifi-manager/http_server.c @@ -33,6 +33,7 @@ function to process requests, decode URLs, serve files, etc. etc. #include "http_server.h" #include "cmd_system.h" +#include "../squeezelite-ota/squeezelite-ota.h" #define NVS_PARTITION_NAME "nvs" @@ -48,7 +49,6 @@ static char *r = "\\\""; static TaskHandle_t task_http_server = NULL; extern char current_namespace[]; -extern void start_ota(const char * bin_url); /** * @brief embedded binary data. * @see file "component.mk" @@ -86,14 +86,14 @@ const static char http_redirect_hdr_end[] = "/\n\n"; -void http_server_start(){ +void CODE_RAM_LOCATION http_server_start(){ if(task_http_server == NULL){ xTaskCreate(&http_server, "http_server", 1024*5, NULL, WIFI_MANAGER_TASK_PRIORITY-1, &task_http_server); } } -void http_server(void *pvParameters) { +void CODE_RAM_LOCATION http_server(void *pvParameters) { struct netconn *conn, *newconn; err_t err; @@ -121,7 +121,7 @@ void http_server(void *pvParameters) { } -char* http_server_get_header(char *request, char *header_name, int *len) { +char* CODE_RAM_LOCATION http_server_get_header(char *request, char *header_name, int *len) { *len = 0; char *ret = NULL; char *ptr = NULL; @@ -138,7 +138,7 @@ char* http_server_get_header(char *request, char *header_name, int *len) { } return NULL; } -char* http_server_search_header(char *request, char *header_name, int *len, char ** parm_name, char ** next_position, char * bufEnd) { +char* CODE_RAM_LOCATION http_server_search_header(char *request, char *header_name, int *len, char ** parm_name, char ** next_position, char * bufEnd) { *len = 0; char *ret = NULL; char *ptr = NULL; @@ -191,7 +191,7 @@ char* http_server_search_header(char *request, char *header_name, int *len, char ESP_LOGD(TAG, "No more match for : %s", header_name); return NULL; } -void http_server_send_resource_file(struct netconn *conn,const uint8_t * start, const uint8_t * end, char * content_type,char * encoding){ +void CODE_RAM_LOCATION http_server_send_resource_file(struct netconn *conn,const uint8_t * start, const uint8_t * end, char * content_type,char * encoding){ uint16_t len=end - start; size_t buff_length= sizeof(http_hdr_template)+strlen(content_type)+strlen(encoding); char * http_hdr=malloc(buff_length); @@ -210,7 +210,7 @@ void http_server_send_resource_file(struct netconn *conn,const uint8_t * start, } } -void http_server_netconn_serve(struct netconn *conn) { +void CODE_RAM_LOCATION http_server_netconn_serve(struct netconn *conn) { struct netbuf *inbuf; char *buf = NULL; @@ -395,10 +395,10 @@ void http_server_netconn_serve(struct netconn *conn) { netconn_write(conn, http_400_hdr, sizeof(http_400_hdr) - 1, NETCONN_NOCOPY); //400 invalid request } else{ - netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); //200ok if(bOTA){ - ESP_LOGI(TAG, "Initiating OTA for url %s",otaURL); - start_ota(otaURL); + ESP_LOGI(TAG, "Restarting to process OTA for url %s",otaURL); + netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); //200ok + esp_restart(); } } @@ -475,7 +475,7 @@ void http_server_netconn_serve(struct netconn *conn) { netbuf_delete(inbuf); } -void strreplace(char *src, char *str, char *rep) +void CODE_RAM_LOCATION strreplace(char *src, char *str, char *rep) { char *p = strstr(src, str); if (p) diff --git a/components/wifi-manager/http_server.h b/components/wifi-manager/http_server.h index ec9afb97..556d97f9 100644 --- a/components/wifi-manager/http_server.h +++ b/components/wifi-manager/http_server.h @@ -67,13 +67,13 @@ extern "C" { * @brief RTOS task for the HTTP server. Do not start manually. * @see void http_server_start() */ -void http_server(void *pvParameters); +void CODE_RAM_LOCATION http_server(void *pvParameters); /* @brief helper function that processes one HTTP request at a time */ -void http_server_netconn_serve(struct netconn *conn); +void CODE_RAM_LOCATION http_server_netconn_serve(struct netconn *conn); /* @brief create the task for the http server */ -void http_server_start(); +void CODE_RAM_LOCATION http_server_start(); /** * @brief gets a char* pointer to the first occurence of header_name withing the complete http request request. @@ -86,9 +86,9 @@ void http_server_start(); * @param len the size of the header value if found. * @return pointer to the beginning of the header value. */ -char* http_server_get_header(char *request, char *header_name, int *len); +char* CODE_RAM_LOCATION http_server_get_header(char *request, char *header_name, int *len); -void strreplace(char *src, char *str, char *rep); +void CODE_RAM_LOCATION strreplace(char *src, char *str, char *rep); #ifdef __cplusplus diff --git a/components/wifi-manager/wifi_manager.c b/components/wifi-manager/wifi_manager.c index 133644b1..78182785 100644 --- a/components/wifi-manager/wifi_manager.c +++ b/components/wifi-manager/wifi_manager.c @@ -56,7 +56,6 @@ Contains the freeRTOS task and all necessary support #include "lwip/ip4_addr.h" #include "esp_ota_ops.h" #include "esp_app_format.h" -#include "squeezelite-ota.h" #ifndef SQUEEZELITE_ESP32_RELEASE_URL #define SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases" @@ -131,21 +130,21 @@ const int WIFI_MANAGER_SCAN_BIT = BIT7; const int WIFI_MANAGER_REQUEST_DISCONNECT_BIT = BIT8; -void wifi_manager_refresh_ota_json(){ +void CODE_RAM_LOCATION wifi_manager_refresh_ota_json(){ wifi_manager_send_message(EVENT_REFRESH_OTA, NULL); } -void wifi_manager_scan_async(){ +void CODE_RAM_LOCATION wifi_manager_scan_async(){ wifi_manager_send_message(ORDER_START_WIFI_SCAN, NULL); } -void wifi_manager_disconnect_async(){ +void CODE_RAM_LOCATION wifi_manager_disconnect_async(){ wifi_manager_send_message(ORDER_DISCONNECT_STA, NULL); //xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT); TODO: delete } -void wifi_manager_start(){ +void CODE_RAM_LOCATION wifi_manager_start(){ /* disable the default wifi logging */ esp_log_level_set("wifi", ESP_LOG_NONE); @@ -176,7 +175,7 @@ void wifi_manager_start(){ xTaskCreate(&wifi_manager, "wifi_manager", 4096, NULL, WIFI_MANAGER_TASK_PRIORITY, &task_wifi_manager); } -uint8_t wifi_manager_get_flag(){ +uint8_t CODE_RAM_LOCATION wifi_manager_get_flag(){ uint8_t value=0; nvs_handle handle; esp_err_t esp_err; @@ -191,7 +190,7 @@ uint8_t wifi_manager_get_flag(){ } -char * wifi_manager_alloc_get_config(char * name, size_t * l){ +char * CODE_RAM_LOCATION wifi_manager_alloc_get_config(char * name, size_t * l){ size_t len=0; char * value=NULL; @@ -224,7 +223,7 @@ char * wifi_manager_alloc_get_config(char * name, size_t * l){ } -esp_err_t wifi_manager_save_autoexec_flag(uint8_t flag){ +esp_err_t CODE_RAM_LOCATION wifi_manager_save_autoexec_flag(uint8_t flag){ nvs_handle handle; esp_err_t esp_err; ESP_LOGI(TAG, "About to save autoexec flag to flash"); @@ -257,7 +256,7 @@ esp_err_t wifi_manager_save_autoexec_flag(uint8_t flag){ return ESP_OK; } -esp_err_t wifi_manager_save_autoexec_config(char * value, char * name, int len){ +esp_err_t CODE_RAM_LOCATION wifi_manager_save_autoexec_config(char * value, char * name, int len){ nvs_handle handle; esp_err_t esp_err; ESP_LOGI(TAG, "About to save config to flash. Name: %s, value: %s", name,value); @@ -290,7 +289,7 @@ esp_err_t wifi_manager_save_autoexec_config(char * value, char * name, int len){ } -esp_err_t wifi_manager_save_sta_config(){ +esp_err_t CODE_RAM_LOCATION wifi_manager_save_sta_config(){ nvs_handle handle; esp_err_t esp_err; ESP_LOGI(TAG, "About to save config to flash"); @@ -332,7 +331,7 @@ esp_err_t wifi_manager_save_sta_config(){ return ESP_OK; } -bool wifi_manager_fetch_wifi_sta_config(){ +bool CODE_RAM_LOCATION wifi_manager_fetch_wifi_sta_config(){ nvs_handle handle; esp_err_t esp_err; @@ -409,12 +408,12 @@ bool wifi_manager_fetch_wifi_sta_config(){ } -void wifi_manager_clear_ip_info_json(){ +void CODE_RAM_LOCATION wifi_manager_clear_ip_info_json(){ strcpy(ip_info_json, "{}\n"); } -void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code){ +void CODE_RAM_LOCATION wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code){ wifi_config_t *config = wifi_manager_get_wifi_sta_config(); if(update_reason_code == UPDATE_OTA) { update_reason_code = last_update_reason_code; @@ -498,11 +497,11 @@ void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code) } -void wifi_manager_clear_access_points_json(){ +void CODE_RAM_LOCATION wifi_manager_clear_access_points_json(){ strcpy(accessp_json, "[]\n"); } -void wifi_manager_generate_acess_points_json(){ +void CODE_RAM_LOCATION wifi_manager_generate_acess_points_json(){ strcpy(accessp_json, "["); @@ -531,7 +530,7 @@ void wifi_manager_generate_acess_points_json(){ } -bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait){ +bool CODE_RAM_LOCATION wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait){ if(wifi_manager_sta_ip_mutex){ if( xSemaphoreTake( wifi_manager_sta_ip_mutex, xTicksToWait ) == pdTRUE ) { return true; @@ -546,11 +545,11 @@ bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait){ } -void wifi_manager_unlock_sta_ip_string(){ +void CODE_RAM_LOCATION wifi_manager_unlock_sta_ip_string(){ xSemaphoreGive( wifi_manager_sta_ip_mutex ); } -void wifi_manager_safe_update_sta_ip_string(uint32_t ip){ +void CODE_RAM_LOCATION wifi_manager_safe_update_sta_ip_string(uint32_t ip){ if(wifi_manager_lock_sta_ip_string(portMAX_DELAY)){ struct ip4_addr ip4; @@ -566,11 +565,11 @@ void wifi_manager_safe_update_sta_ip_string(uint32_t ip){ } } -char* wifi_manager_get_sta_ip_string(){ +char* CODE_RAM_LOCATION wifi_manager_get_sta_ip_string(){ return wifi_manager_sta_ip; } -bool wifi_manager_lock_json_buffer(TickType_t xTicksToWait){ +bool CODE_RAM_LOCATION wifi_manager_lock_json_buffer(TickType_t xTicksToWait){ if(wifi_manager_json_mutex){ if( xSemaphoreTake( wifi_manager_json_mutex, xTicksToWait ) == pdTRUE ) { return true; @@ -585,15 +584,15 @@ bool wifi_manager_lock_json_buffer(TickType_t xTicksToWait){ } -void wifi_manager_unlock_json_buffer(){ +void CODE_RAM_LOCATION wifi_manager_unlock_json_buffer(){ xSemaphoreGive( wifi_manager_json_mutex ); } -char* wifi_manager_get_ap_list_json(){ +char* CODE_RAM_LOCATION wifi_manager_get_ap_list_json(){ return accessp_json; } -esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event) +esp_err_t CODE_RAM_LOCATION wifi_manager_event_handler(void *ctx, system_event_t *event) { switch(event->event_id) { @@ -667,11 +666,11 @@ esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event) return ESP_OK; } -wifi_config_t* wifi_manager_get_wifi_sta_config(){ +wifi_config_t* CODE_RAM_LOCATION wifi_manager_get_wifi_sta_config(){ return wifi_manager_config_sta; } -void wifi_manager_connect_async(){ +void CODE_RAM_LOCATION wifi_manager_connect_async(){ /* in order to avoid a false positive on the front end app we need to quickly flush the ip json * There'se a risk the front end sees an IP or a password error when in fact * it's a remnant from a previous connection @@ -684,11 +683,11 @@ void wifi_manager_connect_async(){ } -char* wifi_manager_get_ip_info_json(){ +char* CODE_RAM_LOCATION wifi_manager_get_ip_info_json(){ return ip_info_json; } -void wifi_manager_destroy(){ +void CODE_RAM_LOCATION wifi_manager_destroy(){ vTaskDelete(task_wifi_manager); task_wifi_manager = NULL; @@ -717,7 +716,7 @@ void wifi_manager_destroy(){ wifi_manager_queue = NULL; } -void wifi_manager_filter_unique( wifi_ap_record_t * aplist, uint16_t * aps) { +void CODE_RAM_LOCATION wifi_manager_filter_unique( wifi_ap_record_t * aplist, uint16_t * aps) { int total_unique; wifi_ap_record_t * first_free; total_unique=*aps; @@ -768,27 +767,27 @@ void wifi_manager_filter_unique( wifi_ap_record_t * aplist, uint16_t * aps) { *aps = total_unique; } -BaseType_t wifi_manager_send_message_to_front(message_code_t code, void *param){ +BaseType_t CODE_RAM_LOCATION wifi_manager_send_message_to_front(message_code_t code, void *param){ queue_message msg; msg.code = code; msg.param = param; return xQueueSendToFront( wifi_manager_queue, &msg, portMAX_DELAY); } -BaseType_t wifi_manager_send_message(message_code_t code, void *param){ +BaseType_t CODE_RAM_LOCATION wifi_manager_send_message(message_code_t code, void *param){ queue_message msg; msg.code = code; msg.param = param; return xQueueSend( wifi_manager_queue, &msg, portMAX_DELAY); } -void wifi_manager_set_callback(message_code_t message_code, void (*func_ptr)(void*) ){ +void CODE_RAM_LOCATION wifi_manager_set_callback(message_code_t message_code, void (*func_ptr)(void*) ){ if(cb_ptr_arr && message_code < MESSAGE_CODE_COUNT){ cb_ptr_arr[message_code] = func_ptr; } } -void wifi_manager( void * pvParameters ){ +void CODE_RAM_LOCATION wifi_manager( void * pvParameters ){ queue_message msg; BaseType_t xStatus; EventBits_t uxBits; diff --git a/components/wifi-manager/wifi_manager.h b/components/wifi-manager/wifi_manager.h index f989987c..18d6f00f 100644 --- a/components/wifi-manager/wifi_manager.h +++ b/components/wifi-manager/wifi_manager.h @@ -39,13 +39,13 @@ extern "C" { #include "esp_system.h" #include "esp_wifi.h" #include "esp_wifi_types.h" +#include "squeezelite-ota.h" #ifndef RECOVERY_APPLICATION #error "RECOVERY_APPLICATION not defined. Defaulting to squeezelite" #endif #if RECOVERY_APPLICATION==1 -#warning "compiling for recovery." #elif RECOVERY_APPLICATION==0 #warning "compiling for squeezelite." #else @@ -268,71 +268,71 @@ typedef struct{ /** * Allocate heap memory for the wifi manager and start the wifi_manager RTOS task */ -void wifi_manager_start(); +void CODE_RAM_LOCATION wifi_manager_start(); /** * Frees up all memory allocated by the wifi_manager and kill the task. */ -void wifi_manager_destroy(); +void CODE_RAM_LOCATION wifi_manager_destroy(); /** * Filters the AP scan list to unique SSIDs */ -void filter_unique( wifi_ap_record_t * aplist, uint16_t * ap_num); +void CODE_RAM_LOCATION filter_unique( wifi_ap_record_t * aplist, uint16_t * ap_num); /** * Main task for the wifi_manager */ -void wifi_manager( void * pvParameters ); +void CODE_RAM_LOCATION wifi_manager( void * pvParameters ); -char* wifi_manager_get_ap_list_json(); -char* wifi_manager_get_ip_info_json(); +char* CODE_RAM_LOCATION wifi_manager_get_ap_list_json(); +char* CODE_RAM_LOCATION wifi_manager_get_ip_info_json(); -uint8_t wifi_manager_get_flag(); -char * wifi_manager_alloc_get_config(char * name, size_t * l); +uint8_t CODE_RAM_LOCATION wifi_manager_get_flag(); +char * CODE_RAM_LOCATION wifi_manager_alloc_get_config(char * name, size_t * l); /** * @brief saves the current STA wifi config to flash ram storage. */ -esp_err_t wifi_manager_save_sta_config(); +esp_err_t CODE_RAM_LOCATION wifi_manager_save_sta_config(); /** * @brief saves the current configuration to flash ram storage */ -esp_err_t wifi_manager_save_autoexec_config(char * value, char * name, int len); -esp_err_t wifi_manager_save_autoexec_flag(uint8_t flag); +esp_err_t CODE_RAM_LOCATION wifi_manager_save_autoexec_config(char * value, char * name, int len); +esp_err_t CODE_RAM_LOCATION wifi_manager_save_autoexec_flag(uint8_t flag); /** * @brief fetch a previously STA wifi config in the flash ram storage. * @return true if a previously saved config was found, false otherwise. */ -bool wifi_manager_fetch_wifi_sta_config(); +bool CODE_RAM_LOCATION wifi_manager_fetch_wifi_sta_config(); -wifi_config_t* wifi_manager_get_wifi_sta_config(); +wifi_config_t* CODE_RAM_LOCATION wifi_manager_get_wifi_sta_config(); /** * @brief A standard wifi event handler as recommended by Espressif */ -esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event); +esp_err_t CODE_RAM_LOCATION wifi_manager_event_handler(void *ctx, system_event_t *event); /** * @brief requests a connection to an access point that will be process in the main task thread. */ -void wifi_manager_connect_async(); +void CODE_RAM_LOCATION wifi_manager_connect_async(); /** * @brief requests a wifi scan */ -void wifi_manager_scan_async(); +void CODE_RAM_LOCATION wifi_manager_scan_async(); /** * @brief requests to disconnect and forget about the access point. */ -void wifi_manager_disconnect_async(); +void CODE_RAM_LOCATION wifi_manager_disconnect_async(); /** * @brief Tries to get access to json buffer mutex. @@ -349,65 +349,65 @@ void wifi_manager_disconnect_async(); * @param xTicksToWait The time in ticks to wait for the semaphore to become available. * @return true in success, false otherwise. */ -bool wifi_manager_lock_json_buffer(TickType_t xTicksToWait); +bool CODE_RAM_LOCATION wifi_manager_lock_json_buffer(TickType_t xTicksToWait); /** * @brief Releases the json buffer mutex. */ -void wifi_manager_unlock_json_buffer(); +void CODE_RAM_LOCATION wifi_manager_unlock_json_buffer(); /** * @brief Generates the connection status json: ssid and IP addresses. * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful. */ -void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code); +void CODE_RAM_LOCATION wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code); /** * @brief Clears the connection status json. * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful. */ -void wifi_manager_clear_ip_info_json(); +void CODE_RAM_LOCATION wifi_manager_clear_ip_info_json(); /** * @brief Generates the list of access points after a wifi scan. * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful. */ -void wifi_manager_generate_acess_points_json(); +void CODE_RAM_LOCATION wifi_manager_generate_acess_points_json(); /** * @brief Clear the list of access points. * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful. */ -void wifi_manager_clear_access_points_json(); +void CODE_RAM_LOCATION wifi_manager_clear_access_points_json(); /** * @brief Start the mDNS service */ -void wifi_manager_initialise_mdns(); +void CODE_RAM_LOCATION wifi_manager_initialise_mdns(); -bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait); -void wifi_manager_unlock_sta_ip_string(); +bool CODE_RAM_LOCATION wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait); +void CODE_RAM_LOCATION wifi_manager_unlock_sta_ip_string(); /** * @brief gets the string representation of the STA IP address, e.g.: "192.168.1.69" */ -char* wifi_manager_get_sta_ip_string(); +char* CODE_RAM_LOCATION wifi_manager_get_sta_ip_string(); /** * @brief thread safe char representation of the STA IP update */ -void wifi_manager_safe_update_sta_ip_string(uint32_t ip); +void CODE_RAM_LOCATION wifi_manager_safe_update_sta_ip_string(uint32_t ip); /** * @brief Register a callback to a custom function when specific event message_code happens. */ -void wifi_manager_set_callback(message_code_t message_code, void (*func_ptr)(void*) ); +void CODE_RAM_LOCATION wifi_manager_set_callback(message_code_t message_code, void (*func_ptr)(void*) ); -BaseType_t wifi_manager_send_message(message_code_t code, void *param); -BaseType_t wifi_manager_send_message_to_front(message_code_t code, void *param); +BaseType_t CODE_RAM_LOCATION wifi_manager_send_message(message_code_t code, void *param); +BaseType_t CODE_RAM_LOCATION wifi_manager_send_message_to_front(message_code_t code, void *param); #ifdef __cplusplus } diff --git a/main/console.c b/main/console.c index 3fa2a91d..174f5ebd 100644 --- a/main/console.c +++ b/main/console.c @@ -17,7 +17,6 @@ #include "driver/uart.h" #include "linenoise/linenoise.h" #include "argtable3/argtable3.h" -#include "esp_vfs_fat.h" #include "nvs.h" #include "nvs_flash.h" #include "pthread.h" @@ -34,9 +33,6 @@ static void * console_thread(); void console_start(); static const char * TAG = "console"; -#if RECOVERY_APPLICATION ==1 -extern void start_ota(const char * bin_url); -#endif /* Prompt to be printed before each line. @@ -52,71 +48,6 @@ const char* prompt = LOG_COLOR_I "squeezelite-esp32> " LOG_RESET_COLOR; #define MOUNT_PATH "/data" #define HISTORY_PATH MOUNT_PATH "/history.txt" void run_command(char * line); -//optListStruct * getOptionByName(char * option){ -// optListStruct * curOpt=&optList[0]; -// while(curOpt->optName !=NULL){ -// if(!strcmp(curOpt->optName, option)){ -// return curOpt; -// } -// curOpt++; -// } -// return NULL; -//} -// -//static int list_options(int argc, char **argv) -//{ -// nvs_handle nvs; -// esp_err_t err; -// -// err = nvs_open(current_namespace, NVS_READONLY, &nvs); -// if (err != ESP_OK) { -// return err; -// } -// // -// optListStruct * curOpt=&optList[0]; -// printf("System Configuration Options.\n"); -// while(curOpt->optName!=NULL){ -// printf("Option: %s\n" -// " Description: %20s\n" -// " Default Value: %20s\n" -// " Current Value: ",curOpt->optName, curOpt->description, curOpt->defaultValue); -// size_t len; -// if ( (nvs_get_str(nvs, curOpt->optName, NULL, &len)) == ESP_OK) { -// char *str = (char *)malloc(len); -// if ( (nvs_get_str(nvs, curOpt->optName, str, &len)) == ESP_OK) { -// printf("%20s\n", str); -// } -// free(str); -// } -// else -// { -// if(store_nvs_value(NVS_TYPE_STR, curOpt->optName,curOpt->defaultValue, strlen(curOpt->defaultValue))==ESP_OK) -// { -// printf("%20s\n", curOpt->defaultValue); -// } -// else -// { -// printf("Error. Invalid key\n"); -// } -// } -// curOpt++; -// } -// printf("\n"); -// nvs_close(nvs); -// return 0; -//} -//void register_list_options(){ -// const esp_console_cmd_t config_list = { -// .command = "config-list", -// .help = "Lists available configuration options.", -// .hint = NULL, -// .func = &list_options, -// .argtable = NULL -// }; -// -// ESP_ERROR_CHECK( esp_console_cmd_register(&config_list) ); -// -//} void process_autoexec(){ int i=1; @@ -156,20 +87,20 @@ void process_autoexec(){ store_nvs_value(NVS_TYPE_STR,"autoexec1",autoexec1_dft); } } -static void initialize_filesystem() { - static wl_handle_t wl_handle; - const esp_vfs_fat_mount_config_t mount_config = { - .max_files = 10, - .format_if_mount_failed = true, - .allocation_unit_size = 4096 - }; - esp_err_t err = esp_vfs_fat_spiflash_mount(MOUNT_PATH, "storage", - &mount_config, &wl_handle); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err)); - return; - } -} +//static void initialize_filesystem() { +// static wl_handle_t wl_handle; +// const esp_vfs_fat_mount_config_t mount_config = { +// .max_files = 10, +// .format_if_mount_failed = true, +// .allocation_unit_size = 4096 +// }; +// esp_err_t err = esp_vfs_fat_spiflash_mount(MOUNT_PATH, "storage", +// &mount_config, &wl_handle); +// if (err != ESP_OK) { +// ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err)); +// return; +// } +//} static void initialize_nvs() { esp_err_t err = nvs_flash_init(); @@ -229,12 +160,12 @@ void initialize_console() { linenoiseHistorySetMaxLen(100); /* Load command history from filesystem */ - linenoiseHistoryLoad(HISTORY_PATH); + //linenoiseHistoryLoad(HISTORY_PATH); } void console_start() { initialize_nvs(); - initialize_filesystem(); + //initialize_filesystem(); initialize_console(); /* Register commands */ @@ -242,23 +173,29 @@ void console_start() { register_system(); register_nvs(); #if RECOVERY_APPLICATION!=1 -#warning "compiling for squeezelite" register_squeezelite(); #elif RECOVERY_APPLICATION==1 -#warning "compiling for recovery" register_ota_cmd(); #else #error "Unknown build configuration" #endif register_i2ctools(); printf("\n" +#if RECOVERY_APPLICATION + "****************************************************************\n" + "RECOVERY APPLICATION\n" + "This mode is used to flash Squeezelite into the OTA partition\n" + "****\n\n" +#endif "Type 'help' to get the list of commands.\n" "Use UP/DOWN arrows to navigate through command history.\n" "Press TAB when typing command name to auto-complete.\n" "\n" +#if !RECOVERY_APPLICATION "To automatically execute lines at startup:\n" "\tSet NVS variable autoexec (U8) = 1 to enable, 0 to disable automatic execution.\n" "\tSet NVS variable autoexec[1~9] (string)to a command that should be executed automatically\n" +#endif "\n" "\n"); @@ -283,8 +220,7 @@ void console_start() { cfg.thread_name= "console"; cfg.inherit_cfg = true; #if RECOVERY_APPLICATION - // make sure the stack is large enough for http processing with redirects. - cfg.stack_size = 1024*100 ; + cfg.stack_size = 4096 ; #endif esp_pthread_set_cfg(&cfg); pthread_attr_t attr; @@ -310,7 +246,9 @@ void run_command(char * line){ } } static void * console_thread() { +#if !RECOVERY_APPLICATION process_autoexec(); +#endif /* Main loop */ while (1) { /* Get a line using linenoise. diff --git a/main/esp_app_main.c b/main/esp_app_main.c index 256db528..8d9366ee 100644 --- a/main/esp_app_main.c +++ b/main/esp_app_main.c @@ -44,6 +44,8 @@ #include "squeezelite-ota.h" static EventGroupHandle_t wifi_event_group; +extern char current_namespace[]; + const int CONNECTED_BIT = BIT0; #define JOIN_TIMEOUT_MS (10000) @@ -87,30 +89,75 @@ bool wait_for_wifi(){ } return connected; } +static void initialize_nvs() { + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK(err); +} +char * process_ota_url(){ + nvs_handle nvs; + ESP_LOGI(TAG,"Checking for update url"); + char * fwurl=get_nvs_value_alloc(NVS_TYPE_STR, "fwurl"); + if(fwurl!=NULL) + { + ESP_LOGD(TAG,"Deleting nvs entry for Firmware URL %s", fwurl); + esp_err_t err = nvs_open(current_namespace, NVS_READWRITE, &nvs); + if (err == ESP_OK) { + err = nvs_erase_key(nvs, "fwurl"); + if (err == ESP_OK) { + ESP_LOGD(TAG,"Firmware url erased from nvs."); + err = nvs_commit(nvs); + if (err == ESP_OK) { + ESP_LOGI(TAG, "Value with key '%s' erased", "fwurl"); + ESP_LOGD(TAG,"nvs erase committed."); + } + else + { + ESP_LOGE(TAG,"Unable to commit nvs erase operation. Error : %s.",esp_err_to_name(err)); + } + } + else + { + ESP_LOGE(TAG,"Error : %s. Unable to delete firmware url key.",esp_err_to_name(err)); + } + nvs_close(nvs); + } + else + { + ESP_LOGE(TAG,"Error opening nvs: %s. Unable to delete firmware url key.",esp_err_to_name(err)); + } + } + return fwurl; +} + void app_main() { + char * fwurl = NULL; + initialize_nvs(); led_config(LED_GREEN, LED_GREEN_GPIO, 0); led_config(LED_RED, LED_RED_GPIO, 0); wifi_event_group = xEventGroupCreate(); xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); + fwurl = process_ota_url(); /* start the wifi manager */ led_blink(LED_GREEN, 250, 250); wifi_manager_start(); wifi_manager_set_callback(EVENT_STA_GOT_IP, &cb_connection_got_ip); wifi_manager_set_callback(WIFI_EVENT_STA_DISCONNECTED, &cb_connection_sta_disconnected); + console_start(); - char * fwurl = get_nvs_value_alloc(NVS_TYPE_STR, "fwurl"); if(fwurl && strlen(fwurl)>0){ while(!bWifiConnected){ wait_for_wifi(); + taskYIELD(); } ESP_LOGI(TAG,"Updating firmware from link: %s",fwurl); - start_ota(fwurl); - } - else - { - console_start(); + start_ota(fwurl, true); + free(fwurl); } } diff --git a/main/nvs_utilities.c b/main/nvs_utilities.c index 7463fb67..bea6df34 100644 --- a/main/nvs_utilities.c +++ b/main/nvs_utilities.c @@ -13,8 +13,8 @@ #include "esp_vfs_fat.h" #include "nvs.h" #include "nvs_flash.h" - extern char current_namespace[]; + static const char * TAG = "platform_esp32"; bool isNameValid(char * key){ bool bFound=false;