diff --git a/.cproject b/.cproject index 174d5e84..288cf441 100644 --- a/.cproject +++ b/.cproject @@ -1,114 +1,230 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -j8 - all - true - false - true - - - make - size-components - true - true - true - - - make - flash - true - true - true - - - make - -j8 app PROJECT_NAME="recovery.custom" EXTRA_CFLAGS=" -DRECOVERY_APPLICATION=1" - recovery - true - false - true - - - python - ${IDF_PATH}/tools/windows/eclipse_make.py -j8 - app - true - true - true - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make + + -j6 + + all + + true + + true + + true + + + + + + make + + -j6 + + size-components + + true + + true + + true + + + + + + make + + -j6 + + make -j8 EXTRA_CFLAGS="-D RECOVERY_APPLICATION=1" + + true + + true + + true + + + + + + python + + ${IDF_PATH}/tools/windows/eclipse_make.py -j8 app PROJECT_NAME="recovery.custom" EXTRA_CFLAGS=" -DRECOVERY_APPLICATION=1" + + recovery + + true + + false + + true + + + + + + python + + ${IDF_PATH}/tools/windows/eclipse_make.py -j8 + + app + + true + + true + + true + + + + + + + diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml index 5151056a..460b38fd 100644 --- a/.settings/language.settings.xml +++ b/.settings/language.settings.xml @@ -1,12 +1,22 @@ - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs new file mode 100644 index 00000000..90be52ce --- /dev/null +++ b/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,12 @@ +eclipse.preferences.version=1 +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/BATCH_BUILD/delimiter=; +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/BATCH_BUILD/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/BATCH_BUILD/value=1 +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/IDF_PATH/delimiter=; +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/IDF_PATH/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/IDF_PATH/value=d\:/msys2/opt/esp-idf +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/PATH/delimiter=; +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/PATH/operation=replace +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/PATH/value=C\:/msys2/opt/xtensa-esp32-elf/bin;C\:/jdk-12.0.2/bin/server;C\:/jdk-12.0.2/bin;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Program Files\\NVIDIA Corporation\\NVIDIA NvDLISR;C\:\\jdk-12.0.2\\bin;C\:\\Program Files\\PuTTY\\;C\:\\Program Files (x86)\\HP\\IdrsOCR_15.2.10.1114\\;C\:\\eclipse +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/append=true +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/appendContributed=true diff --git a/components/cmd_nvs/cmd_nvs.c b/components/cmd_nvs/cmd_nvs.c index daff6e7b..bebe9157 100644 --- a/components/cmd_nvs/cmd_nvs.c +++ b/components/cmd_nvs/cmd_nvs.c @@ -47,7 +47,7 @@ static const type_str_pair_t type_str_pair[] = { static const size_t TYPE_STR_PAIR_SIZE = sizeof(type_str_pair) / sizeof(type_str_pair[0]); static const char *ARG_TYPE_STR = "type can be: i8, u8, i16, u16 i32, u32 i64, u64, str, blob"; -char current_namespace[16] = "espwifimgr"; +char current_namespace[16] = "squeezelite-esp32"; static const char * TAG = "platform_esp32"; static struct { @@ -461,8 +461,6 @@ static int set_namespace(int argc, char **argv) return 0; } -#ifdef ESP_IDF_COMMIT_bde1c30 // this commit added support for listing nvs entries - static int list(const char *part, const char *name, const char *str_type) { nvs_type_t type = str_to_type(str_type); @@ -502,7 +500,6 @@ static int list_entries(int argc, char **argv) return list(part, name, type); } -#endif void register_nvs() { esp_log_level_set(TAG, ESP_LOG_VERBOSE); @@ -569,7 +566,6 @@ void register_nvs() .argtable = &namespace_args }; -#ifdef ESP_IDF_COMMIT_bde1c30 // this commit added support for listing nvs entries const esp_console_cmd_t list_entries_cmd = { .command = "nvs_list", .help = "List stored key-value pairs stored in NVS." @@ -581,7 +577,6 @@ void register_nvs() .argtable = &list_args }; ESP_ERROR_CHECK(esp_console_cmd_register(&list_entries_cmd)); -#endif ESP_ERROR_CHECK(esp_console_cmd_register(&set_cmd)); ESP_ERROR_CHECK(esp_console_cmd_register(&get_cmd)); ESP_ERROR_CHECK(esp_console_cmd_register(&erase_cmd)); diff --git a/components/wifi-manager/http_server.c b/components/wifi-manager/http_server.c index 9e6b45f3..4939e44c 100644 --- a/components/wifi-manager/http_server.c +++ b/components/wifi-manager/http_server.c @@ -33,7 +33,7 @@ function to process requests, decode URLs, serve files, etc. etc. #include "http_server.h" #include "cmd_system.h" - +#define NVS_PARTITION_NAME "nvs" /* @brief tag used for ESP serial console messages */ static const char TAG[] = "http_server"; @@ -134,6 +134,38 @@ 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, int parm_name_max_len, char ** next_position ) { + *len = 0; + char *ret = NULL; + char *ptr = NULL; + + ptr = strstr(request, header_name); + if (ptr) { + ret = ptr + strlen(header_name); + ptr = ret; + while (*ptr != '\0' && *ptr != '\n' && *ptr != '\r' && *ptr != ':' ) { + ptr++; + } + if(*ptr==':'){ + // save the parameter name: the string between header name and ":" + strncpy(parm_name,ret,(ptr-ret-1>parm_name_max_len?parm_name_max_len:ptr-ret-1)); + ptr++; + while (*ptr == ' ' ) { + ptr++; + } + } + + while (*ptr != '\0' && *ptr != '\n' && *ptr != '\r') { + (*len)++; + ptr++; + } + // Terminate value inside its actual buffer so we can treat it as individual string + *ptr='\0'; + *next_position=ptr; + return ret; + } + return NULL; +} void http_server_netconn_serve(struct netconn *conn) { @@ -239,40 +271,43 @@ void http_server_netconn_serve(struct netconn *conn) { { int i=1; size_t l = 0; + esp_err_t esp_err; netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); - autoexec_flag = wifi_manager_get_flag(); snprintf(buff,buflen-1, json_start, RECOVERY_APPLICATION, autoexec_flag); netconn_write(conn, buff, strlen(buff), NETCONN_NOCOPY); - do { - snprintf(autoexec_name,sizeof(autoexec_name)-1,"autoexec%u",i); - ESP_LOGD(TAG,"Getting command name %s", autoexec_name); - autoexec_value = wifi_manager_alloc_get_config(autoexec_name, &l); - if(autoexec_value!=NULL ){ + + ESP_LOGI(TAG, "About to get config from flash"); + + nvs_iterator_t it = nvs_entry_find(NVS_PARTITION_NAME, NULL, NVS_TYPE_STR); + if (it == NULL) { + ESP_LOGW(TAG, "No nvs entry found in %s",NVS_PARTITION_NAME ); + } + while (it != NULL){ + nvs_entry_info_t info; + nvs_entry_info(it, &info); + it = nvs_entry_next(it); + if(strstr(info.namespace_name, current_namespace)){ if(i>1) { netconn_write(conn, array_separator, strlen(array_separator), NETCONN_NOCOPY); ESP_LOGD(TAG,"%s", array_separator); } - ESP_LOGI(TAG,"found command %s = %s", autoexec_name, autoexec_value); - strreplace(autoexec_value, s, r); - snprintf(buff, buflen-1, template, autoexec_name, autoexec_value); + + autoexec_value = wifi_manager_alloc_get_config(info.key, &l); + strreplace(autoexec_value, s, r); + ESP_LOGI(TAG,"Namespace %s, key=%s, value=%s", info.namespace_name, info.key,autoexec_value ); + snprintf(buff, buflen-1, template, info.key, autoexec_value); netconn_write(conn, buff, strlen(buff), NETCONN_NOCOPY); - ESP_LOGD(TAG,"%s", buff); ESP_LOGD(TAG,"Freeing memory for command %s name", autoexec_name); - free(autoexec_value); + free(autoexec_value ); + i++; } - else { - ESP_LOGD(TAG,"No matching command found for name %s", autoexec_name); - break; - } - i++; - } while(1); + } free(buff); netconn_write(conn, json_end, strlen(json_end), NETCONN_NOCOPY); ESP_LOGD(TAG,"%s", json_end); - } } else if(strstr(line, "POST /config.json ")){ @@ -280,56 +315,47 @@ void http_server_netconn_serve(struct netconn *conn) { if(wifi_manager_lock_json_buffer(( TickType_t ) 10)){ int i=1; - int lenS = 0, lenA=0; - char autoexec_name[22]={0}; - char autoexec_key[12]={0}; - char * autoexec_value=NULL; - char * autoexec_flag_s=NULL; + int lenA=0; + char * last_parm=save_ptr; + char * next_parm=save_ptr; + char * last_parm_name[41]={0}; uint8_t autoexec_flag=0; - autoexec_flag_s = http_server_get_header(save_ptr, "X-Custom-autoexec: ", &lenA); - if(autoexec_flag_s!=NULL && lenA > 0) - { - autoexec_flag = atoi(autoexec_flag_s); - wifi_manager_save_autoexec_flag(autoexec_flag); + bool bErrorFound=false; + + while(last_parm!=NULL){ + // Search will return + memset(last_parm_name,0x00,sizeof(last_parm_name)); + last_parm = http_server_search_header(next_parm, "X-Custom- ", &lenA, last_parm_name, sizeof(last_parm_name)-1,&next_parm); + ESP_LOGD(TAG, "http_server_netconn_serve: config.json/ call, found parameter %s=%s, length %i", last_parm_name, last_parm, lenA); + if(last_parm!=NULL){ + if(strstr(last_parm_name, "autoexec")){ + autoexec_flag = atoi(last_parm); + wifi_manager_save_autoexec_flag(autoexec_flag); + } + else { + if(lenA < MAX_COMMAND_LINE_SIZE ){ + ESP_LOGD(TAG, "http_server_netconn_serve: config.json/ Storing parameter"); + wifi_manager_save_autoexec_config(last_parm,last_parm_name,lenA); + } + else + { + char szErrorPrefix[]="{ status: \"value length is too long for "; + char szErrorSuffix[]="{ status: \"value length is too long for "; + netconn_write(conn, szErrorPrefix, strlen(szErrorPrefix), NETCONN_NOCOPY); + ESP_LOGE(TAG,"length is too long : %s = %s", last_parm_name, last_parm); + last_parm=NULL; + } + } + } + } + if(bErrorFound){ + 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 } - do { - if(snprintf(autoexec_name,sizeof(autoexec_name)-1,"X-Custom-autoexec%u: ",i)<0) - { - ESP_LOGE(TAG,"Unable to process autoexec%u. Name length overflow.",i); - break; - } - if(snprintf(autoexec_key,sizeof(autoexec_key)-1,"autoexec%u",i++)<0) - { - ESP_LOGE(TAG,"Unable to process autoexec%u. Name length overflow.",i); - break; - } - ESP_LOGD(TAG,"Looking for command name %s.", autoexec_name); - autoexec_value = http_server_get_header(save_ptr, autoexec_name, &lenS); - if(autoexec_value ){ - if(lenS < MAX_COMMAND_LINE_SIZE ){ - ESP_LOGD(TAG, "http_server_netconn_serve: config.json/ call, with %s: %s, length %i", autoexec_key, autoexec_value, lenS); - wifi_manager_save_autoexec_config(autoexec_value,autoexec_key,lenS); - } - else - { - ESP_LOGE(TAG,"command line length is too long : %s = %s", autoexec_name, autoexec_value); - } - } - else { - ESP_LOGD(TAG,"No matching command found for name %s", autoexec_name); - break; - } - } while(1); - - netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); //200ok - - //reboot esp if autoexec1 was modified - if (i > 1) { - ESP_LOGD(TAG,"autoexec1 changed, triggering reboot"); - esp_restart(); - } } else{ netconn_write(conn, http_503_hdr, sizeof(http_503_hdr) - 1, NETCONN_NOCOPY); diff --git a/components/wifi-manager/wifi_manager.c b/components/wifi-manager/wifi_manager.c index 93e8c446..5d6f5e08 100644 --- a/components/wifi-manager/wifi_manager.c +++ b/components/wifi-manager/wifi_manager.c @@ -54,7 +54,7 @@ Contains the freeRTOS task and all necessary support #include "lwip/err.h" #include "lwip/netdb.h" #include "lwip/ip4_addr.h" - +#include "app_update/include/esp_ota_ops.h" #ifndef SQUEEZELITE_ESP32_RELEASE_URL #define SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases" @@ -98,6 +98,7 @@ struct wifi_settings_t wifi_settings = { }; const char wifi_manager_nvs_namespace[] = "espwifimgr"; +char current_namespace[16] = "squeezelite-esp32"; EventGroupHandle_t wifi_manager_event_group; @@ -177,7 +178,7 @@ uint8_t wifi_manager_get_flag(){ esp_err_t esp_err; ESP_LOGI(TAG, "About to get config from flash"); - esp_err = nvs_open(wifi_manager_nvs_namespace, NVS_READWRITE, &handle); + esp_err = nvs_open(current_namespace, NVS_READWRITE, &handle); if (esp_err != ESP_OK) return 0; esp_err= nvs_get_u8(handle, "autoexec", &value); @@ -194,7 +195,7 @@ char * wifi_manager_alloc_get_config(char * name, size_t * l){ nvs_handle handle; ESP_LOGD(TAG, "About to get config value %s from flash",name); - if (nvs_open(wifi_manager_nvs_namespace, NVS_READWRITE, &handle) == ESP_OK) { + if (nvs_open(current_namespace, NVS_READWRITE, &handle) == ESP_OK) { if (nvs_get_str(handle, name, NULL, &len)==ESP_OK) { value=(char *)malloc(len); memset(value,0x0, len); @@ -220,7 +221,7 @@ esp_err_t wifi_manager_save_autoexec_flag(uint8_t flag){ nvs_handle handle; esp_err_t esp_err; ESP_LOGI(TAG, "About to save config to flash"); - esp_err=nvs_open(wifi_manager_nvs_namespace, NVS_READWRITE, &handle); + esp_err=nvs_open(current_namespace, NVS_READWRITE, &handle); if (esp_err != ESP_OK) { ESP_LOGE(TAG,"Unable to open nvs namespace %s",wifi_manager_nvs_namespace); return esp_err; @@ -248,17 +249,15 @@ esp_err_t wifi_manager_save_autoexec_flag(uint8_t flag){ esp_err_t wifi_manager_save_autoexec_config(char * value, char * name, int len){ nvs_handle handle; - char val[len+1]; - esp_err_t esp_err; - if (len) { *val = '\0'; strncat(val, value, len); } - ESP_LOGI(TAG, "About to save config to flash"); - esp_err = nvs_open(wifi_manager_nvs_namespace, NVS_READWRITE, &handle); + esp_err_t esp_err; + ESP_LOGI(TAG, "About to save config to flash"); + esp_err = nvs_open(current_namespace, NVS_READWRITE, &handle); if (esp_err != ESP_OK) { - ESP_LOGE(TAG,"Unable to open nvs namespace %s",wifi_manager_nvs_namespace); + ESP_LOGE(TAG,"Unable to open nvs namespace %s",current_namespace); return esp_err; } - esp_err = nvs_set_str(handle, name, val); + esp_err = nvs_set_str(handle, name, value); if (esp_err != ESP_OK){ ESP_LOGE(TAG,"Unable to save value %s=%s",name,val); nvs_close(handle); @@ -406,13 +405,14 @@ void wifi_manager_clear_ip_info_json(){ void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code){ wifi_config_t *config = wifi_manager_get_wifi_sta_config(); if(config){ -#if !RECOVERY_APPLICATION - const char ip_info_json_format[] = ",\"ip\":\"%s\",\"netmask\":\"%s\",\"gw\":\"%s\",\"urc\":%d}\n"; -#else - const char ip_info_json_format[] = ",\"ip\":\"%s\",\"netmask\":\"%s\",\"gw\":\"%s\",\"urc\":%d, \"ota_dsc\":\"%s\", \"ota_pct\":%d}\n"; + const char ip_info_json_format[] = ",\"ip\":\"%s\",\"netmask\":\"%s\",\"gw\":\"%s\",\"urc\":%d,\"project_name\":\"%s\",\"version\":\"%s\""; +#if RECOVERY_APPLICATION + "\"ota_dsc\":\"%s\", \"ota_pct\":%d"; #endif + "}\n"; memset(ip_info_json, 0x00, JSON_IP_INFO_SIZE); + app_desc_t* app_desc=esp_ota_get_app_description(void); /* to avoid declaring a new buffer we copy the data directly into the buffer at its correct address */ strcpy(ip_info_json, "{\"ssid\":"); @@ -433,7 +433,11 @@ void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code) ip, netmask, gw, - (int)update_reason_code + (int)update_reason_code, + app_desc->project_name, + app_desc->version + + #if RECOVERY_APPLICATION ,ota_get_status(), ota_get_pct_complete() diff --git a/components/wifi-manager/wifi_manager.h b/components/wifi-manager/wifi_manager.h index d32076d9..d56adce4 100644 --- a/components/wifi-manager/wifi_manager.h +++ b/components/wifi-manager/wifi_manager.h @@ -176,7 +176,8 @@ extern "C" { // recovery has more resources available. Let's use them to include more details about the OTA process #define JSON_IP_INFO_SIZE 150+255 #else -#define JSON_IP_INFO_SIZE 150 +// 40 chars for appname and version +#define JSON_IP_INFO_SIZE 150+40 #endif