瀏覽代碼

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.
Sebastien 5 年之前
父節點
當前提交
b6f1ce9a7a

+ 0 - 0
build-scripts/SqueezeAmp4MBFlash-sdkconfig.defaults → build-scripts/SqueezeAmp-sdkconfig.defaults


+ 5 - 33
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>", "namespace to be erased");
     erase_all_args.end = arg_end(2);
 
-    namespace_args.namespace = arg_str1(NULL, NULL, "<namespace>", "namespace of the partition to be selected");
-    namespace_args.end = arg_end(2);
     list_args.partition = arg_str1(NULL, NULL, "<partition>", "partition name");
     list_args.namespace = arg_str0("n", "namespace", "<namespace>", "namespace name");
     list_args.type = arg_str0("t", "type", "<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

+ 2 - 1
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

+ 22 - 13
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()

+ 5 - 14
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 */

+ 1 - 1
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/

+ 2 - 2
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/	

+ 8 - 8
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

+ 14 - 16
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");
+	}
 }

+ 5 - 2
components/squeezelite/embedded.h

@@ -1,6 +1,6 @@
 #ifndef EMBEDDED_H
 #define EMBEDDED_H
-
+#include "esp_system.h"
 #include <inttypes.h>
 
 /* 	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);
 				   

+ 4 - 1
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);

+ 2 - 0
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/
 
+
+

+ 14 - 16
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) {

+ 17 - 74
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);
 
-	/* 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);
+	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 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));
+	else {
+		free(release_url);
 	}
-	return value;
+	/* start wifi manager task */
+	xTaskCreate(&wifi_manager, "wifi_manager", 4096, NULL, WIFI_MANAGER_TASK_PRIORITY, &task_wifi_manager);
 
 }
 
 
-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());
 				}
 

+ 0 - 7
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.

+ 1 - 1
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()

+ 2 - 0
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

+ 47 - 3
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();

+ 9 - 3
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){

+ 3 - 0
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

+ 3 - 0
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();

+ 2 - 1
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,