From b6f1ce9a7aba3fbecfac73fb5c88e2de035b25f6 Mon Sep 17 00:00:00 2001 From: Sebastien Date: Thu, 3 Oct 2019 14:15:59 -0400 Subject: [PATCH] NVS Refactor ** Factory+Squeezelite FLASH required for this branch! This is a major refactoring of the nvs parameters storage. To support this, a new partition was added. To start using this branch, one must flash all binaries and possibly re-configure the system. --- ...defaults => SqueezeAmp-sdkconfig.defaults} | 0 components/cmd_nvs/cmd_nvs.c | 38 +------- components/cmd_nvs/component.mk | 3 +- components/cmd_system/cmd_system.c | 35 ++++--- components/driver_bt/bt_app_sink.c | 19 +--- components/driver_bt/component.mk | 2 +- components/raop/component.mk | 4 +- components/raop/raop_sink.c | 16 ++-- components/squeezelite/decode_external.c | 30 +++--- components/squeezelite/embedded.h | 7 +- components/squeezelite/output_i2s.c | 5 +- components/wifi-manager/component.mk | 2 + components/wifi-manager/http_server.c | 30 +++--- components/wifi-manager/wifi_manager.c | 91 ++++--------------- components/wifi-manager/wifi_manager.h | 7 -- main/CMakeLists.txt | 2 +- main/component.mk | 2 + main/esp_app_main.c | 50 +++++++++- main/nvs_utilities.c | 12 ++- main/nvs_utilities.h | 3 + main/platform_esp32.h | 3 + partitions.csv | 3 +- 22 files changed, 168 insertions(+), 196 deletions(-) rename build-scripts/{SqueezeAmp4MBFlash-sdkconfig.defaults => SqueezeAmp-sdkconfig.defaults} (100%) diff --git a/build-scripts/SqueezeAmp4MBFlash-sdkconfig.defaults b/build-scripts/SqueezeAmp-sdkconfig.defaults similarity index 100% rename from build-scripts/SqueezeAmp4MBFlash-sdkconfig.defaults rename to build-scripts/SqueezeAmp-sdkconfig.defaults diff --git a/components/cmd_nvs/cmd_nvs.c b/components/cmd_nvs/cmd_nvs.c index a5fccf14..4b7df150 100644 --- a/components/cmd_nvs/cmd_nvs.c +++ b/components/cmd_nvs/cmd_nvs.c @@ -24,7 +24,7 @@ extern "C" { #include "esp_err.h" #include "cmd_nvs.h" #include "nvs.h" - +#include "nvs_utilities.h" typedef struct { nvs_type_t type; @@ -47,7 +47,6 @@ 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[] = "config"; static const char * TAG = "platform_esp32"; static struct { @@ -73,11 +72,6 @@ static struct { struct arg_end *end; } erase_all_args; -static struct { - struct arg_str *namespace; - struct arg_end *end; -} namespace_args; - static struct { struct arg_str *partition; struct arg_str *namespace; @@ -175,7 +169,7 @@ static esp_err_t set_value_in_nvs(const char *key, const char *str_type, const c return ESP_ERR_NVS_TYPE_MISMATCH; } - err = nvs_open(current_namespace, NVS_READWRITE, &nvs); + err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READWRITE, &nvs); if (err != ESP_OK) { return err; } @@ -262,7 +256,7 @@ static esp_err_t get_value_from_nvs(const char *key, const char *str_type) return ESP_ERR_NVS_TYPE_MISMATCH; } - err = nvs_open(current_namespace, NVS_READONLY, &nvs); + err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READWRITE, &nvs); if (err != ESP_OK) { return err; } @@ -339,7 +333,7 @@ static esp_err_t erase(const char *key) { nvs_handle nvs; - esp_err_t err = nvs_open(current_namespace, NVS_READWRITE, &nvs); + esp_err_t err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READWRITE, &nvs); if (err == ESP_OK) { err = nvs_erase_key(nvs, key); if (err == ESP_OK) { @@ -358,7 +352,7 @@ static esp_err_t erase_all(const char *name) { nvs_handle nvs; - esp_err_t err = nvs_open(current_namespace, NVS_READWRITE, &nvs); + esp_err_t err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READWRITE, &nvs); if (err == ESP_OK) { err = nvs_erase_all(nvs); if (err == ESP_OK) { @@ -457,19 +451,7 @@ static int erase_namespace(int argc, char **argv) return 0; } -static int set_namespace(int argc, char **argv) -{ - int nerrors = arg_parse(argc, argv, (void **) &namespace_args); - if (nerrors != 0) { - arg_print_errors(stderr, namespace_args.end, argv[0]); - return 1; - } - const char *namespace = namespace_args.namespace->sval[0]; - strlcpy(current_namespace, namespace, sizeof(current_namespace)); - ESP_LOGI(TAG, "Namespace set to '%s'", current_namespace); - return 0; -} static int list(const char *part, const char *name, const char *str_type) { @@ -528,8 +510,6 @@ void register_nvs() erase_all_args.namespace = arg_str1(NULL, NULL, "", "namespace to be erased"); erase_all_args.end = arg_end(2); - namespace_args.namespace = arg_str1(NULL, NULL, "", "namespace of the partition to be selected"); - namespace_args.end = arg_end(2); list_args.partition = arg_str1(NULL, NULL, "", "partition name"); list_args.namespace = arg_str0("n", "namespace", "", "namespace name"); list_args.type = arg_str0("t", "type", "", ARG_TYPE_STR); @@ -571,13 +551,6 @@ void register_nvs() .argtable = &erase_all_args }; - const esp_console_cmd_t namespace_cmd = { - .command = "nvs_namespace", - .help = "Set current namespace", - .hint = NULL, - .func = &set_namespace, - .argtable = &namespace_args - }; const esp_console_cmd_t list_entries_cmd = { .command = "nvs_list", @@ -593,7 +566,6 @@ void register_nvs() 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)); - ESP_ERROR_CHECK(esp_console_cmd_register(&namespace_cmd)); ESP_ERROR_CHECK(esp_console_cmd_register(&erase_namespace_cmd)); } #ifdef __cplusplus diff --git a/components/cmd_nvs/component.mk b/components/cmd_nvs/component.mk index 57343a7e..a71c86c5 100644 --- a/components/cmd_nvs/component.mk +++ b/components/cmd_nvs/component.mk @@ -9,4 +9,5 @@ COMPONENT_ADD_INCLUDEDIRS := . CFLAGS += -I$(COMPONENT_PATH)/../squeezelite-ota - +COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/components/tools/ +COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/main diff --git a/components/cmd_system/cmd_system.c b/components/cmd_system/cmd_system.c index e7f6362b..4373bd64 100644 --- a/components/cmd_system/cmd_system.c +++ b/components/cmd_system/cmd_system.c @@ -96,21 +96,19 @@ static void register_version() /** 'restart' command restarts the program */ -static int restart(int argc, char **argv) -{ - ESP_LOGI(TAG, "Restarting"); - esp_restart(); -} -esp_err_t guided_factory() + +esp_err_t guided_boot(esp_partition_subtype_t partition_subtype) { #if RECOVERY_APPLICATION - ESP_LOGW(TAG,"RECOVERY application is already active"); - return ESP_OK; + if(partition_subtype ==ESP_PARTITION_SUBTYPE_APP_FACTORY){ + ESP_LOGW(TAG,"RECOVERY application is already active"); + return ESP_OK; + } #else bool bFound=false; - ESP_LOGI(TAG, "Looking for recovery partition."); + ESP_LOGI(TAG, "Looking for partition type %u",partition_subtype); const esp_partition_t *partition; - esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); + esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, partition_subtype, NULL); if(it == NULL){ ESP_LOGE(TAG,"Unable initialize partition iterator!"); @@ -120,13 +118,13 @@ esp_err_t guided_factory() partition = (esp_partition_t *) esp_partition_get(it); if(partition != NULL){ - ESP_LOGI(TAG, "Found recovery partition."); + ESP_LOGI(TAG, "Found partition type %u",partition_subtype); esp_ota_set_boot_partition(partition); bFound=true; } else { - ESP_LOGE(TAG,"Recovery partition not found! Unable to reboot to recovery."); + ESP_LOGE(TAG,"partition type %u not found! Unable to reboot to recovery.",partition_subtype); } esp_partition_iterator_release(it); if(bFound) { @@ -137,9 +135,20 @@ esp_err_t guided_factory() #endif return ESP_OK; } + +static int restart(int argc, char **argv) +{ + ESP_LOGI(TAG, "Restarting"); + guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0); + return 0; // return fail. This should never return... we're rebooting! +} +esp_err_t guided_factory(){ + guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY); + return ESP_FAIL; // return fail. This should never return... we're rebooting! +} static int restart_factory(int argc, char **argv) { - guided_factory(); + guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY); return 0; // return fail. This should never return... we're rebooting! } static void register_restart() diff --git a/components/driver_bt/bt_app_sink.c b/components/driver_bt/bt_app_sink.c index d0088501..759ac1c9 100644 --- a/components/driver_bt/bt_app_sink.c +++ b/components/driver_bt/bt_app_sink.c @@ -22,7 +22,7 @@ #include "esp_a2dp_api.h" #include "esp_avrc_api.h" #include "nvs.h" - +#include "nvs_utilities.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -43,12 +43,11 @@ #define CONFIG_BT_NAME "ESP32-BT" #endif -extern char current_namespace[]; - /* event for handler "bt_av_hdl_stack_up */ enum { BT_APP_EVT_STACK_UP = 0, }; +char * bt_name = NULL; static void (*bt_app_a2d_cmd_cb)(bt_sink_cmd_t cmd, ...); static void (*bt_app_a2d_data_cb)(const uint8_t *data, uint32_t len); @@ -467,17 +466,9 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) switch (event) { case BT_APP_EVT_STACK_UP: { /* set up device name */ - nvs_handle nvs; - char dev_name[32] = CONFIG_BT_NAME; - - if (nvs_open(current_namespace, NVS_READONLY, &nvs) == ESP_OK) { - size_t len = 31; - nvs_get_str(nvs, "bt_name", dev_name, &len); - nvs_close(nvs); - } - - esp_bt_dev_set_device_name(dev_name); - + bt_name = (char * )get_nvs_value_alloc_default(NVS_TYPE_STR, "bt_name", CONFIG_BT_NAME, 0); + esp_bt_dev_set_device_name(bt_name); + free(bt_name); esp_bt_gap_register_callback(bt_app_gap_cb); /* initialize AVRCP controller */ diff --git a/components/driver_bt/component.mk b/components/driver_bt/component.mk index 7460959c..e1758449 100644 --- a/components/driver_bt/component.mk +++ b/components/driver_bt/component.mk @@ -10,4 +10,4 @@ CFLAGS += -I$(COMPONENT_PATH)/../tools COMPONENT_ADD_INCLUDEDIRS := . COMPONENT_ADD_INCLUDEDIRS += $(COMPONENT_PATH)/../tools - +COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/main/ diff --git a/components/raop/component.mk b/components/raop/component.mk index 9da56926..9614efb8 100644 --- a/components/raop/component.mk +++ b/components/raop/component.mk @@ -9,5 +9,5 @@ CFLAGS += -fstack-usage \ -I$(COMPONENT_PATH)/../tools \ - -I$(COMPONENT_PATH)/../codecs/inc/alac - + -I$(COMPONENT_PATH)/../codecs/inc/alac \ + -I$(PROJECT_PATH)/main/ diff --git a/components/raop/raop_sink.c b/components/raop/raop_sink.c index 623c45d1..c2cfcb0b 100644 --- a/components/raop/raop_sink.c +++ b/components/raop/raop_sink.c @@ -11,7 +11,7 @@ #include "esp_pthread.h" #include "esp_system.h" #include "freertos/timers.h" - +#include "nvs_utilities.h" #include "raop.h" #include "log_util.h" @@ -23,7 +23,6 @@ #endif static const char * TAG = "platform"; -extern char current_namespace[]; log_level raop_loglevel = lINFO; log_level util_loglevel; @@ -58,12 +57,13 @@ void raop_sink_init(raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb) { ESP_ERROR_CHECK( mdns_init() ); ESP_ERROR_CHECK( mdns_hostname_set(hostname) ); - if (nvs_open(current_namespace, NVS_READONLY, &nvs) == ESP_OK) { - size_t len = sizeof(sink_name) - 1; - nvs_get_str(nvs, "airplay_name", sink_name, &len); - nvs_close(nvs); - } - + char * sink_name_buffer= get_nvs_value_alloc(NVS_TYPE_STR, "airplay_name"); + if(sink_name_buffer != NULL){ + memset(sink_name, 0x00, sizeof(sink_name)); + strncpy(sink_name,sizeof(sink_name)-1, sink_name_buffer ); + free(sink_name_buffer); + } + ESP_LOGI(TAG, "mdns hostname set to: [%s] with servicename %s", hostname, sink_name); // create RAOP instance, latency is set by controller diff --git a/components/squeezelite/decode_external.c b/components/squeezelite/decode_external.c index 2b02f916..276ba501 100644 --- a/components/squeezelite/decode_external.c +++ b/components/squeezelite/decode_external.c @@ -269,29 +269,27 @@ void raop_sink_cmd_handler(raop_event_t event, void *param) * We provide the generic codec register option */ void register_external(void) { -#ifdef CONFIG_BT_SINK - if (!strcasestr(output.device, "BT ")) { - bt_sink_init(bt_sink_cmd_handler, sink_data_handler); - LOG_INFO("Initializing BT sink"); + if (!strcasestr(output.device, "BT ") ) { + if(enable_bt_sink){ + bt_sink_init(bt_sink_cmd_handler, sink_data_handler); + LOG_INFO("Initializing BT sink"); + } } else { LOG_WARN("Cannot be a BT sink and source"); } -#endif -#ifdef CONFIG_AIRPLAY_SINK - raop_sink_init(raop_sink_cmd_handler, raop_sink_data_handler); - LOG_INFO("Initializing AirPlay sink"); -#endif + if(enable_airplay){ + raop_sink_init(raop_sink_cmd_handler, raop_sink_data_handler); + LOG_INFO("Initializing AirPlay sink"); + } } void deregister_external(void) { -#ifdef CONFIG_BT_SINK - if (!strcasestr(output.device, "BT ")) { + if (!strcasestr(output.device, "BT ") && enable_bt_sink) { bt_sink_deinit(); LOG_INFO("Stopping BT sink"); } -#endif -#ifdef CONFIG_AIRPLAY_SINK - raop_sink_deinit(); - LOG_INFO("Stopping AirPlay sink"); -#endif + if(enable_airplay){ + raop_sink_deinit(); + LOG_INFO("Stopping AirPlay sink"); + } } diff --git a/components/squeezelite/embedded.h b/components/squeezelite/embedded.h index 8db425ab..3c9ec1a8 100644 --- a/components/squeezelite/embedded.h +++ b/components/squeezelite/embedded.h @@ -1,6 +1,6 @@ #ifndef EMBEDDED_H #define EMBEDDED_H - +#include "esp_system.h" #include /* must provide @@ -41,7 +41,10 @@ uint32_t _gettime_ms_(void); int pthread_create_name(pthread_t *thread, _CONST pthread_attr_t *attr, void *(*start_routine)( void * ), void *arg, char *name); -// these are here as they can be #define to nothing +// these are here as they can be #define to nothing +extern bool enable_bt_sink; +extern bool enable_airplay; + void register_external(void); void deregister_external(void); diff --git a/components/squeezelite/output_i2s.c b/components/squeezelite/output_i2s.c index e4b8ed20..f77992e2 100644 --- a/components/squeezelite/output_i2s.c +++ b/components/squeezelite/output_i2s.c @@ -109,6 +109,7 @@ extern struct outputstate output; extern struct buffer *streambuf; extern struct buffer *outputbuf; extern u8_t *silencebuf; +extern bool jack_mutes_amp; static log_level loglevel; static bool running, isI2SStarted; @@ -433,7 +434,9 @@ static void *output_thread_i2s() { TIME_MEASUREMENT_START(timer_start); LOCK; - + if(jack_mutes_amp){ + // todo: implement some muting logic + } // manage led display if (state != output.state) { LOG_INFO("Output state is %d", output.state); diff --git a/components/wifi-manager/component.mk b/components/wifi-manager/component.mk index d951e503..18db7039 100644 --- a/components/wifi-manager/component.mk +++ b/components/wifi-manager/component.mk @@ -14,3 +14,5 @@ COMPONENT_ADD_INCLUDEDIRS += $(COMPONENT_PATH)/../tools COMPONENT_ADD_INCLUDEDIRS += $(COMPONENT_PATH)/../squeezelite-ota COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/main/ + + diff --git a/components/wifi-manager/http_server.c b/components/wifi-manager/http_server.c index 1a47e7e3..d5f5715a 100644 --- a/components/wifi-manager/http_server.c +++ b/components/wifi-manager/http_server.c @@ -50,7 +50,6 @@ static char *s = "\""; static char *r = "\\\""; /* @brief task handle for the http server */ static TaskHandle_t task_http_server = NULL; -extern char current_namespace[]; /** * @brief embedded binary data. @@ -74,14 +73,14 @@ extern const uint8_t index_html_end[] asm("_binary_index_html_end"); /* const http headers stored in ROM */ -const static char http_hdr_template[] = "HTTP/1.1 200 OK\nContent-type: %s\nAccept-Ranges: bytes\nContent-Length: %d\nContent-Encoding: %s\n\n"; -const static char http_html_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/html\n\n"; -const static char http_css_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/css\nCache-Control: public, max-age=31536000\n\n"; -const static char http_js_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/javascript\n\n"; +const static char http_hdr_template[] = "HTTP/1.1 200 OK\nContent-type: %s\nAccept-Ranges: bytes\nContent-Length: %d\nContent-Encoding: %s\nAccess-Control-Allow-Origin: *\n\n"; +const static char http_html_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/html\nAccess-Control-Allow-Origin: *\n\n"; +const static char http_css_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/css\nCache-Control: public, max-age=31536000\nAccess-Control-Allow-Origin: *\n\n"; +const static char http_js_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/javascript\nAccess-Control-Allow-Origin: *\n\n"; const static char http_400_hdr[] = "HTTP/1.1 400 Bad Request\nContent-Length: 0\n\n"; const static char http_404_hdr[] = "HTTP/1.1 404 Not Found\nContent-Length: 0\n\n"; const static char http_503_hdr[] = "HTTP/1.1 503 Service Unavailable\nContent-Length: 0\n\n"; -const static char http_ok_json_no_cache_hdr[] = "HTTP/1.1 200 OK\nContent-type: application/json\nCache-Control: no-store, no-cache, must-revalidate, max-age=0\nPragma: no-cache\n\n"; +const static char http_ok_json_no_cache_hdr[] = "HTTP/1.1 200 OK\nContent-type: application/json\nCache-Control: no-store, no-cache, must-revalidate, max-age=0\nPragma: no-cache\nAccess-Control-Allow-Origin: *\n\n"; const static char http_redirect_hdr_start[] = "HTTP/1.1 302 Found\nLocation: http://"; const static char http_redirect_hdr_end[] = "/\n\n"; @@ -308,12 +307,18 @@ void http_server_netconn_serve(struct netconn *conn) { /* captive portal functionality: redirect to access point IP for HOST that are not the access point IP OR the STA IP */ int lenH = 0; char *host = http_server_get_header(save_ptr, "Host: ", &lenH); + const char * host_name=NULL; + if((err=tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &host_name )) !=ESP_OK){ + ESP_LOGE(TAG,"Unable to get host name. Error: %s",esp_err_to_name(err)); + } + /* determine if Host is from the STA IP address */ wifi_manager_lock_sta_ip_string(portMAX_DELAY); bool access_from_sta_ip = lenH > 0?strstr(host, wifi_manager_get_sta_ip_string()):false; wifi_manager_unlock_sta_ip_string(); + bool access_from_host_name = (host_name!=NULL) && strstr(host, host_name); - if (lenH > 0 && !strstr(host, DEFAULT_AP_IP) && !access_from_sta_ip) { + if (lenH > 0 && !strstr(host, DEFAULT_AP_IP) && !(access_from_sta_ip || access_from_host_name)) { ESP_LOGI(TAG,"Redirecting to default AP IP Address : %s", DEFAULT_AP_IP); netconn_write(conn, http_redirect_hdr_start, sizeof(http_redirect_hdr_start) - 1, NETCONN_NOCOPY); netconn_write(conn, DEFAULT_AP_IP, sizeof(DEFAULT_AP_IP) - 1, NETCONN_NOCOPY); @@ -402,16 +407,9 @@ void http_server_netconn_serve(struct netconn *conn) { bOTA=true; } else { - if(lenA < MAX_COMMAND_LINE_SIZE ){ ESP_LOGD(TAG, "http_server_netconn_serve: config.json/ Storing parameter"); - wifi_manager_save_config(last_parm,last_parm_name,lenA); - } - else - { - ESP_LOGE(TAG,"length is too long : %s = %s", last_parm_name, last_parm); - last_parm=NULL; - bErrorFound=true; - } + err= store_nvs_value(NVS_TYPE_STR, last_parm_name , last_parm); + if(err!=ESP_OK) ESP_LOGE(TAG,"Unable to save nvs value. Error: %s",esp_err_to_name(err)); } } if(last_parm_name!=NULL) { diff --git a/components/wifi-manager/wifi_manager.c b/components/wifi-manager/wifi_manager.c index 81a3d59e..4463f324 100644 --- a/components/wifi-manager/wifi_manager.c +++ b/components/wifi-manager/wifi_manager.c @@ -59,6 +59,7 @@ Contains the freeRTOS task and all necessary support #include "driver/gpio.h" #include "driver/adc.h" #include "cJSON.h" +#include "nvs_utilities.h" #ifndef RECOVERY_APPLICATION #define RECOVERY_APPLICATION 0 @@ -84,6 +85,7 @@ uint16_t ap_num = MAX_AP_NUM; wifi_ap_record_t *accessp_records; char *accessp_json = NULL; char *ip_info_json = NULL; +char *host_name = NULL; cJSON * ip_info_cjson=NULL; wifi_config_t* wifi_manager_config_sta = NULL; static update_reason_code_t last_update_reason_code=0; @@ -113,7 +115,6 @@ struct wifi_settings_t wifi_settings = { const char wifi_manager_nvs_namespace[] = "config"; -extern char current_namespace[]; EventGroupHandle_t wifi_manager_event_group; @@ -185,78 +186,20 @@ void wifi_manager_start(){ wifi_manager_sta_ip = (char*)malloc(sizeof(char) * IP4ADDR_STRLEN_MAX); wifi_manager_safe_update_sta_ip_string((uint32_t)0); + host_name = (char * )get_nvs_value_alloc_default(NVS_TYPE_STR, "host_name", "squeezelite-esp32", 0); + char * release_url = (char * )get_nvs_value_alloc_default(NVS_TYPE_STR, "release_url", SQUEEZELITE_ESP32_RELEASE_URL, 0); + if(release_url == NULL){ + ESP_LOGE(TAG,"Unable to retrieve the release url from nvs"); + } + else { + free(release_url); + } /* start wifi manager task */ xTaskCreate(&wifi_manager, "wifi_manager", 4096, NULL, WIFI_MANAGER_TASK_PRIORITY, &task_wifi_manager); -} - - -char * wifi_manager_alloc_get_config(char * name, size_t * l){ - - size_t len=0; - char * value=NULL; - - nvs_handle handle; - ESP_LOGD(TAG, "About to get config value %s from flash",name); - esp_err_t esp_err=nvs_open(current_namespace, NVS_READWRITE, &handle); - if(esp_err==ESP_ERR_NVS_NOT_INITIALIZED){ - ESP_LOGE(TAG,"Unable to open nvs namespace %s. nvs is not initialized.",wifi_manager_nvs_namespace); - } - else if( esp_err == ESP_OK) { - if (nvs_get_str(handle, name, NULL, &len)==ESP_OK) { - value=(char *)malloc(len); - memset(value,0x0, len); - nvs_get_str(handle, name, value, &len); - *l=len; - ESP_LOGD(TAG,"Found value %s, length %u = %s",name,*l,value); - } - else - { - ESP_LOGW(TAG, "Value %s does one exist in flash",name); - } - nvs_close(handle); - } - else - { - ESP_LOGE(TAG,"Unable to open nvs namespace %s. Error: %d, %s", wifi_manager_nvs_namespace,esp_err, esp_err_to_name(esp_err)); - } - return value; } -esp_err_t wifi_manager_save_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); - esp_err = nvs_open(current_namespace, NVS_READWRITE, &handle); - if(esp_err==ESP_ERR_NVS_NOT_INITIALIZED){ - ESP_LOGE(TAG,"Unable to open nvs namespace %s. nvs is not initialized.",wifi_manager_nvs_namespace); - } - else if (esp_err != ESP_OK) { - ESP_LOGE(TAG,"Unable to open nvs namespace %s. Error: %d, %s", wifi_manager_nvs_namespace, esp_err, esp_err_to_name(esp_err)); - return esp_err; - } - esp_err = nvs_set_str(handle, name, value); - if (esp_err != ESP_OK){ - ESP_LOGE(TAG,"Unable to save value %s=%s",name,value); - nvs_close(handle); - return esp_err; - } - - esp_err = nvs_commit(handle); - if (esp_err != ESP_OK){ - ESP_LOGE(TAG,"nvs commit error"); - return esp_err; - } - - nvs_close(handle); - - ESP_LOGD(TAG, "wifi_manager_wrote %s=%s with length %i", name, value, len); - - return ESP_OK; - -} - esp_err_t wifi_manager_save_sta_config(){ nvs_handle handle; esp_err_t esp_err; @@ -626,7 +569,7 @@ char* wifi_manager_get_ip_info_json(){ void wifi_manager_destroy(){ vTaskDelete(task_wifi_manager); task_wifi_manager = NULL; - + free(host_name); /* heap buffers */ free(accessp_records); accessp_records = NULL; @@ -729,7 +672,7 @@ void wifi_manager( void * pvParameters ){ BaseType_t xStatus; EventBits_t uxBits; uint8_t retries = 0; - + esp_err_t err=ESP_OK; /* initialize the tcp stack */ tcpip_adapter_init(); @@ -782,7 +725,6 @@ void wifi_manager( void * pvParameters ){ ESP_ERROR_CHECK(esp_wifi_set_bandwidth(WIFI_IF_AP, wifi_settings.ap_bandwidth)); ESP_ERROR_CHECK(esp_wifi_set_ps(wifi_settings.sta_power_save)); - /* STA - Wifi Station configuration setup */ tcpip_adapter_dhcp_status_t status; if(wifi_settings.sta_static_ip) { @@ -802,15 +744,12 @@ void wifi_manager( void * pvParameters ){ ESP_ERROR_CHECK(tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &status)); if (status!=TCPIP_ADAPTER_DHCP_STARTED) ESP_ERROR_CHECK(tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA)); - } - - + } /* by default the mode is STA because wifi_manager will not start the access point unless it has to! */ ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_start()); - /* start http server */ http_server_start(); @@ -906,6 +845,10 @@ void wifi_manager( void * pvParameters ){ else{ /* update config to latest and attempt connection */ ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, wifi_manager_get_wifi_sta_config())); + ESP_LOGI(TAG,"Setting host name to : %s",host_name); + if((err=tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, host_name)) !=ESP_OK){ + ESP_LOGE(TAG,"Unable to set host name. Error: %s",esp_err_to_name(err)); + } ESP_ERROR_CHECK(esp_wifi_connect()); } diff --git a/components/wifi-manager/wifi_manager.h b/components/wifi-manager/wifi_manager.h index 164eee9c..06cc2194 100644 --- a/components/wifi-manager/wifi_manager.h +++ b/components/wifi-manager/wifi_manager.h @@ -279,19 +279,12 @@ void wifi_manager( void * pvParameters ); char* wifi_manager_get_ap_list_json(); char* wifi_manager_get_ip_info_json(); -char * 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(); -/** - * @brief saves the current configuration to flash ram storage - */ -esp_err_t wifi_manager_save_config(char * value, char * name, int len); - /** * @brief fetch a previously STA wifi config in the flash ram storage. diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 497df353..f228ef93 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -2,7 +2,7 @@ set(COMPONENT_ADD_INCLUDEDIRS . ) set(COMPONENT_SRCS "esp_app_main.c" "platform_esp32.c" "cmd_wifi.c" "console.c" "nvs_utilities.c" "cmd_squeezelite.c") set(REQUIRES esp_common) -set(REQUIRES_COMPONENTS freertos squeezelite nvs_flash esp32 spi_flash newlib log console ota ) +set(REQUIRES_COMPONENTS freertos squeezelite nvs_flash esp32 spi_flash newlib log console ota tools ) register_component() diff --git a/main/component.mk b/main/component.mk index a0fd0ee8..98aa5078 100644 --- a/main/component.mk +++ b/main/component.mk @@ -7,4 +7,6 @@ # please read the SDK documents if you need to do this. # CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_DEBUG +COMPONENT_ADD_INCLUDEDIRS += $(COMPONENT_PATH)/../tools +COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/components/tools/ LDFLAGS += -s \ No newline at end of file diff --git a/main/esp_app_main.c b/main/esp_app_main.c index 8beacdb0..d9533fad 100644 --- a/main/esp_app_main.c +++ b/main/esp_app_main.c @@ -40,12 +40,14 @@ #include "lwip/netdb.h" #include "nvs_utilities.h" #include "http_server.h" +#include "trace.h" #include "wifi_manager.h" #include "squeezelite-ota.h" static EventGroupHandle_t wifi_event_group; -extern char current_namespace[]; - +bool enable_bt_sink=false; +bool enable_airplay=false; +bool jack_mutes_amp=false; const int CONNECTED_BIT = BIT0; #define JOIN_TIMEOUT_MS (10000) @@ -61,6 +63,9 @@ char * fwurl = NULL; #endif static bool bWifiConnected=false; + + + /* brief this is an exemple of a callback that you can setup in your own app to get notified of wifi manager event */ void cb_connection_got_ip(void *pvParameter){ ESP_LOGI(TAG, "I have a connection!"); @@ -104,7 +109,7 @@ char * process_ota_url(){ 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); + esp_err_t err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READWRITE, &nvs); if (err == ESP_OK) { err = nvs_erase_key(nvs, "fwurl"); if (err == ESP_OK) { @@ -133,11 +138,50 @@ char * process_ota_url(){ return fwurl; } +//CONFIG_SDIF_NUM=0 +//CONFIG_SPDIF_BCK_IO=26 +//CONFIG_SPDIF_WS_IO=25 +//CONFIG_SPDIF_DO_IO=15 +//CONFIG_A2DP_CONTROL_DELAY_MS=500 +//CONFIG_A2DP_CONNECT_TIMEOUT_MS=1000 +//CONFIG_WIFI_MANAGER_MAX_RETRY=2 + +void register_default_nvs(){ + nvs_value_set_default(NVS_TYPE_STR, "bt_sink_name", CONFIG_BT_NAME, 0); + nvs_value_set_default(NVS_TYPE_STR, "bt_sink_pin", QUOTE(CONFIG_BT_SINK_PIN), 0); + nvs_value_set_default(NVS_TYPE_STR, "host_name", "squeezelite-esp32", 0); + nvs_value_set_default(NVS_TYPE_STR, "release_url", SQUEEZELITE_ESP32_RELEASE_URL, 0); + nvs_value_set_default(NVS_TYPE_STR, "ap_ip_address",CONFIG_DEFAULT_AP_IP , 0); + nvs_value_set_default(NVS_TYPE_STR, "ap_ip_gateway",CONFIG_DEFAULT_AP_GATEWAY , 0); + nvs_value_set_default(NVS_TYPE_STR, "ap_ip_netmask",CONFIG_DEFAULT_AP_NETMASK , 0); + nvs_value_set_default(NVS_TYPE_STR, "ap_channel",QUOTE(CONFIG_DEFAULT_AP_CHANNEL) , 0); + nvs_value_set_default(NVS_TYPE_STR, "ap_ssid",CONFIG_DEFAULT_AP_SSID , 0); + nvs_value_set_default(NVS_TYPE_STR, "ap_password", CONFIG_DEFAULT_AP_PASSWORD, 0); + nvs_value_set_default(NVS_TYPE_STR, "airplay_name",CONFIG_AIRPLAY_NAME , 0); + nvs_value_set_default(NVS_TYPE_STR, "airplay_port", CONFIG_AIRPLAY_PORT, 0); + nvs_value_set_default(NVS_TYPE_STR, "a2dp_sink_name", CONFIG_A2DP_SINK_NAME, 0); + nvs_value_set_default(NVS_TYPE_STR, "a2dp_device_name", CONFIG_A2DP_DEV_NAME, 0); + + char * flag = get_nvs_value_alloc_default(NVS_TYPE_STR, "enable_bt_sink", QUOTE(CONFIG_BT_SINK), 0); + enable_bt_sink= (strcmp(flag,"1")==0 ||strcasecmp(flag,"y")==0); + free(flag); + flag = get_nvs_value_alloc_default(NVS_TYPE_STR, "enable_airplay", QUOTE(CONFIG_AIRPLAY_SINK), 0); + enable_airplay= (strcmp(flag,"1")==0 ||strcasecmp(flag,"y")==0); + free(flag); + + flag = get_nvs_value_alloc_default(NVS_TYPE_STR, "jack_mutes_amp", "n", 0); + jack_mutes_amp= (strcmp(flag,"1")==0 ||strcasecmp(flag,"y")==0); + free(flag); + + + +} void app_main() { char * fwurl = NULL; initialize_nvs(); + register_default_nvs(); led_config(LED_GREEN, LED_GREEN_GPIO, 0); led_config(LED_RED, LED_RED_GPIO, 0); wifi_event_group = xEventGroupCreate(); diff --git a/main/nvs_utilities.c b/main/nvs_utilities.c index d17f75d1..061b2305 100644 --- a/main/nvs_utilities.c +++ b/main/nvs_utilities.c @@ -13,9 +13,11 @@ #include "esp_vfs_fat.h" #include "nvs.h" #include "nvs_flash.h" -extern char current_namespace[]; +const char current_namespace[] = "config"; +const char settings_partition[] = "settings"; static const char * TAG = "platform_esp32"; + bool isNameValid(char * key){ bool bFound=false; nvs_handle nvs; @@ -99,9 +101,10 @@ esp_err_t store_nvs_value_len(nvs_type_t type, const char *key, void * data, nvs_close(nvs); return err; } - +void nvs_value_set_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size) { + free(get_nvs_value_alloc_default(type, key, default_value, blob_size)); +} void * get_nvs_value_alloc_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size) { - void * current_value = get_nvs_value_alloc(type, key); if(current_value == NULL && default_value != NULL){ if(type == NVS_TYPE_BLOB && blob_size == 0){ @@ -114,6 +117,9 @@ void * get_nvs_value_alloc_default(nvs_type_t type, const char *key, void * defa ESP_LOGE(TAG,"Unable to store default nvs value. Error: %s",esp_err_to_name(err)); return NULL; } + else{ + ESP_LOGI(TAG,"Stored new default value for key %s", key); + } } } if(current_value == NULL){ diff --git a/main/nvs_utilities.h b/main/nvs_utilities.h index 8610e8db..a9331227 100644 --- a/main/nvs_utilities.h +++ b/main/nvs_utilities.h @@ -4,6 +4,8 @@ #ifdef __cplusplus extern "C" { #endif +extern const char current_namespace[]; +extern const char settings_partition[]; bool isNameValid(char * key); esp_err_t store_nvs_value_len(nvs_type_t type, const char *key, void * data, size_t data_len); esp_err_t store_nvs_value(nvs_type_t type, const char *key, void * data); @@ -11,6 +13,7 @@ esp_err_t get_nvs_value(nvs_type_t type, const char *key, void*value, const uint void * get_nvs_value_alloc(nvs_type_t type, const char *key); esp_err_t erase_nvs(const char *key); void * get_nvs_value_alloc_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size); +void nvs_value_set_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size); #ifdef __cplusplus } #endif diff --git a/main/platform_esp32.h b/main/platform_esp32.h index 786c932d..3443e069 100644 --- a/main/platform_esp32.h +++ b/main/platform_esp32.h @@ -22,6 +22,9 @@ #pragma once #include "esp_pthread.h" +#ifndef SQUEEZELITE_ESP32_RELEASE_URL +#define SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases" +#endif extern void run_command(char * line); extern bool wait_for_wifi(); diff --git a/partitions.csv b/partitions.csv index 086865b4..5e4118dd 100644 --- a/partitions.csv +++ b/partitions.csv @@ -4,4 +4,5 @@ nvs, data, nvs, 0x9000, 0x4000, otadata, data, ota, 0xD000, 0x2000, phy_init, data, phy, 0xF000, 0x1000, recovery, app, factory, 0x10000, 0x140000, -ota_0, app, ota_0, 0x150000, 0x2B0000, +ota_0, app, ota_0, 0x150000, 0x2A0000, +settings, data, nvs, 0x3F0000, 0x10000,