Update webpack and web ui to recent versions, bug fixes

This commit is contained in:
Sebastien L
2022-01-21 17:02:34 -05:00
parent bd63723189
commit 977935015e
39 changed files with 542 additions and 442 deletions

2
.gitignore vendored
View File

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

View File

@@ -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);

View File

@@ -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

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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));

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -187,53 +187,7 @@ 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) {
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) {
cJSON_SetNumberValue(cjsonvalue, value);
} else {
cJSON_AddNumberToObject(*root, key, value);
}
}
network_status_unlock_json_buffer();
} else {
ESP_LOGW(TAG, "Unable to lock status json buffer. ");
}
return *root;
}
cJSON* network_status_update_float(cJSON** root, const char* key, float value) {
if (network_status_lock_json_buffer(portMAX_DELAY)) {
if (*root == NULL) {
@@ -274,26 +228,44 @@ cJSON* network_status_update_bool(cJSON** root, const char* key, bool value) {
}
return *root;
}
cJSON * network_update_cjson_string(cJSON** root, const char* key, const char* value){
if (network_status_lock_json_buffer(portMAX_DELAY)) {
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. ");
}
return *root;
}
cJSON* network_status_get_basic_info(cJSON** old) {
if (network_status_lock_json_buffer(portMAX_DELAY)) {
network_t* nm = network_get_state_machine();
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);
}

View File

@@ -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",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

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

View File

@@ -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},

View File

@@ -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"

View File

@@ -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",

View File

@@ -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>

View File

@@ -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>' +

View File

@@ -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";

View File

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

View File

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

View File

@@ -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)

View File

@@ -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
};

View File

@@ -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",

View File

@@ -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>

View File

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

View File

@@ -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
#