Просмотр исходного кода

Update webpack and web ui to recent versions, bug fixes

Sebastien L 3 лет назад
Родитель
Сommit
977935015e
39 измененных файлов с 536 добавлено и 433 удалено
  1. 2 0
      .gitignore
  2. 60 0
      components/platform_config/platform_config.c
  3. 4 1
      components/platform_config/platform_config.h
  4. 127 132
      components/platform_console/cmd_config.c
  5. 30 0
      components/platform_console/cmd_system.c
  6. 1 1
      components/platform_console/platform_console.c
  7. 7 5
      components/wifi-manager/http_server_handlers.c
  8. 1 5
      components/wifi-manager/http_server_handlers.h
  9. 9 12
      components/wifi-manager/network_manager.c
  10. 1 1
      components/wifi-manager/network_manager.h
  11. 0 2
      components/wifi-manager/network_manager_handlers.c
  12. 35 63
      components/wifi-manager/network_status.c
  13. 29 0
      components/wifi-manager/webapp/.vscode/tasks.json
  14. 6 0
      components/wifi-manager/webapp/dist/css/index.04bd6e438114e559773d.css
  15. BIN
      components/wifi-manager/webapp/dist/css/index.04bd6e438114e559773d.css.gz
  16. 0 6
      components/wifi-manager/webapp/dist/css/index.5712d0365318b239ca44.css
  17. BIN
      components/wifi-manager/webapp/dist/css/index.5712d0365318b239ca44.css.gz
  18. 0 0
      components/wifi-manager/webapp/dist/css/index.5712d0365318b239ca44.css.map
  19. 0 0
      components/wifi-manager/webapp/dist/index.html
  20. BIN
      components/wifi-manager/webapp/dist/index.html.gz
  21. 0 0
      components/wifi-manager/webapp/dist/js/index.41c7e6.bundle.js.map
  22. 0 1
      components/wifi-manager/webapp/dist/js/index.79297e.bundle.js
  23. 0 0
      components/wifi-manager/webapp/dist/js/index.79297e.bundle.js.LICENSE.txt
  24. BIN
      components/wifi-manager/webapp/dist/js/index.79297e.bundle.js.gz
  25. 0 1
      components/wifi-manager/webapp/dist/src/test.d.ts
  26. 2 2
      components/wifi-manager/webapp/mock/ap.json
  27. 3 3
      components/wifi-manager/webapp/mock/commands.json
  28. 1 0
      components/wifi-manager/webapp/package.json
  29. 2 2
      components/wifi-manager/webapp/src/index.ejs
  30. 143 135
      components/wifi-manager/webapp/src/js/custom.js
  31. 3 6
      components/wifi-manager/webapp/src/sass/main.scss
  32. 3 0
      components/wifi-manager/webapp/src/sass/utils/_variables.scss
  33. 1 1
      components/wifi-manager/webapp/src/test.ts
  34. 2 3
      components/wifi-manager/webapp/webapp.cmake
  35. 10 15
      components/wifi-manager/webapp/webpack.c
  36. 37 35
      components/wifi-manager/webapp/webpack.config.js
  37. 1 1
      components/wifi-manager/webapp/webpack.h
  38. 1 0
      components/wifi-manager/webapp/webpack/webpack.dev.js
  39. 15 0
      sdkconfig

+ 2 - 0
.gitignore

@@ -102,3 +102,5 @@ esp-dsp/
 
 
 components/wifi-manager/network_manager_handlers.multi
+
+components/wifi-manager/UML-State-Machine-in-C

+ 60 - 0
components/platform_config/platform_config.c

@@ -620,6 +620,31 @@ void config_delete_key(const char *key){
 void * config_alloc_get(nvs_type_t nvs_type, const char *key) {
 	return config_alloc_get_default(nvs_type, key, NULL, 0);
 }
+cJSON * config_alloc_get_cjson(const char *key){
+	char * conf_str = config_alloc_get_default(NVS_TYPE_STR, key, NULL, 0);
+	if(conf_str==NULL){
+		ESP_LOGE(TAG, "Unable to get config value for key [%s]", key);
+		return NULL;
+	}
+	cJSON * conf_json = cJSON_Parse(conf_str);
+	free(conf_str);
+	if(conf_json==NULL){
+		ESP_LOGE(TAG, "Unable to parse config value for key [%s]", key);
+		return NULL;
+	}
+	return conf_json;
+}
+esp_err_t config_set_cjson_str(const char *key, cJSON *value){
+	char * value_str = cJSON_PrintUnformatted(value);
+	if(value_str==NULL){
+		ESP_LOGE(TAG, "Unable to print cJSON for key [%s]", key);
+		return ESP_ERR_INVALID_ARG;
+	}
+	esp_err_t err = config_set_value(NVS_TYPE_STR,key, value_str);
+	free(value_str);
+	cJSON_Delete(value);
+	return err;
+}
 void config_get_uint16t_from_str(const char *key, uint16_t *value, uint16_t default_value){
 	char * str_value = config_alloc_get(NVS_TYPE_STR, key);
 	if(str_value == NULL){
@@ -725,7 +750,42 @@ esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, const void * va
 	config_unlock();
 	return result;
 }
+cJSON* cjson_update_string(cJSON** root, const char* key, const char* value) {
+	if (*root == NULL) {
+		*root = cJSON_CreateObject();
+		if (*root == NULL) {
+			ESP_LOGE(TAG, "Error creating cJSON object!");
+		}
+	}
+	if (!key || !value || strlen(key) == 0) {
+		ESP_LOGE(TAG, "cjson_update_string. Invalid key or value passed! key: %s, value: %s", STR_OR_ALT(key, ""), STR_OR_ALT(value, ""));
+		return *root;
+	}
+	cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
+	if (cjsonvalue && strcasecmp(cJSON_GetStringValue(cjsonvalue), value) != 0) {
+		ESP_LOGD(TAG, "Value %s changed from %s to %s", key, cJSON_GetStringValue(cjsonvalue), value);
+		cJSON_SetValuestring(cjsonvalue, value);
+	} else if(!cjsonvalue){
+		ESP_LOGD(TAG, "Adding new value %s: %s", key, value);
+		cJSON_AddItemToObject(*root, key, cJSON_CreateString(value));
+	}
+    return *root;
+}
+cJSON* cjson_update_number(cJSON** root, const char* key, int value) {
 
+	if (*root == NULL) {
+		*root = cJSON_CreateObject();
+	}
+	if (key  && strlen(key) != 0) {
+		cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
+		if (cjsonvalue) {
+			cJSON_SetNumberValue(cjsonvalue, value);
+		} else {
+			cJSON_AddNumberToObject(*root, key, value);
+		}
+	}
+    return *root;
+}
 IMPLEMENT_SET_DEFAULT(uint8_t,NVS_TYPE_U8);
 IMPLEMENT_SET_DEFAULT(int8_t,NVS_TYPE_I8);
 IMPLEMENT_SET_DEFAULT(uint16_t,NVS_TYPE_U16);

+ 4 - 1
components/platform_config/platform_config.h

@@ -52,6 +52,8 @@ void config_start_timer();
 void config_init();
 void * config_alloc_get_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size);
 void * config_alloc_get_str(const char *key, char *lead, char *fallback);
+cJSON * config_alloc_get_cjson(const char *key);
+esp_err_t config_set_cjson_str(const char *key, cJSON *value);
 void config_get_uint16t_from_str(const char *key, uint16_t *value, uint16_t default_value);
 void config_delete_key(const char *key);
 void config_set_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size);
@@ -61,7 +63,8 @@ char * config_alloc_get_json(bool bFormatted);
 esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, const void * value);
 nvs_type_t  config_get_item_type(cJSON * entry);
 void * config_safe_alloc_get_entry_value(nvs_type_t nvs_type, cJSON * entry);
-
+cJSON* cjson_update_number(cJSON** root, const char* key, int value);
+cJSON* cjson_update_string(cJSON** root, const char* key, const char* value);
 #ifdef __cplusplus
 }
 #endif

+ 127 - 132
components/platform_console/cmd_config.c

@@ -23,6 +23,7 @@
 
 const char * desc_squeezelite ="Squeezelite Options";
 const char * desc_dac= "DAC Options";
+const char * desc_cspotc= "Spotify (cSpot) Options";
 const char * desc_preset= "Preset Options";
 const char * desc_spdif= "SPDIF Options";
 const char * desc_audio= "General Audio Options";
@@ -114,7 +115,12 @@ static struct{
 //		struct arg_dbl *control_delay;
 		struct arg_end *end;
 } bt_source_args;
-
+static struct {
+	struct arg_str *deviceName;
+//	struct arg_int *volume;
+	struct arg_int *bitrate;
+	struct arg_end *end;
+} cspot_args;
 static struct {
     struct arg_int *clock;
     struct arg_int *wordselect;
@@ -586,6 +592,49 @@ static int is_valid_gpio_number(int gpio, const char * name, FILE *f, bool manda
 	}
 	return 0;
 }
+static int do_cspot_config(int argc, char **argv){
+	char * name = NULL;
+    int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&cspot_args);
+    if (nerrors != 0) {
+        return 1;
+    }
+
+	char *buf = NULL;
+	size_t buf_size = 0;
+	FILE *f = open_memstream(&buf, &buf_size);
+	if (f == NULL) {
+		cmd_send_messaging(argv[0],MESSAGING_ERROR,"Unable to open memory stream.");
+		return 1;
+	}
+
+	cJSON * cspot_config = config_alloc_get_cjson("cspot_config");
+	if(!cspot_config){
+		nerrors++;
+		fprintf(f,"error: Unable to get cspot config.\n");
+	}
+	else {
+		cjson_update_string(&cspot_config,cspot_args.deviceName->hdr.longopts,cspot_args.deviceName->count>0?cspot_args.deviceName->sval[0]:NULL);
+//		cjson_update_number(&cspot_config,cspot_args.volume->hdr.longopts,cspot_args.volume->count>0?cspot_args.volume->ival[0]:0);
+		cjson_update_number(&cspot_config,cspot_args.bitrate->hdr.longopts,cspot_args.bitrate->count>0?cspot_args.bitrate->ival[0]:0);
+	}
+	
+	if(!nerrors ){
+		fprintf(f,"Storing cspot parameters.\n");
+		nerrors+=(config_set_cjson_str("cspot_config",cspot_config) !=ESP_OK);
+	}
+	if(nerrors==0){
+		fprintf(f,"Device name changed to %s\n",name);
+	}
+	if(!nerrors ){
+		fprintf(f,"Done.\n");
+	}
+	FREE_AND_NULL(name);
+	fflush (f);
+	cmd_send_messaging(argv[0],nerrors>0?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf);
+	fclose(f);
+	FREE_AND_NULL(buf);
+	return nerrors;
+}
 static int do_i2s_cmd(int argc, char **argv)
 {
 	i2s_platform_config_t i2s_dac_pin = {
@@ -679,22 +728,46 @@ cJSON * example_cb(){
 }
 
 cJSON * known_model_cb(){
-	const char * key="preset_name";
 	cJSON * values = cJSON_CreateObject();
 	if(!values){
 		ESP_LOGE(TAG,"known_model_cb: Failed to create JSON object");
 		return NULL;
 	}
-	char * name = config_alloc_get_default(NVS_TYPE_STR,key,"",0);
+	char * name = config_alloc_get_default(NVS_TYPE_STR,known_model_args.model_config->hdr.longopts,"",0);
 	if(!name){
-		ESP_LOGE(TAG,"Failed to get board model from nvs key %s ",key);
+		ESP_LOGE(TAG,"Failed to get board model from nvs key %s ",known_model_args.model_config->hdr.longopts);
 	}
 	else {
 		cJSON_AddStringToObject(values,known_model_args.model_config->hdr.longopts,name);
 	}
 	return values;
 }
-
+cJSON * cspot_cb(){
+	cJSON * values = cJSON_CreateObject();
+	if(!values){
+		ESP_LOGE(TAG,"cspot_cb: Failed to create JSON object");
+		return NULL;
+	}
+	cJSON * cspot_config = config_alloc_get_cjson("cspot_config");
+	if(!cspot_config){
+		ESP_LOGE(TAG,"cspot_cb: Failed to get cspot config");
+		return NULL;
+	}
+	cJSON * cspot_values = cJSON_GetObjectItem(cspot_config,cspot_args.deviceName->hdr.longopts);
+	if(cspot_values){
+		cJSON_AddStringToObject(values,cspot_args.deviceName->hdr.longopts,cJSON_GetStringValue(cspot_values));
+	}
+	cspot_values = cJSON_GetObjectItem(cspot_config,cspot_args.bitrate->hdr.longopts);
+	if(cspot_values){
+		cJSON_AddNumberToObject(values,cspot_args.bitrate->hdr.longopts,cJSON_GetNumberValue(cspot_values));
+	}
+	// cspot_values = cJSON_GetObjectItem(cspot_config,cspot_args.volume->hdr.longopts);
+	// if(cspot_values){
+	// 	cJSON_AddNumberToObject(values,cspot_args.volume->hdr.longopts,cJSON_GetNumberValue(cspot_values));
+	// }
+	cJSON_Delete(cspot_config);
+	return values;
+}
 cJSON * i2s_cb(){
 	cJSON * values = cJSON_CreateObject();
 
@@ -956,85 +1029,6 @@ void replace_char_in_string(char * str, char find, char replace){
 		}
 	}
 }
-
-// static cJSON * get_known_configurations(FILE * f){
-// #ifndef CONFIG_SQUEEZEAMP 
-// 	#define err1_msg "Failed to parse known_configs json.  %s\nError at:\n%s"
-// 	#define err2_msg "Known configs should be an array and it is not: \n%s"
-
-
-// 	const char * known_configs_string = (const char *)_presets_json_start;
-	
-// 	if(!known_configs_string || strlen(known_configs_string)==0){
-// 		return NULL;
-// 	}
-// 	cJSON * known_configs_json = cJSON_Parse(known_configs_string);
-// 	if(!known_configs_json){
-// 		if(f){
-// 			fprintf(f,err1_msg,known_configs_string,STR_OR_BLANK(cJSON_GetErrorPtr()));
-// 		}
-// 		else {
-// 			ESP_LOGE(TAG,err1_msg,known_configs_string,STR_OR_BLANK(cJSON_GetErrorPtr()));
-// 		}
-// 		return NULL;
-// 	}
-// 	else {
-// 		if(!cJSON_IsArray(known_configs_json)){
-// 			if(f){
-// 				fprintf(f,err2_msg,STR_OR_BLANK(cJSON_GetErrorPtr()));
-// 			}
-// 			else {
-// 				ESP_LOGE(TAG,err2_msg,STR_OR_BLANK(cJSON_GetErrorPtr()));
-// 			}
-// 			cJSON_Delete(known_configs_json);
-// 			return NULL;
-// 		}
-		
-// 	}
-// 	return known_configs_json;
-// #else
-// 	return NULL;
-// #endif
-
-// }
-
-// static  cJSON * find_known_model_name(cJSON * root,const char * name, FILE * f, bool * found){
-// 	if(found){
-// 		*found = false;
-// 	}
-// 	if(!root){
-// 		return NULL;
-// 	}
-// 	cJSON * item;
-// 	cJSON_ArrayForEach(item, root){
-// 		if(cJSON_IsObject(item)){
-// 			cJSON * model = cJSON_GetObjectItem(item,"name");
-// 			if(model && cJSON_IsString(model) && strcmp(cJSON_GetStringValue(model),name)==0){
-// 				if(found){
-// 					*found = true;
-// 				}
-// 				return item;
-// 			}
-// 		}
-// 	}
-// 	return NULL;
-// }
-// static esp_err_t is_known_model_name(const char * name, FILE * f, bool * found){
-// 	esp_err_t err = ESP_OK;
-// 	if(found){
-// 		*found = false;
-// 	}
-// 	cJSON * known_configs_json = get_known_configurations(f);
-// 	if(known_configs_json){
-// 		cJSON * known_item = find_known_model_name(known_configs_json,name,f,found);
-// 		if(known_item && found){
-// 			*found = true;
-// 		}
-// 		cJSON_Delete(known_configs_json);
-// 	}
-// 	return err;
-// }
-	
 static esp_err_t save_known_config(cJSON * known_item, const char * name,FILE * f){
 	esp_err_t err = ESP_OK;
 	char * json_string=NULL;
@@ -1050,14 +1044,14 @@ static esp_err_t save_known_config(cJSON * known_item, const char * name,FILE *
 		cJSON_ArrayForEach(kvp, config_array){
 			cJSON * kvp_value=kvp->child;
 			if(!kvp_value){
-				ESP_LOGE(TAG,"config entry is not an object!");
+				printf("config entry is not an object!\n");
 				err=ESP_FAIL;
 				continue;
 			}
 			char * key = kvp_value->string;
 			char * value = kvp_value->valuestring;
 			if(!key || !value || strlen(key)==0){
-				ESP_LOGE(TAG,"Invalid config entry %s:%s",STR_OR_BLANK(key),STR_OR_BLANK(value));
+				printf("Invalid config entry %s:%s\n",STR_OR_BLANK(key),STR_OR_BLANK(value));
 				err=ESP_FAIL;
 				continue;
 			}
@@ -1065,7 +1059,7 @@ static esp_err_t save_known_config(cJSON * known_item, const char * name,FILE *
 			fprintf(f,"Storing %s=%s\n",key,value);
 			err = config_set_value(NVS_TYPE_STR,key,value);
 			if(err){
-				fprintf(f,"Failed: %s\n",esp_err_to_name(err));
+				fprintf(f,"Failed to store config value: %s\n",esp_err_to_name(err));
 				break;
 			}
 		}
@@ -1090,45 +1084,6 @@ static esp_err_t save_known_config(cJSON * known_item, const char * name,FILE *
 	return err;
 }
 
-// char * config_dac_alloc_print_known_config(){
-// 	cJSON * item=NULL;
-// 	char * dac_list=NULL;
-// 	size_t total_len=0;
-// 	cJSON * object = get_known_configurations(NULL);
-// 	if(!object){
-// 		return strdup_psram("");
-// 	}
-// 	// loop through all items, and concatenate model name separated with |
-	
-// 	cJSON_ArrayForEach(item, object){
-// 		if(cJSON_IsObject(item)){
-// 			cJSON * model = cJSON_GetObjectItem(item,"name");
-// 			if(model && cJSON_IsString(model)){
-// 				total_len+=strlen(model->valuestring)+1;
-// 			}
-// 		}
-// 	}
-// 	if(total_len==0){
-// 		ESP_LOGI(TAG,"No known configs found");
-// 		cJSON_Delete(object);
-// 		return NULL;
-// 	}
-// 	dac_list = malloc_init_external(total_len+1);
-// 	if(dac_list){
-// 		cJSON_ArrayForEach(item, object){
-// 			if(cJSON_IsObject(item)){
-// 				cJSON * model = cJSON_GetObjectItem(item,"name");
-// 				if(model && cJSON_IsString(model)){
-// 					strcat(dac_list,model->valuestring);
-// 					strcat(dac_list,"|");
-// 				}
-// 			}
-// 		}
-// 	}
-// 	dac_list[strlen(dac_list)-1]='\0';
-// 	cJSON_Delete(object);
-// 	return dac_list;
-// }
 static int do_register_known_templates_config(int argc, char **argv){
 	esp_err_t err=ESP_OK;
 	int nerrors = arg_parse(argc, argv,(void **)&known_model_args);
@@ -1144,20 +1099,43 @@ static int do_register_known_templates_config(int argc, char **argv){
 		arg_print_errors(f,known_model_args.end,desc_preset);
 	}
 	else {
-		cJSON * known_item = cJSON_Parse(known_model_args.model_config->sval[0]);
+		ESP_LOGD(TAG,"arg: %s",STR_OR_BLANK(known_model_args.model_config->sval[0]));
+		char * model_config = strdup_psram(known_model_args.model_config->sval[0]);
+		char * t = model_config;
+		for(const char * p=known_model_args.model_config->sval[0];*p;p++){
+			if(*p=='\\' && *(p+1)=='"'){
+				*t++='"';
+				p++;
+			}
+			else {
+				*t++=*p;
+			}
+		}
+		*t=0;
+		cJSON * known_item = cJSON_Parse(model_config);
 		if(known_item){
+			ESP_LOGD(TAG,"Parsing success");
 			config_name= cJSON_GetObjectItem(known_item,"name");
-			nerrors+=(err = save_known_config(known_item,config_name,f)!=ESP_OK);
+			if(!config_name || !cJSON_IsString(config_name) || strlen(config_name->valuestring)==0){
+				fprintf(f,"Failed to find name in config\n");
+				err=ESP_FAIL;
+				nerrors++;
+			}
 			if(nerrors==0){
-				const i2s_platform_config_t * i2s_config= config_dac_get();
-				if(i2s_config->scl!=-1 && i2s_config->sda!=-1 && GPIO_IS_VALID_GPIO(i2s_config->scl) && GPIO_IS_VALID_GPIO(i2s_config->sda)){
-					fprintf(f,"Scanning i2c bus for devices\n");
-					cmd_i2ctools_scan_bus(f,i2s_config->sda, i2s_config->scl);
+				const char * name = cJSON_GetStringValue(config_name);
+				nerrors+=(err = save_known_config(known_item,name,f)!=ESP_OK);
+				if(nerrors==0){
+					const i2s_platform_config_t * i2s_config= config_dac_get();
+					if(i2s_config->scl!=-1 && i2s_config->sda!=-1 && GPIO_IS_VALID_GPIO(i2s_config->scl) && GPIO_IS_VALID_GPIO(i2s_config->sda)){
+						fprintf(f,"Scanning i2c bus for devices\n");
+						cmd_i2ctools_scan_bus(f,i2s_config->sda, i2s_config->scl);
+					}
 				}
 			}
 			cJSON_Delete(known_item);
 		}
 		else {
+			ESP_LOGE(TAG,"Parsing error: %s",cJSON_GetErrorPtr());
 			fprintf(f,"Failed to parse JSON: %s\n",cJSON_GetErrorPtr());
 			err=ESP_FAIL;
 		}
@@ -1193,6 +1171,22 @@ static void register_known_templates_config(){
     cmd_to_json_with_cb(&cmd,&known_model_cb);
     ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
 }
+
+static void register_cspot_config(){
+	cspot_args.deviceName = arg_str1(NULL,"deviceName","","Device Name");
+	cspot_args.bitrate = arg_int1(NULL,"bitrate","96|160|320","Streaming Bitrate (kbps)");
+//	cspot_args.volume = arg_int1(NULL,"volume","","Spotify Volume");
+	cspot_args.end = arg_end(1);
+	 const esp_console_cmd_t cmd = {
+		.command = CFG_TYPE_SYST("cspot"),
+		.help = desc_cspotc,
+		.hint = NULL,
+		.func = &do_cspot_config,
+		.argtable = &cspot_args
+	};
+	cmd_to_json_with_cb(&cmd,&cspot_cb);
+	ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
+}
 static void register_i2s_config(void){
 	i2s_args.model_name = arg_str1(NULL,"model_name",STR_OR_BLANK(get_dac_list()),"DAC Model Name");
 	i2s_args.clear = arg_lit0(NULL, "clear", "Clear configuration");
@@ -1335,6 +1329,7 @@ void register_config_cmd(void){
 	if(!is_dac_config_locked()){
 	 	 register_known_templates_config();
 	}
+	register_cspot_config();
 	register_audio_config();
 //	register_squeezelite_config();
 	register_bt_source_config();

+ 30 - 0
components/platform_console/cmd_system.c

@@ -346,6 +346,35 @@ typedef enum {
     SCANNING,
     PROCESSING_NAME
 } scanstate_t;
+int set_cspot_player_name(FILE * f,const char * name){
+    int ret=0;
+    cJSON * cspot_config = config_alloc_get_cjson("cspot_config");
+    if(cspot_config==NULL){
+        fprintf(f,"Unable to get cspot_config\n");
+        return 1;
+    }
+    cJSON * player_name = cJSON_GetObjectItemCaseSensitive(cspot_config,"deviceName");
+    if(player_name==NULL){
+        fprintf(f,"Unable to get deviceName\n");
+        ret=1;
+    }
+    if(strcmp(player_name->valuestring,name)==0){
+        fprintf(f,"CSpot device name not changed.\n");
+        ret=0;
+    }
+    else{
+        cJSON_SetValuestring(player_name,name);
+        if(setnamevar("cspot_config",f,cJSON_Print(cspot_config))!=0){
+            fprintf(f,"Unable to set cspot_config\n");
+            ret=1;
+        }
+        else{
+            fprintf(f,"CSpot device name set to %s\n",name);
+        }
+    }
+    cJSON_Delete(cspot_config);
+    return ret;
+}
 int set_squeezelite_player_name(FILE * f,const char * name){
 	char * nvs_config= config_alloc_get(NVS_TYPE_STR, "autoexec1");
 	char **argv = NULL;
@@ -442,6 +471,7 @@ static int setdevicename(int argc, char **argv)
 	nerrors+=setnamevar("bt_name", f, name);
 	nerrors+=setnamevar("host_name", f, name);
     nerrors+=set_squeezelite_player_name(f, name);
+    nerrors+=set_cspot_player_name(f, name);
 	if(nerrors==0){
 		fprintf(f,"Device name changed to %s\n",name);
 	}

+ 1 - 1
components/platform_console/platform_console.c

@@ -40,7 +40,7 @@ extern void register_squeezelite();
 
 static EXT_RAM_ATTR QueueHandle_t uart_queue;
 static EXT_RAM_ATTR struct {
-		uint8_t _buf[128];
+		uint8_t _buf[512];
 		StaticRingbuffer_t _ringbuf;
 		RingbufHandle_t handle;
 		QueueSetHandle_t queue_set;

+ 7 - 5
components/wifi-manager/http_server_handlers.c

@@ -3,7 +3,6 @@ Copyright (c) 2017-2021 Sebastien L
 */
 
 #include "http_server_handlers.h"
-
 #include "esp_http_server.h"
 #include "cmd_system.h"
 #include <inttypes.h>
@@ -302,8 +301,11 @@ static esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filena
         return httpd_resp_set_type(req, "text/javascript");
     } else if (IS_FILE_EXT(filename, ".json")) {
         return httpd_resp_set_type(req, HTTPD_TYPE_JSON);
+    } else if (IS_FILE_EXT(filename, ".map")) {
+        return httpd_resp_set_type(req, "map");
     }
 
+
     /* This is a limited set only */
     /* For any other type always set as plain text */
     return httpd_resp_set_type(req, "text/plain");
@@ -368,7 +370,6 @@ esp_err_t resource_filehandler(httpd_req_t *req){
    ESP_LOGD_LOC(TAG, "serving [%s]", req->uri);
 
    const char *filename = get_path_from_uri(filepath, req->uri, sizeof(filepath));
-
    if (!filename) {
 	   ESP_LOGE_LOC(TAG, "Filename is too long");
 	   /* Respond with 500 Internal Server Error */
@@ -382,7 +383,9 @@ esp_err_t resource_filehandler(httpd_req_t *req){
 	   return ESP_FAIL;
    }
 
-
+	if(strlen(filename) !=0 && IS_FILE_EXT(filename, ".map")){
+		return httpd_resp_sendstr(req, "");
+	}
 	int idx=-1;
 	if((idx=resource_get_index(filename))>=0){
 	    set_content_type_from_file(req, filename);
@@ -441,7 +444,6 @@ esp_err_t console_cmd_get_handler(httpd_req_t *req){
 }
 esp_err_t console_cmd_post_handler(httpd_req_t *req){
 	char success[]="{\"Result\" : \"Success\" }";
-	char failed[]="{\"Result\" : \"Failed\" }";
 	ESP_LOGD_LOC(TAG, "serving [%s]", req->uri);
 	//bool bOTA=false;
 	//char * otaURL=NULL;
@@ -482,7 +484,7 @@ esp_err_t console_cmd_post_handler(httpd_req_t *req){
 		// navigate to the first child of the config structure
 		char *cmd = cJSON_GetStringValue(item);
 		if(!console_push(cmd, strlen(cmd) + 1)){
-			httpd_resp_send(req, (const char *)failed, strlen(failed));
+			httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Unable to push command for execution");
 		}
 		else {
 			httpd_resp_send(req, (const char *)success, strlen(success));

+ 1 - 5
components/wifi-manager/http_server_handlers.h

@@ -46,11 +46,7 @@ extern "C" {
 
 esp_err_t root_get_handler(httpd_req_t *req);
 esp_err_t resource_filehandler(httpd_req_t *req);
-esp_err_t resource_filehandler(httpd_req_t *req);
-esp_err_t resource_filehandler(httpd_req_t *req);
-esp_err_t resource_filehandler(httpd_req_t *req);
-esp_err_t resource_filehandler(httpd_req_t *req);
-esp_err_t resource_filehandler(httpd_req_t *req);
+
 esp_err_t ap_get_handler(httpd_req_t *req);
 esp_err_t config_get_handler(httpd_req_t *req);
 esp_err_t config_post_handler(httpd_req_t *req);

+ 9 - 12
components/wifi-manager/network_manager.c

@@ -670,28 +670,25 @@ esp_err_t network_get_hostname(const char** hostname) {
 }
 
 void network_set_timer(uint16_t duration, const char * tag) {
-    if(NM.timer_tag){
-        ESP_LOGD(TAG,"Cancelling timer %s",NM.timer_tag);
-        FREE_AND_NULL(NM.timer_tag);
-        NM.timer_tag = NULL;
-    }
     if (duration > 0) {
+        if(tag){
+            ESP_LOGD(TAG, "Setting timer tag to %s", tag);
+            NM.timer_tag = strdup_psram(tag);
+        }
         if (!NM.state_timer) {
-            ESP_LOGD(TAG, "Starting new pulse check timer with period of %u ms.", duration);
+            ESP_LOGD(TAG, "Starting %s timer with period of %u ms.", STR_OR_ALT(NM.timer_tag,"anonymous"), duration);
             NM.state_timer = xTimerCreate("background STA", pdMS_TO_TICKS(duration), pdFALSE, NULL, network_timer_cb);
         } else {
-            ESP_LOGD(TAG, "Changing the pulse timer period to %u ms.", duration);
+            ESP_LOGD(TAG, "Changing %s timer period to %u ms.", STR_OR_ALT(NM.timer_tag,"anonymous"),duration);
             xTimerChangePeriod(NM.state_timer, pdMS_TO_TICKS(duration), portMAX_DELAY);
         }
         xTimerStart(NM.state_timer, portMAX_DELAY);
     } else if (NM.state_timer) {
-        ESP_LOGD(TAG, "Stopping timer");
+        ESP_LOGD(TAG,"Stopping timer %s",STR_OR_ALT(NM.timer_tag,"anonymous"));
         xTimerStop(NM.state_timer, portMAX_DELAY);
+        FREE_AND_NULL(NM.timer_tag);
     }
-    if(tag){
-        ESP_LOGD(TAG, "Setting timer tag to %s", tag);
-        NM.timer_tag = strdup_psram(tag);
-    }
+
 }
 void network_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
     ip_event_got_ip_t* s = NULL;

+ 1 - 1
components/wifi-manager/network_manager.h

@@ -83,7 +83,7 @@ typedef struct
     uint16_t dhcp_timeout;
     uint16_t wifi_dhcp_fail_ms;    
 	queue_message * event_parameters;
-    const char * timer_tag;
+    char * timer_tag;
 } network_t;
 
 

+ 0 - 2
components/wifi-manager/network_manager_handlers.c

@@ -224,8 +224,6 @@ static state_machine_result_t NETWORK_INSTANTIATED_STATE_handler(state_machine_t
     network_t* const nm = (network_t *)State_Machine;
     State_Machine->State = &network_states[NETWORK_INSTANTIATED_STATE];
     State_Machine->Event = EN_START;
-      char * valuestr=NULL;
-
     config_get_uint16t_from_str("pollmx",&nm->sta_polling_max_ms,600);
     nm->sta_polling_max_ms = nm->sta_polling_max_ms * 1000;
     config_get_uint16t_from_str("apdelay",&nm->ap_duration_ms,20);

+ 35 - 63
components/wifi-manager/network_status.c

@@ -187,40 +187,14 @@ void network_status_update_basic_info() {
     // locking happens below this level
     network_status_get_basic_info(&ip_info_cjson);
 }
-cJSON* network_status_update_string(cJSON** root, const char* key, const char* value) {
-    if (network_status_lock_json_buffer(portMAX_DELAY)) {
-        if (*root == NULL) {
-            *root = cJSON_CreateObject();
-            if (*root == NULL) {
-                ESP_LOGE(TAG, "Error creating cJSON object!");
-            }
-        }
 
-        if (!key || !value || strlen(key) == 0) {
-            ESP_LOGE(TAG, "network_status_update_string. Invalid key or value passed! key: %s, value: %s", STR_OR_ALT(key, ""), STR_OR_ALT(value, ""));
-            network_status_unlock_json_buffer();
-            return *root;
-        }
-        cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
-        if (cjsonvalue && strcasecmp(cJSON_GetStringValue(cjsonvalue), value) != 0) {
-            ESP_LOGD(TAG, "Value %s changed from %s to %s", key, cJSON_GetStringValue(cjsonvalue), value);
-            cJSON_SetValuestring(cjsonvalue, value);
-        } else if(!cjsonvalue){
-            cJSON_AddItemToObject(*root, key, cJSON_CreateString(value));
-        }
-        network_status_unlock_json_buffer();
-    } else {
-        ESP_LOGW(TAG, "Unable to lock status json buffer. ");
-    }
-    return *root;
-}
-cJSON* network_status_update_number(cJSON** root, const char* key, int value) {
+cJSON* network_status_update_float(cJSON** root, const char* key, float value) {
     if (network_status_lock_json_buffer(portMAX_DELAY)) {
         if (*root == NULL) {
             *root = cJSON_CreateObject();
         }
 
-        if (key  && strlen(key) != 0) {
+        if (key && strlen(key) != 0) {
             cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
             if (cjsonvalue) {
                 cJSON_SetNumberValue(cjsonvalue, value);
@@ -234,7 +208,7 @@ cJSON* network_status_update_number(cJSON** root, const char* key, int value) {
     }
     return *root;
 }
-cJSON* network_status_update_float(cJSON** root, const char* key, float value) {
+cJSON* network_status_update_bool(cJSON** root, const char* key, bool value) {
     if (network_status_lock_json_buffer(portMAX_DELAY)) {
         if (*root == NULL) {
             *root = cJSON_CreateObject();
@@ -243,9 +217,9 @@ cJSON* network_status_update_float(cJSON** root, const char* key, float value) {
         if (key && strlen(key) != 0) {
             cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
             if (cjsonvalue) {
-                cJSON_SetNumberValue(cjsonvalue, value);
+                cjsonvalue->type = value ? cJSON_True : cJSON_False;
             } else {
-                cJSON_AddNumberToObject(*root, key, value);
+                cJSON_AddBoolToObject(*root, key, value);
             }
         }
         network_status_unlock_json_buffer();
@@ -254,20 +228,18 @@ cJSON* network_status_update_float(cJSON** root, const char* key, float value) {
     }
     return *root;
 }
-cJSON* network_status_update_bool(cJSON** root, const char* key, bool value) {
+cJSON * network_update_cjson_string(cJSON** root, const char* key, const char* value){
     if (network_status_lock_json_buffer(portMAX_DELAY)) {
-        if (*root == NULL) {
-            *root = cJSON_CreateObject();
-        }
-
-        if (key && strlen(key) != 0) {
-            cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
-            if (cjsonvalue) {
-                cjsonvalue->type = value ? cJSON_True : cJSON_False;
-            } else {
-                cJSON_AddBoolToObject(*root, key, value);
-            }
-        }
+        cjson_update_string(root, key, value);
+        network_status_unlock_json_buffer();
+    } else {
+        ESP_LOGW(TAG, "Unable to lock status json buffer. ");
+    }
+    return *root;
+}
+cJSON * network_update_cjson_number(cJSON** root, const char* key, int value){
+    if (network_status_lock_json_buffer(portMAX_DELAY)) {
+        cjson_update_number(root, key, value);
         network_status_unlock_json_buffer();
     } else {
         ESP_LOGW(TAG, "Unable to lock status json buffer. ");
@@ -280,20 +252,20 @@ cJSON* network_status_get_basic_info(cJSON** old) {
         monitor_gpio_t* mgpio = get_jack_insertion_gpio();
         const esp_app_desc_t* desc = esp_ota_get_app_description();
 
-        *old = network_status_update_string(old, "project_name", desc->project_name);
+        *old = network_update_cjson_string(old, "project_name", desc->project_name);
 #ifdef CONFIG_FW_PLATFORM_NAME
-        *old = network_status_update_string(old, "platform_name", CONFIG_FW_PLATFORM_NAME);
+        *old = network_update_cjson_string(old, "platform_name", CONFIG_FW_PLATFORM_NAME);
 #endif
-        *old = network_status_update_string(old, "version", desc->version);
+        *old = network_update_cjson_string(old, "version", desc->version);
         if (release_url != NULL)
-            *old = network_status_update_string(old, "release_url", release_url);
-        *old = network_status_update_number(old, "recovery", is_recovery_running ? 1 : 0);
+            *old = network_update_cjson_string(old, "release_url", release_url);
+        *old = network_update_cjson_number(old, "recovery", is_recovery_running ? 1 : 0);
         *old = network_status_update_bool(old, "Jack", mgpio->gpio >= 0 && jack_inserted_svc());
         *old = network_status_update_float(old, "Voltage", battery_value_svc());
-        *old = network_status_update_number(old, "disconnect_count", nm->num_disconnect);
+        *old = network_update_cjson_number(old, "disconnect_count", nm->num_disconnect);
         *old = network_status_update_float(old, "avg_conn_time", nm->num_disconnect > 0 ? (nm->total_connected_time / nm->num_disconnect) : 0);
-        *old = network_status_update_number(old, "bt_status", bt_app_source_get_a2d_state());
-        *old = network_status_update_number(old, "bt_sub_status", bt_app_source_get_media_state());
+        *old = network_update_cjson_number(old, "bt_status", bt_app_source_get_a2d_state());
+        *old = network_update_cjson_number(old, "bt_sub_status", bt_app_source_get_media_state());
 #if CONFIG_I2C_LOCKED
         *old = network_status_update_bool(old, "is_i2c_locked", true);
 #else
@@ -303,15 +275,15 @@ cJSON* network_status_get_basic_info(cJSON** old) {
             *old = network_status_update_bool(old, "eth_up", network_ethernet_is_up());
         }
         if (lms_server_cport > 0) {
-            *old = network_status_update_number(old, "lms_cport", lms_server_cport);
+            *old = network_update_cjson_number(old, "lms_cport", lms_server_cport);
         }
 
         if (lms_server_port > 0) {
-            *old = network_status_update_number(old, "lms_port", lms_server_port);
+            *old = network_update_cjson_number(old, "lms_port", lms_server_port);
         }
 
         if (strlen(lms_server_ip) > 0) {
-            *old = network_status_update_string(old, "lms_ip", lms_server_ip);
+            *old = network_update_cjson_string(old, "lms_ip", lms_server_ip);
         }
         ESP_LOGV(TAG, "network_status_get_basic_info done");
         network_status_unlock_json_buffer();
@@ -325,9 +297,9 @@ void network_status_update_address(cJSON* root, esp_netif_ip_info_t* ip_info) {
         ESP_LOGE(TAG, "Cannor update IP address. JSON structure or ip_info is null");
         return;
     }
-    network_status_update_string(&root, "ip", ip4addr_ntoa((ip4_addr_t*)&ip_info->ip));
-    network_status_update_string(&root, "netmask", ip4addr_ntoa((ip4_addr_t*)&ip_info->netmask));
-    network_status_update_string(&root, "gw", ip4addr_ntoa((ip4_addr_t*)&ip_info->gw));
+    network_update_cjson_string(&root, "ip", ip4addr_ntoa((ip4_addr_t*)&ip_info->ip));
+    network_update_cjson_string(&root, "netmask", ip4addr_ntoa((ip4_addr_t*)&ip_info->netmask));
+    network_update_cjson_string(&root, "gw", ip4addr_ntoa((ip4_addr_t*)&ip_info->gw));
 }
 void network_status_update_ip_info(update_reason_code_t update_reason_code) {
     ESP_LOGV(TAG, "network_status_update_ip_info called");
@@ -336,18 +308,18 @@ void network_status_update_ip_info(update_reason_code_t update_reason_code) {
         /* generate the connection info with success */
 
         ip_info_cjson = network_status_get_basic_info(&ip_info_cjson);
-        ip_info_cjson = network_status_update_number(&ip_info_cjson, "urc", update_reason_code);
+        ip_info_cjson = network_update_cjson_number(&ip_info_cjson, "urc", (int)update_reason_code);
         ESP_LOGD(TAG,"Updating ip info with reason code %d. Checking if Wifi interface is connected",update_reason_code);
         if (network_is_interface_connected(network_wifi_get_interface()) || update_reason_code == UPDATE_FAILED_ATTEMPT ) {
-            network_status_update_string(ip_info_cjson, "if", "wifi");
+            network_update_cjson_string(&ip_info_cjson, "if", "wifi");
             esp_netif_get_ip_info(network_wifi_get_interface(), &ip_info);
             network_status_update_address(ip_info_cjson, &ip_info);
             if (!network_wifi_is_ap_mode()) {
                 /* wifi is active, and associated to an AP */
                 wifi_ap_record_t ap;
                 esp_wifi_sta_get_ap_info(&ap);
-                network_status_update_string(&ip_info_cjson, "ssid", ((char*)ap.ssid));
-                network_status_update_number(&ip_info_cjson, "rssi", ap.rssi);
+                network_update_cjson_string(&ip_info_cjson, "ssid", ((char*)ap.ssid));
+                network_update_cjson_number(&ip_info_cjson, "rssi", ap.rssi);
             }
 
         } else {
@@ -356,7 +328,7 @@ void network_status_update_ip_info(update_reason_code_t update_reason_code) {
         }
         ESP_LOGD(TAG,"Checking if ethernet interface is connected");
         if (network_is_interface_connected(network_ethernet_get_interface())) {
-            network_status_update_string(ip_info_cjson, "if", "eth");
+            network_update_cjson_string(&ip_info_cjson, "if", "eth");
             esp_netif_get_ip_info(network_ethernet_get_interface(), &ip_info);
             network_status_update_address(ip_info_cjson, &ip_info);
         } 

+ 29 - 0
components/wifi-manager/webapp/.vscode/tasks.json

@@ -30,6 +30,35 @@
           }
         }
       },
+      {
+        "type": "npm",
+        "label": "webpack: prod server",
+        "script": "prod",
+        "promptOnClose": true,
+        "isBackground": true,
+        "problemMatcher": {
+          "owner": "webpack",
+          "severity": "error",
+          "fileLocation": "absolute",
+          "pattern": [
+            {
+              "regexp": "ERROR in (.*)",
+              "file": 1
+            },
+            {
+              "regexp": "\\((\\d+),(\\d+)\\):(.*)",
+              "line": 1,
+              "column": 2,
+              "message": 3
+            }
+          ],
+          "background": {
+            "activeOnStart": true,
+            "beginsPattern": "Compiling\\.\\.\\.",
+            "endsPattern": "Compiled successfully\\."
+          }
+        }
+      },
       {
         "type": "npm",
         "label": "webpack: build",

Разница между файлами не показана из-за своего большого размера
+ 6 - 0
components/wifi-manager/webapp/dist/css/index.04bd6e438114e559773d.css


BIN
components/wifi-manager/webapp/dist/css/index.04bd6e438114e559773d.css.gz


Разница между файлами не показана из-за своего большого размера
+ 0 - 6
components/wifi-manager/webapp/dist/css/index.5712d0365318b239ca44.css


BIN
components/wifi-manager/webapp/dist/css/index.5712d0365318b239ca44.css.gz


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
components/wifi-manager/webapp/dist/css/index.5712d0365318b239ca44.css.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
components/wifi-manager/webapp/dist/index.html


BIN
components/wifi-manager/webapp/dist/index.html.gz


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
components/wifi-manager/webapp/dist/js/index.41c7e6.bundle.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 1
components/wifi-manager/webapp/dist/js/index.79297e.bundle.js


+ 0 - 0
components/wifi-manager/webapp/dist/js/index.41c7e6.bundle.js.LICENSE.txt → components/wifi-manager/webapp/dist/js/index.79297e.bundle.js.LICENSE.txt


BIN
components/wifi-manager/webapp/dist/js/index.41c7e6.bundle.js.gz → components/wifi-manager/webapp/dist/js/index.79297e.bundle.js.gz


+ 0 - 1
components/wifi-manager/webapp/dist/src/test.d.ts

@@ -1,4 +1,3 @@
 import 'bootstrap';
 import './sass/main.scss';
 import './js/test.js';
-import 'remixicon/fonts/remixicon.css';

+ 2 - 2
components/wifi-manager/webapp/mock/ap.json

@@ -2,10 +2,10 @@
 {"ssid":"Pantum-AP-A6D49F","chan":11,"rssi":-55,"auth":4, "known":false},
 {"ssid":"a0308","chan":1,"rssi":-56,"auth":3, "known":false},
 {"ssid":"dlink-D9D8","chan":11,"rssi":-82,"auth":4, "known":false},
-{"ssid":"Linksys06730","chan":7,"rssi":-85,"auth":3, "known":false},
+{"ssid":"Linksys06730","chan":7,"rssi":-85,"auth":0, "known":false},
 {"ssid":"SINGTEL-5171","chan":9,"rssi":-88,"auth":4, "known":false},
 {"ssid":"1126-1","chan":11,"rssi":-89,"auth":4, "known":false},
-{"ssid":"The Shah 5GHz-2","chan":1,"rssi":-90,"auth":3, "known":false},
+{"ssid":"The Shah 5GHz-2","chan":1,"rssi":-90,"auth":0, "known":false},
 {"ssid":"SINGTEL-1D28 (2G)","chan":11,"rssi":-91,"auth":3, "known":false},
 {"ssid":"dlink-F864","chan":1,"rssi":-92,"auth":4, "known":false},
 {"ssid":"dlink-74F0","chan":1,"rssi":-93,"auth":4, "known":false},

+ 3 - 3
components/wifi-manager/webapp/mock/commands.json

@@ -61,7 +61,7 @@
 			"argtable":	[{
 					"datatype":	"squeezelite-1fe714",
 					"glossary":	"New Name",
-					"longopts":	"name",
+					"longopts":	"new_name",
 					"shortopts":	"n",
 					"checkbox":	false,
 					"remark":	false,
@@ -745,10 +745,10 @@
 			"telnet":	"Telnet and Serial"
 		},
 		"cfg-syst-name":	{
-			"name":	"squeezelite-1fe714"
+			"new_name":	"squeezelite-1fe714"
 		},
 		"cfg-hw-preset":	{
-			"model_config":	""
+			"model_config":	"previous config value"
 		},
 		"cfg-audio-general":	{
 			"jack_behavior":	"Subwoofer"

+ 1 - 0
components/wifi-manager/webapp/package.json

@@ -49,6 +49,7 @@
     "node-sass": "^5.0.0",
     "postcss": "^8.2.4",
     "postcss-loader": "^4.2.0",
+    "purgecss-webpack-plugin": "^4.1.3",
     "remixicon": "^2.5.0",
     "sass-loader": "^10.1.1",
     "string-argv": "^0.3.1",

+ 2 - 2
components/wifi-manager/webapp/src/index.ejs

@@ -7,13 +7,13 @@
 	<meta name="apple-mobile-web-app-capable" content="yes" />
 	<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
 	<link href="https://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet">	
-	<title>SqueezeESP32</title>
+	<title></title>
 
 </head>
 
 <body class="d-flex flex-column">
 	<header class="navbar navbar-expand-sm navbar-dark  bg-primary sticky-top border-bottom border-dark" id="mainnav">
-		<a class="navbar-brand" id="navtitle" href="#">SqueezeESP32</a>
+		<a class="navbar-brand" id="navtitle" href="#"></a>
 		<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
 			aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
 			<span class="navbar-toggler-icon"></span>

+ 143 - 135
components/wifi-manager/webapp/src/js/custom.js

@@ -62,14 +62,15 @@ const nvsTypes = {
   NVS_TYPE_ANY: 0xff /*! < Must be last */,
 };
 const btIcons = {
-  bt_playing: 'play-circle-fill',
-  bt_disconnected: 'bluetooth-fill',
-  bt_neutral: '',
-  bt_connected: 'bluetooth-connect-fill',
-  bt_disabled: '',
-  play_arrow:  'play-circle-fill',
-  pause: 'pause-circle-fill',
-  stop:  'stop-circle-fill',
+  bt_playing: 'media_bluetooth_on',
+  bt_disconnected: 'media_bluetooth_off',
+  bt_neutral: 'bluetooth',
+  bt_connecting: 'bluetooth_searching',
+  bt_connected: 'bluetooth_connected',
+  bt_disabled: 'bluetooth_disabled',
+  play_arrow:  'play_circle_filled',
+  pause: 'pause_circle',
+  stop:  'stop_circle',
   '': '',
 };
 const batIcons = [
@@ -80,10 +81,10 @@ const batIcons = [
 ];
 const btStateIcons = [
   { desc: 'Idle', sub: ['bt_neutral'] },
-  { desc: 'Discovering', sub: ['bt_disconnected'] },
-  { desc: 'Discovered', sub: ['bt_disconnected'] },
+  { desc: 'Discovering', sub: ['bt_connecting'] },
+  { desc: 'Discovered', sub: ['bt_connecting'] },
   { desc: 'Unconnected', sub: ['bt_disconnected'] },
-  { desc: 'Connecting', sub: ['bt_disconnected'] },
+  { desc: 'Connecting', sub: ['bt_connecting'] },
   { 
     desc: 'Connected',
     sub: ['bt_connected', 'play_arrow', 'bt_playing', 'pause', 'stop'],
@@ -378,19 +379,18 @@ function handlebtstate(data) {
   let icon = '';
   let tt = '';
   if (data.bt_status !== undefined && data.bt_sub_status !== undefined) {
-    const iconsvg = btStateIcons[data.bt_status].sub[data.bt_sub_status];
-    if (iconsvg) {
-      icon = `#${btIcons[iconsvg]}`;
+    const iconindex = btStateIcons[data.bt_status].sub[data.bt_sub_status];
+    if (iconindex) {
+      icon = btIcons[iconindex];
       tt = btStateIcons[data.bt_status].desc;
     } else {
-      icon = `#${btIcons.bt_connected}`;
+      icon = btIcons.bt_connected;
       tt = 'Output status';
     }
   }
-  $('#o_type').title = tt;
-  $('#o_bt').attr('xlink:href',icon);
-
   
+  $('#o_type').attr('title', tt);
+  $('#o_bt').html(icon);
 }
 function handleTemplateTypeRadio(outtype) {
   $('#o_type').children('span').css({ display : 'none' });
@@ -466,6 +466,7 @@ let hostName = '';
 let versionName='Squeezelite-ESP32';
 let prevmessage='';
 let project_name=versionName;
+let board_model='';
 let platform_name=versionName;
 let preset_name='';
 let btSinkNamesOptSel='#cfg-audio-bt_source-sink_name';
@@ -549,36 +550,101 @@ function getConfigJson(slimMode) {
   return config;
 }
 
+function handleHWPreset(allfields,reboot){
+  
+  const selJson = JSON.parse(allfields[0].value);
+  var cmd=allfields[0].attributes.cmdname.value;
+  
+  console.log(`selected model: ${selJson.name}`);
+  let confPayload={
+    timestamp: Date.now(),
+    config : { model_config : {value:selJson.name,type:33 }}
+  };
+  for(const [name, value]  of Object.entries(selJson.config)){
+    const storedval=(typeof value === 'string' || value instanceof String)?value:JSON.stringify(value);
+    confPayload.config[name] = {
+        value : storedval,
+        type: 33,
+    }
+    showCmdMessage(
+      cmd,
+      'MESSAGING_INFO',
+      `Setting ${name}=${storedval} `,
+      true
+    );
+  }
+  
+  showCmdMessage(
+    cmd,
+    'MESSAGING_INFO',
+    `Committing `,
+    true
+  );
+  $.ajax({
+    url: '/config.json',
+    dataType: 'text',
+    method: 'POST',
+    cache: false,
+    contentType: 'application/json; charset=utf-8',
+    data: JSON.stringify(confPayload),
+    error: function(xhr, _ajaxOptions, thrownError){
+      handleExceptionResponse(xhr, _ajaxOptions, thrownError);
+      showCmdMessage(
+        cmd,
+        'MESSAGING_ERROR',
+        `Unexpected error ${(thrownError !== '')?thrownError:'with return status = '+xhr.status} `,
+        true
+      );        
+    },
+    success: function(response) {
+      showCmdMessage(
+        cmd,
+        'MESSAGING_INFO',
+        `Saving complete `,
+        true
+      );
+      console.log(response);
+      if (reboot) {
+        delayReboot(2500, cmd);
+      }
+    },
+  });
+
+
+  
+  
+
+}
 
 
 // pull json file from https://gist.githubusercontent.com/sle118/dae585e157b733a639c12dc70f0910c5/raw/b462691f69e2ad31ac95c547af6ec97afb0f53db/squeezelite-esp32-presets.json and
-// load the names into cfg-hw-preset-model_name
 function loadPresets() {
+  if($("#cfg-hw-preset-model_config").length == 0) return;
   if(presetsloaded) return;
   presetsloaded = true;
+  $('#cfg-hw-preset-model_config').html('<option>--</option>');
   $.getJSON(
-    'https://gist.githubusercontent.com/sle118/dae585e157b733a639c12dc70f0910c5/raw/b462691f69e2ad31ac95c547af6ec97afb0f53db/squeezelite-esp32-presets.json',
+    'https://gist.githubusercontent.com/sle118/dae585e157b733a639c12dc70f0910c5/raw/',
+    {_: new Date().getTime()},
     function(data) {
       $.each(data, function(key, val) {
-          $('#cfg-hw-preset-model_config').append(`<option value="${JSON.stringify(val).replace(/\"/g, '\'')}">${val.name}</option>`);
+          $('#cfg-hw-preset-model_config').append(`<option value='${JSON.stringify(val).replace(/"/g, '\"').replace(/\'/g, '\"')}'>${val.name}</option>`);
+          if(preset_name !=='' && preset_name==val.name){
+            $('#cfg-hw-preset-model_config').val(preset_name);
+          }
       });
       if(preset_name !== ''){
         ('#prev_preset').show().val(preset_name);
-      }
-      console.log('update prev_preset in case of a change');
+      }      
     }
 
   ).fail(function(jqxhr, textStatus, error) {
     const err = textStatus + ', ' + error;
     console.log('Request Failed: ' + err);
-    $('hw-preset-section').hide();
   }
   );
 }
 
-        
-
-
 function delayReboot(duration, cmdname, ota = 'reboot') {
   const url = '/'+ota+'.json';
   $('tbody#tasks').empty();
@@ -736,9 +802,6 @@ window.handleConnect = function(){
 
 }
 $(document).ready(function() {
-  $('#wifiTable').on('click','tr', function() {
-
-  });
   $('#fw-url-input').on('input', function() {
     if($(this).val().length>8 && ($(this).val().startsWith('http://') || $(this).val().startsWith('https://'))){
       $('#start-flash').show();
@@ -890,12 +953,6 @@ $(document).ready(function() {
       $('*[href*="-nvs"]').hide();
     }
   });
- $('#btn-save-cfg-hw-preset').on('click', function(){
-  runCommand(this,false);
- });
- $('#btn-commit-cfg-hw-preset').on('click', function(){
-  runCommand(this,true);
- });
  $('#btn_reboot_recovery').on('click',function(){
   handleReboot('recovery');
  });
@@ -1192,15 +1249,11 @@ function formatAP(ssid, rssi, auth){
   return `<tr data-toggle="modal" data-target="#WifiConnectDialog"><td></td><td>${ssid}</td><td>
   <span class="material-icons" style="fill:white; display: inline" >${rssiToIcon(rssi)}</span>
   	</td><td>
-   <svg style="fill:white; width:1.5rem; height: 1.5rem;">
-  <use xlink:href="#lock${(auth == 0 ? '-unlock':'')}-fill"></use>
-</svg>
-
+    <span class="material-icons">${(auth == 0 ? 'no_encryption':'lock')}</span>
   </td></tr>`;
 }
 function refreshAPHTML2(data) {
   let h = '';
-  $('#tab-wifi').show();
   $('#wifiTable tr td:first-of-type').text('');
   $('#wifiTable tr').removeClass('table-success table-warning');
   if(data){
@@ -1221,8 +1274,7 @@ function refreshAPHTML2(data) {
     $(wifiSelector).filter(function() {return $(this).text() === ConnectedTo.ssid;  }).siblings().first().html('&check;').parent().addClass((ConnectedTo.urc === connectReturnCode.OK?'table-success':'table-warning'));
     $('span#foot-if').html(`SSID: <strong>${ConnectedTo.ssid}</strong>, IP: <strong>${ConnectedTo.ip}</strong>`);    
     $('#wifiStsIcon').html(rssiToIcon(ConnectedTo.rssi));
-    $(".if_eth").hide();
-    $('.if_wifi').show();
+
   }
   else if(ConnectedTo.urc !== connectReturnCode.ETH){
     $('span#foot-if').html('');
@@ -1230,9 +1282,7 @@ function refreshAPHTML2(data) {
   
 }
 function refreshETH() {
-  
-  $(".if_eth").show();
-  $('.if_wifi').hide();
+
   if(ConnectedTo.urc === connectReturnCode.ETH ){
     $('span#foot-if').html(`Network: Ethernet, IP: <strong>${ConnectedTo.ip}</strong>`);    
   }
@@ -1496,13 +1546,17 @@ function handleWifiDialog(data){
   }
 }
 function handleNetworkStatus(data) {
-  if(hasConnectionChanged(data)){
+  if(hasConnectionChanged(data) || !data.urc){
     ConnectedTo=data;
-    if(ConnectedTo.urc == connectReturnCode.ETH ){
-      refreshETH();
+    $(".if_eth").hide();
+    $('.if_wifi').hide();    
+    if(!data.urc || ConnectedTo.urc == connectReturnCode.ETH ){
+      $('.if_wifi').show();  
+      refreshAPHTML2();      
     } 
     else {
-      refreshAPHTML2();
+      $(".if_eth").show();
+      refreshETH();
     }
 
   }
@@ -1546,15 +1600,18 @@ function checkStatus() {
       ota_dsc: (data.ota_dsc ??''),
       event: flash_events.PROCESS_OTA_STATUS
     });
+
     if (data.project_name && data.project_name !== '') {
       project_name = data.project_name;
     }
     if(data.platform_name && data.platform_name!==''){
       platform_name = data.platform_name;
     }
+    if(board_model==='') board_model = project_name;
+    if(board_model==='') board_model = 'Squeezelite-ESP32';
     if (data.version && data.version !== '') {
       versionName=data.version;
-      $("#navtitle").html(`${project_name}${recovery?'<br>[recovery]':''}`);
+      $("#navtitle").html(`${board_model}${recovery?'<br>[recovery]':''}`);
       $('span#foot-fw').html(`fw: <strong>${versionName}</strong>, mode: <strong>${recovery?"Recovery":project_name}</strong>`);
     } else {
       $('span#flash-status').html('');
@@ -1614,38 +1671,41 @@ window.runCommand = function(button, reboot) {
     false
   );
   const fields = document.getElementById('flds-' + cmdstring);
+  const allfields = fields?.querySelectorAll('select,input');
+  if(cmdstring ==='cfg-hw-preset') return handleHWPreset(allfields,reboot);
   cmdstring += ' ';
   if (fields) {
-    const allfields = fields.querySelectorAll('select,input');
-    for (var i = 0; i < allfields.length; i++) {
-      const attr = allfields[i].attributes;
+
+    for(const field of allfields) {
       let qts = '';
       let opt = '';
-      let isSelect = $(allfields[i]).is('select');
-      const hasValue=attr.hasvalue.value === 'true';
-      const validVal=(isSelect && allfields[i].value !== '--' ) || ( !isSelect && allfields[i].value !== '' );
+      let attr=field.attributes;
+      let isSelect = $(field).is('select');
+      const hasValue=attr?.hasvalue?.value === 'true';
+      const validVal=(isSelect && field.value !== '--' ) || ( !isSelect && field.value !== '' );
 
       if ( !hasValue|| hasValue && validVal)  {
-        if (attr.longopts.value !== 'undefined') {
-          opt += '--' + attr.longopts.value;
-        } else if (attr.shortopts.value !== 'undefined') {
+        if (attr?.longopts?.value !== 'undefined') {
+          opt += '--' + attr?.longopts?.value;
+        } else if (attr?.shortopts?.value !== 'undefined') {
           opt = '-' + attr.shortopts.value;
         }
 
-        if (attr.hasvalue.value === 'true') {
-          if (allfields[i].value !== '') {
-            qts = /\s/.test(allfields[i].value) ? '"' : '';
-            cmdstring += opt + ' ' + qts + allfields[i].value + qts + ' ';
+        if (attr?.hasvalue?.value === 'true') {
+          if (attr?.value !== '') {
+            qts = /\s/.test(field.value) ? '"' : '';
+            cmdstring += opt + ' ' + qts + field.value + qts + ' ';
           }
         } else {
           // this is a checkbox
-          if (allfields[i].checked) {
+          if (field?.checked) {
             cmdstring += opt + ' ';
           }
         }
       }
     }
   }
+  
   console.log(cmdstring);
 
   const data = {
@@ -1705,13 +1765,7 @@ function getCommands() {
         const isConfig = cmdParts[0] === 'cfg';
         const targetDiv = '#tab-' + cmdParts[0] + '-' + cmdParts[1];
         let innerhtml = '';
-
-        // innerhtml+='<tr class="table-light"><td>'+(isConfig?'<h1>':'');
-        innerhtml +=
-          '<div class="card text-white mb-3"><div class="card-header">' +
-          command.help.encodeHTML().replace(/\n/g, '<br />') +
-          '</div><div class="card-body">';
-        innerhtml += '<fieldset id="flds-' + command.name + '">';
+        innerhtml += `<div class="card text-white mb-3"><div class="card-header">${command.help.encodeHTML().replace(/\n/g, '<br />')}</div><div class="card-body"><fieldset id="flds-${command.name}">`;
         if (command.argtable) {
           command.argtable.forEach(function(arg) {
             let placeholder = arg.datatype || '';
@@ -1719,8 +1773,6 @@ function getCommands() {
             const curvalue =  getLongOps(data,command.name,arg.longopts);
 
             let attributes = 'hasvalue=' + arg.hasvalue + ' ';
-
-            // attributes +='datatype="'+arg.datatype+'" ';
             attributes += 'longopts="' + arg.longopts + '" ';
             attributes += 'shortopts="' + arg.shortopts + '" ';
             attributes += 'checkbox=' + arg.checkbox + ' ';
@@ -1738,25 +1790,9 @@ function getCommands() {
               attributes += ' style="visibility: hidden;"';
             }
             if (arg.checkbox) {
-              innerhtml +=
-                '<div class="form-check"><label class="form-check-label">';
-              innerhtml +=
-                '<input type="checkbox" ' +
-                attributes +
-                ' class="form-check-input ' +
-                extraclass +
-                '" value="" >' +
-                arg.glossary.encodeHTML() +
-                '<small class="form-text text-muted">Previous value: ' +
-                (curvalue ? 'Checked' : 'Unchecked') +
-                '</small></label>';
+              innerhtml += `<div class="form-check"><label class="form-check-label"><input type="checkbox" ${attributes} class="form-check-input ${extraclass}" value="" >${arg.glossary.encodeHTML()}<small class="form-text text-muted">Previous value: ${(curvalue ? 'Checked' : 'Unchecked')}</small></label>`;
             } else {
-              innerhtml +=
-                '<div class="form-group" ><label for="' +
-                ctrlname +
-                '">' +
-                arg.glossary.encodeHTML() +
-                '</label>';
+              innerhtml +=`<div class="form-group" ><label for="${ctrlname}">${arg.glossary.encodeHTML()}</label>`;
               if (placeholder.includes('|')) {
                 extraclass = placeholder.startsWith('+') ? ' multiple ' : '';
                 placeholder = placeholder
@@ -1770,54 +1806,23 @@ function getCommands() {
                 });
                 innerhtml += '</select>';
               } else {
-                innerhtml +=
-                  '<input type="text" class="form-control ' +
-                  extraclass +
-                  '" placeholder="' +
-                  placeholder +
-                  '" ' +
-                  attributes +
-                  '>';
+                innerhtml +=`<input type="text" class="form-control ${extraclass}" placeholder="${placeholder}" ${attributes}>`;
               }
-              innerhtml +=
-                '<small class="form-text text-muted">Previous value: ' +
-                (curvalue || '') +
-                '</small>';
+              innerhtml +=`<small class="form-text text-muted">Previous value: ${(curvalue || '')}</small>`;
             }
             innerhtml += '</div>';
           });
         }
-        innerhtml += '<div style="margin-top: 16px;">';
-        innerhtml +=
-          '<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true" style="display: none;" id="toast_' +
-          command.name +
-          '">';
-        innerhtml +=
-          '<div class="toast-header"><strong class="mr-auto">Result</strong><button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close" onclick="$(this).parent().parent().hide()">';
-        innerhtml +=
-          '<span aria-hidden="true">×</span></button></div><div class="toast-body" id="msg_' +
-          command.name +
-          '"></div></div>';
+        innerhtml += `<div style="margin-top: 16px;">
+        <div class="toast show" role="alert" aria-live="assertive" aria-atomic="true" style="display: none;" id="toast_${command.name}">
+        <div class="toast-header"><strong class="mr-auto">Result</strong><button type="button" class="ml-2 mb-1 close click_to_close" data-dismiss="toast" aria-label="Close" >
+        <span aria-hidden="true">×</span></button></div><div class="toast-body" id="msg_${command.name}"></div></div>`;
         if (isConfig) {
           innerhtml +=
-            '<button type="submit" class="btn btn-info" id="btn-save-' +
-            command.name +
-            '" cmdname="' +
-            command.name +
-            '" onclick="runCommand(this,false)">Save</button>';
-          innerhtml +=
-            '<button type="submit" class="btn btn-warning" id="btn-commit-' +
-            command.name +
-            '" cmdname="' +
-            command.name +
-            '" onclick="runCommand(this,true)">Apply</button>';
+`<button type="submit" class="btn btn-info sclk" id="btn-save-${command.name}" cmdname="${command.name}">Save</button>
+<button type="submit" class="btn btn-warning cclk" id="btn-commit-${command.name}" cmdname="${command.name}">Apply</button>`;
         } else {
-          innerhtml +=
-            '<button type="submit" class="btn btn-success" id="btn-run-' +
-            command.name +
-            '" cmdname="' +
-            command.name +
-            '" onclick="runCommand(this,false)">Execute</button>';
+          innerhtml +=`<button type="submit" class="btn btn-success sclk" id="btn-run-${command.name}" cmdname="${command.name}">Execute</button>`;
         }
         innerhtml += '</div></fieldset></div></div>';
         if (isConfig) {
@@ -1827,7 +1832,9 @@ function getCommands() {
         }
       }
     });
-
+    $(".click_to_close").on('click', function(){$(this).parent().parent().hide()});
+    $(".sclk").on('click',function(){runCommand(this,false);});
+    $(".cclk").on('click',function(){runCommand(this,true);});
     data.commands.forEach(function(command) {
       $('[cmdname=' + command.name + ']:input').val('');
       $('[cmdname=' + command.name + ']:checkbox').prop('checked', false);
@@ -1861,7 +1868,6 @@ function getCommands() {
     else {
       handleExceptionResponse(xhr, ajaxOptions, thrownError);
     }
-    
     $('#commands-list').empty();
     blockAjax = false;
   });
@@ -1911,7 +1917,9 @@ function getConfig() {
         else if (key == 'preset_name') {
           preset_name = val;
         }
-        
+        else if (key=='board_model') {
+          board_model=val;
+        }
         
         $('tbody#nvsTable').append(
           '<tr>' +

+ 3 - 6
components/wifi-manager/webapp/src/sass/main.scss

@@ -1,9 +1,6 @@
+
 @import "~bootswatch/dist/darkly/variables";
+@import "utils/variables";
 @import "~bootstrap/scss/bootstrap";
 @import "~bootswatch/dist/darkly/bootswatch";
-@import "utils/style";
-
-
-
-
- 
+@import "utils/style";     

+ 3 - 0
components/wifi-manager/webapp/src/sass/utils/_variables.scss

@@ -0,0 +1,3 @@
+$enable-gradients: false;
+// This is needed below, otherwise colors look washed out
+$table-bg-level: 0; 

+ 1 - 1
components/wifi-manager/webapp/src/test.ts

@@ -1,5 +1,5 @@
 import 'bootstrap';
 import './sass/main.scss';
 import './js/test.js';
-import 'remixicon/fonts/remixicon.css';  
+
 

+ 2 - 3
components/wifi-manager/webapp/webapp.cmake

@@ -1,5 +1,4 @@
-target_add_binary_data( __idf_wifi-manager webapp/dist/css/index.5712d0365318b239ca44.css.gz BINARY)
+target_add_binary_data( __idf_wifi-manager webapp/dist/css/index.04bd6e438114e559773d.css.gz BINARY)
 target_add_binary_data( __idf_wifi-manager webapp/dist/favicon-32x32.png BINARY)
 target_add_binary_data( __idf_wifi-manager webapp/dist/index.html.gz BINARY)
-target_add_binary_data( __idf_wifi-manager webapp/dist/js/index.41c7e6.bundle.js.gz BINARY)
-target_add_binary_data( __idf_wifi-manager webapp/dist/index.html.gz BINARY)
+target_add_binary_data( __idf_wifi-manager webapp/dist/js/index.79297e.bundle.js.gz BINARY)

+ 10 - 15
components/wifi-manager/webapp/webpack.c

@@ -1,34 +1,29 @@
 // Automatically generated. Do not edit manually!.
 #include <inttypes.h>
-extern const uint8_t _index_5712d0365318b239ca44_css_gz_start[] asm("_binary_index_5712d0365318b239ca44_css_gz_start");
-extern const uint8_t _index_5712d0365318b239ca44_css_gz_end[] asm("_binary_index_5712d0365318b239ca44_css_gz_end");
+extern const uint8_t _index_04bd6e438114e559773d_css_gz_start[] asm("_binary_index_04bd6e438114e559773d_css_gz_start");
+extern const uint8_t _index_04bd6e438114e559773d_css_gz_end[] asm("_binary_index_04bd6e438114e559773d_css_gz_end");
 extern const uint8_t _favicon_32x32_png_start[] asm("_binary_favicon_32x32_png_start");
 extern const uint8_t _favicon_32x32_png_end[] asm("_binary_favicon_32x32_png_end");
 extern const uint8_t _index_html_gz_start[] asm("_binary_index_html_gz_start");
 extern const uint8_t _index_html_gz_end[] asm("_binary_index_html_gz_end");
-extern const uint8_t _index_41c7e6_bundle_js_gz_start[] asm("_binary_index_41c7e6_bundle_js_gz_start");
-extern const uint8_t _index_41c7e6_bundle_js_gz_end[] asm("_binary_index_41c7e6_bundle_js_gz_end");
-extern const uint8_t _index_html_gz_start[] asm("_binary_index_html_gz_start");
-extern const uint8_t _index_html_gz_end[] asm("_binary_index_html_gz_end");
+extern const uint8_t _index_79297e_bundle_js_gz_start[] asm("_binary_index_79297e_bundle_js_gz_start");
+extern const uint8_t _index_79297e_bundle_js_gz_end[] asm("_binary_index_79297e_bundle_js_gz_end");
 const char * resource_lookups[] = {
-	"/css/index.5712d0365318b239ca44.css.gz",
+	"/css/index.04bd6e438114e559773d.css.gz",
 	"/favicon-32x32.png",
 	"/index.html.gz",
-	"/js/index.41c7e6.bundle.js.gz",
-	"/index.html.gz",
+	"/js/index.79297e.bundle.js.gz",
 ""
 };
 const uint8_t * resource_map_start[] = {
-	_index_5712d0365318b239ca44_css_gz_start,
+	_index_04bd6e438114e559773d_css_gz_start,
 	_favicon_32x32_png_start,
 	_index_html_gz_start,
-	_index_41c7e6_bundle_js_gz_start,
-	_index_html_gz_start
+	_index_79297e_bundle_js_gz_start
 };
 const uint8_t * resource_map_end[] = {
-	_index_5712d0365318b239ca44_css_gz_end,
+	_index_04bd6e438114e559773d_css_gz_end,
 	_favicon_32x32_png_end,
 	_index_html_gz_end,
-	_index_41c7e6_bundle_js_gz_end,
-	_index_html_gz_end
+	_index_79297e_bundle_js_gz_end
 };

+ 37 - 35
components/wifi-manager/webapp/webpack.config.js

@@ -16,6 +16,12 @@ const { merge } = require('webpack-merge');
 const devserver = require('./webpack/webpack.dev.js');
 const fs = require('fs');
 const zlib = require("zlib");
+const PurgeCSSPlugin = require('purgecss-webpack-plugin')
+
+
+const PATHS = {
+  src: path.join(__dirname, 'src')
+}
 
 class BuildEventsHook {
   constructor(name, fn, stage = 'afterEmit') {
@@ -30,13 +36,12 @@ class BuildEventsHook {
 
 
 module.exports = (env, options) => (
-  merge(options.mode === "production" ? {} : devserver,
+  merge(env.WEBPACK_SERVE ?  devserver : {},
     {
       entry: 
       {
           index: './src/index.ts'
       },
-      devtool: "source-map",
       module: {
         rules: [
           {
@@ -61,11 +66,10 @@ module.exports = (env, options) => (
             ]
           }, 
           {
-            test: /\.scss$|\.css$/,
-            use: [
-              // options.mode !== "production"
-              //   ? "style-loader": 
-                {
+            test: /\.s[ac]ss$/i,
+            
+            use:  [
+               {
                   loader: MiniCssExtractPlugin.loader,
                   options: {
                     publicPath: "../",
@@ -81,7 +85,7 @@ module.exports = (env, options) => (
                 },
               },
               "sass-loader",
-            ],
+            ]
           },
           {
             test: /\.js$/,
@@ -175,19 +179,12 @@ module.exports = (env, options) => (
       //   minRatio: 0.8,
       //   deleteOriginalAssets: false
       // }),
-      new CompressionPlugin({
-          //filename: '[path].gz[query]',
-          test: /\.js$|\.css$|\.html$/,
-          filename: "[path][base].gz",
-
-          algorithm: 'gzip',
-          
-          threshold: 100,
-          minRatio: 0.8,
-      }),
         new MiniCssExtractPlugin({
           filename: "css/[name].[contenthash].css",
         }),
+        new PurgeCSSPlugin({
+          paths: glob.sync(`${PATHS.src}/**/*`,  { nodir: true }),
+        }),
         new webpack.ProvidePlugin({
           $: "jquery",
           jQuery: "jquery",
@@ -196,6 +193,16 @@ module.exports = (env, options) => (
           Util: "exports-loader?Util!bootstrap/js/dist/util",
           Dropdown: "exports-loader?Dropdown!bootstrap/js/dist/dropdown",
         }),
+        new CompressionPlugin({
+          //filename: '[path].gz[query]',
+          test: /\.js$|\.css$|\.html$/,
+          filename: "[path][base].gz",
+
+          algorithm: 'gzip',
+          
+          threshold: 100,
+          minRatio: 0.8,
+      }),
         new BuildEventsHook('Update C App', 
           function (stats, arguments) {
             if (options.mode !== "production") return;
@@ -253,7 +260,6 @@ extern const uint8_t * resource_map_end[];`;
                 let lookupMapStart = 'const uint8_t * resource_map_start[] = {\n';
                 let lookupMapEnd = 'const uint8_t * resource_map_end[] = {\n';
                 let cMake = '';
-                list.push('./dist/index.html.gz');
                 list.forEach(fileName => {
 
                   let exportName = fileName.match(regex)[2].replace(/[\. \-]/gm, '_');
@@ -262,8 +268,8 @@ extern const uint8_t * resource_map_end[];`;
                   lookupDef += '\t"/' + relativeName + '",\n';
                   lookupMapStart += '\t_' + exportName + '_start,\n';
                   lookupMapEnd += '\t_' + exportName + '_end,\n';
-                  cMake += `target_add_binary_data( __idf_wifi-manager ${path.posix.relative(path.posix.resolve(process.cwd(),'..','..'),fileName)
-                } BINARY)\n`;
+                  cMake += `target_add_binary_data( __idf_wifi-manager ${path.posix.relative(path.posix.resolve(process.cwd(),'..','..'),fileName)} BINARY)\n`;
+                  console.log(`Post build: adding cmake file reference to ${path.posix.relative(path.posix.resolve(process.cwd(),'..','..'),fileName)} from C project.`);
                 });
 
                 lookupDef += '""\n};\n';
@@ -329,20 +335,16 @@ extern const uint8_t * resource_map_end[];`;
           //new BundleAnalyzerPlugin()
 
         ],
-        // runtimeChunk: 'single',
-        // splitChunks: {
-        //     chunks: 'all',
-        //     // maxInitialRequests: Infinity,
-        //     // minSize: 0,
-        //     cacheGroups: {
-        //         vendor: {
-        //             test: /node_modules/, // you may add "vendor.js" here if you want to
-        //             name: "node-modules",
-        //             chunks: "initial",
-        //             enforce: true
-        //         },
-        //     }
-        //   }
+        splitChunks: {
+          cacheGroups: {
+            styles: {
+              name: 'styles',
+              test: /\.css$/,
+              chunks: 'all',
+              enforce: true
+            }
+          }
+        }
       },
       //   output: {
       //     filename: "[name].js",

+ 1 - 1
components/wifi-manager/webapp/webpack.h

@@ -1,6 +1,6 @@
 /***********************************
 webpack_headers
-dist/css/index.5712d0365318b239ca44.css.gz,dist/favicon-32x32.png,dist/index.html.gz,dist/js/index.41c7e6.bundle.js.gz
+dist/css/index.04bd6e438114e559773d.css.gz,dist/favicon-32x32.png,dist/index.html.gz,dist/js/index.79297e.bundle.js.gz
 ***********************************/
 #pragma once
 #include <inttypes.h>

+ 1 - 0
components/wifi-manager/webapp/webpack/webpack.dev.js

@@ -106,6 +106,7 @@ module.exports ={
     entry: {
         test: './src/test.ts',
     },
+    devtool:"source-map",
     devServer: {
 
         contentBase: path.resolve(__dirname, './dist'),

+ 15 - 0
sdkconfig

@@ -187,6 +187,7 @@ CONFIG_MUTE_GPIO_LEVEL=0
 # Target
 #
 # CONFIG_SQUEEZEAMP is not set
+# CONFIG_MUSE is not set
 CONFIG_BASIC_I2C_BT=y
 # CONFIG_TWATCH2020 is not set
 CONFIG_RELEASE_API="https://api.github.com/repos/sle118/squeezelite-esp32/releases"
@@ -200,6 +201,10 @@ CONFIG_SPI_CONFIG=""
 CONFIG_DISPLAY_CONFIG=""
 CONFIG_ETH_CONFIG=""
 CONFIG_DAC_CONTROLSET=""
+CONFIG_AUDIO_CONTROLS=""
+CONFIG_BAT_CONFIG=""
+CONFIG_TARGET=""
+CONFIG_AMP_GPIO=-1
 CONFIG_JACK_GPIO=-1
 CONFIG_SPKFAULT_GPIO=-1
 CONFIG_BAT_CHANNEL=-1
@@ -266,6 +271,11 @@ CONFIG_AIRPLAY_PORT="5000"
 CONFIG_CSPOT_SINK=y
 # end of Audio Input
 
+#
+# Controls
+#
+# end of Controls
+
 #
 # Display Screen
 #
@@ -289,6 +299,11 @@ CONFIG_ROTARY_ENCODER=""
 #
 # end of Audio JACK
 
+#
+# Amplifier
+#
+# end of Amplifier
+
 #
 # Speaker Fault
 #

Некоторые файлы не были показаны из-за большого количества измененных файлов