diff --git a/components/platform_console/cmd_i2ctools.c b/components/platform_console/cmd_i2ctools.c index e3d3f4ec..1ba7b08e 100644 --- a/components/platform_console/cmd_i2ctools.c +++ b/components/platform_console/cmd_i2ctools.c @@ -20,6 +20,7 @@ #include "trace.h" #include "messaging.h" #include "display.h" + #define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ #define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ #define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */ @@ -28,6 +29,8 @@ #define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */ #define ACK_VAL 0x0 /*!< I2C ack value */ #define NACK_VAL 0x1 /*!< I2C nack value */ +extern int spi_system_host; +extern int spi_system_dc_gpio; static const char *TAG = "cmd_i2ctools"; #define NOT_OUTPUT "has input capabilities only" @@ -72,6 +75,14 @@ static struct { struct arg_end *end; } i2cconfig_args; +static struct { + struct arg_int *data; + struct arg_int *clk; + struct arg_int *dc; + struct arg_int *host; + struct arg_lit *clear; + struct arg_end *end; +} spiconfig_args; static struct { struct arg_int *port; @@ -97,8 +108,39 @@ static struct { struct arg_lit *clear; struct arg_end *end; } i2cdisp_args; +char * gpio_list = NULL; +const char * get_gpio_list(){ + if(!gpio_list){ + gpio_list = malloc(GPIO_PIN_COUNT*3+1); + memset(gpio_list,0x00,GPIO_PIN_COUNT*3+1); - + for(int i = 0;ihdr.longopts?gpio->hdr.longopts:gpio->hdr.glossary; + *gpio_out=-1; + int t_gpio=gpio->ival[0]; + if(gpio->count==0){ + fprintf(f,"Missing: %s\n", name); + res++; + } else if(!GPIO_IS_VALID_OUTPUT_GPIO(t_gpio)){ + fprintf(f,"Invalid %s gpio: [%d] %s\n",name, t_gpio, GPIO_IS_VALID_GPIO(t_gpio)?NOT_OUTPUT:NOT_GPIO ); + res++; + } + else{ + *gpio_out = t_gpio; + } + return res; +} bool is_i2c_started(i2c_port_t port){ esp_err_t ret = ESP_OK; ESP_LOGD(TAG,"Determining if i2c is started on port %u", port); @@ -118,7 +160,6 @@ bool is_i2c_started(i2c_port_t port){ return (ret!=ESP_ERR_INVALID_STATE); } - typedef struct { uint8_t address; char * description; @@ -442,14 +483,7 @@ static int do_i2c_set_display(int argc, char **argv) /* Check "--back" option */ - if (i2cdisp_args.back->count) { - back=i2cdisp_args.back->ival[0]; - if(!GPIO_IS_VALID_OUTPUT_GPIO(back)){ - fprintf(f,"Invalid GPIO for back light: %d %s\n", back, GPIO_IS_VALID_GPIO(back)?NOT_OUTPUT:NOT_GPIO ); - back=-1; - nerrors ++; - } - } + nerrors +=is_output_gpio(i2cdisp_args.back,f,&back); if(!name) name = strdup("I2C"); @@ -502,6 +536,69 @@ static int do_i2c_set_display(int argc, char **argv) return nerrors==0; } + +static int do_spiconfig_cmd(int argc, char **argv){ + static spi_bus_config_t spi_config = { + .mosi_io_num = -1, + .sclk_io_num = -1, + .miso_io_num = -1, + .quadwp_io_num = -1, + .quadhd_io_num = -1 + }; + + int data, clk, dc, host = 0; + esp_err_t err=ESP_OK; + int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&spiconfig_args); + if (nerrors != 0) { + return 0; + } + + /* Check "--clear" option */ + if (spiconfig_args.clear->count) { + log_send_messaging(MESSAGING_WARNING,"spi config cleared"); + config_set_value(NVS_TYPE_STR, "spi_config", ""); + return 0; + } + + char *buf = NULL; + size_t buf_size = 0; + FILE *f = open_memstream(&buf, &buf_size); + if (f == NULL) { + log_send_messaging(MESSAGING_ERROR,"Unable to open memory stream."); + return 0; + } + /* Check "--clk" option */ + nerrors+=is_output_gpio(spiconfig_args.clk, f, &clk); + nerrors+=is_output_gpio(spiconfig_args.data, f, &data); + nerrors+=is_output_gpio(spiconfig_args.dc, f, &dc); + nerrors+=is_output_gpio(spiconfig_args.host, f, &host); + + if(!nerrors){ + spi_config.mosi_io_num=data; + spi_config.sclk_io_num=clk; + + fprintf(f,"Configuring SPI data:%d clk:%d host:%u dc:%d", spi_config.mosi_io_num, spi_config.sclk_io_num, host, dc); + if((err=spi_bus_initialize( host, &spi_config, 1 ))!=ESP_OK){ + fprintf(f,"SPI bus initialization failed. %s\n", esp_err_to_name(err)); + nerrors++; + } + } + + if(!nerrors){ + fprintf(f,"Storing SPI parameters.\n"); + config_spi_set(&spi_config, host, dc); + } + fflush (f); + log_send_messaging(nerrors>0?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf); + fclose(f); + FREE_AND_NULL(buf); + + return nerrors==0; + + +} + + static int do_i2cconfig_cmd(int argc, char **argv) { esp_err_t err=ESP_OK; @@ -542,30 +639,9 @@ static int do_i2cconfig_cmd(int argc, char **argv) if (i2cconfig_args.freq->count) { i2c_frequency = i2cconfig_args.freq->ival[0]; } - if (i2cconfig_args.sda->count){ - /* Check "--sda" option */ - i2c_gpio_sda = i2cconfig_args.sda->ival[0]; - if(!GPIO_IS_VALID_OUTPUT_GPIO(i2c_gpio_sda )){ - fprintf(f,"Invalid SDA gpio: %d %s\n", i2c_gpio_sda , GPIO_IS_VALID_GPIO(i2c_gpio_sda )?NOT_OUTPUT:NOT_GPIO ); - nerrors ++; - } - } - else { - fprintf(f,"Missing SDA GPIO\n"); - nerrors ++; - } - if (i2cconfig_args.scl->count){ - /* Check "--scl" option */ - i2c_gpio_scl = i2cconfig_args.scl->ival[0]; - if(!GPIO_IS_VALID_OUTPUT_GPIO(i2c_gpio_scl )){ - fprintf(f,"Invalid SCL gpio: %d %s\n", i2c_gpio_scl , GPIO_IS_VALID_GPIO(i2c_gpio_scl )?NOT_OUTPUT:NOT_GPIO ); - nerrors ++; - } - } - else { - fprintf(f,"Missing SCL GPIO\n"); - nerrors ++; - } + + nerrors +=is_output_gpio(i2cconfig_args.sda,f,&i2c_gpio_sda); + nerrors +=is_output_gpio(i2cconfig_args.scl,f,&i2c_gpio_scl); } #ifdef CONFIG_SQUEEZEAMP @@ -957,12 +1033,12 @@ static void register_i2c_set_display(){ i2cdisp_args.hflip = arg_lit0(NULL, "hf", "Flip picture horizontally"); i2cdisp_args.vflip = arg_lit0(NULL, "vf", "Flip picture vertically"); i2cdisp_args.rotate = arg_lit0("r", "rotate", "Rotate the picture 180 deg"); - i2cdisp_args.back = arg_int0("b", "back", "","Backlight GPIO (if applicable)"); + i2cdisp_args.back = arg_int0("b", "back", get_gpio_list(),"Backlight GPIO (if applicable)"); i2cdisp_args.speed = arg_int0("s", "speed", "","Default speed is 8000000 (8MHz) for SPI and 250000 for I2C. The SPI interface can work up to 26MHz~40MHz"); i2cdisp_args.end = arg_end(8); const esp_console_cmd_t i2c_set_display= { .command = "setdisplay", - .help="Sets the display options for the board", + .help="Sets the display options", .hint = NULL, .func = &do_i2c_set_display, .argtable = &i2cdisp_args @@ -1083,19 +1159,63 @@ cJSON * i2config_cb(){ cJSON * values = cJSON_CreateObject(); int i2c_port; const i2c_config_t * i2c= config_i2c_get(&i2c_port); - cJSON_AddNumberToObject(values,"scl",i2c->scl_io_num); - cJSON_AddNumberToObject(values,"sda",i2c->sda_io_num); - cJSON_AddNumberToObject(values,"freq",i2c->master.clk_speed); - cJSON_AddNumberToObject(values,"port",i2c_port); + if(i2c->scl_io_num>0) { + cJSON_AddNumberToObject(values,"scl",i2c->scl_io_num); + } + if(i2c->sda_io_num>0) { + cJSON_AddNumberToObject(values,"sda",i2c->sda_io_num); + } + if(i2c->master.clk_speed>0) { + cJSON_AddNumberToObject(values,"freq",i2c->master.clk_speed); + } + if(i2c_port>0) { + cJSON_AddNumberToObject(values,"port",i2c_port); + } return values; } +cJSON * spiconfig_cb(){ + cJSON * values = cJSON_CreateObject(); + const spi_bus_config_t * spi_config= config_spi_get(NULL); + if(spi_config->mosi_io_num>0){ + cJSON_AddNumberToObject(values,"data",spi_config->mosi_io_num); + } + if(spi_config->sclk_io_num>0){ + cJSON_AddNumberToObject(values,"clk",spi_config->sclk_io_num); + } + if(spi_system_dc_gpio>0){ + cJSON_AddNumberToObject(values,"dc",spi_system_dc_gpio); + } + if(spi_system_host>0){ + cJSON_AddNumberToObject(values,"host",spi_system_host); + } + return values; +} + +static void register_spiconfig(void) +{ + spiconfig_args.clear = arg_lit0(NULL, "clear", "clear configuration"); + spiconfig_args.clk = arg_int0("k", "clock", get_gpio_list(), "Set the gpio for SPI clock"); + spiconfig_args.data = arg_int0("d","data", get_gpio_list(),"Set the gpio for SPI data"); + spiconfig_args.dc = arg_int0("c","dc", get_gpio_list(), "Set the gpio for SPI dc"); + spiconfig_args.host= arg_int0("h", "host", "int", "Set the SPI host number to use"); + spiconfig_args.end = arg_end(4); + const esp_console_cmd_t spiconfig_cmd = { + .command = "spiconfig", + .help = "Config SPI bus", + .hint = NULL, + .func = &do_spiconfig_cmd, + .argtable = &spiconfig_args + }; + cmd_to_json_with_cb(&spiconfig_cmd,&spiconfig_cb); + ESP_ERROR_CHECK(esp_console_cmd_register(&spiconfig_cmd)); +} static void register_i2cconfig(void) { - i2cconfig_args.clear = arg_lit0(NULL, "clear", "clear configuration and return"); + i2cconfig_args.clear = arg_lit0(NULL, "clear", "clear configuration"); i2cconfig_args.port = arg_int0("p", "port", "0|1", "Set the I2C bus port number"); i2cconfig_args.freq = arg_int0("f", "freq", "int", "Set the frequency(Hz) of I2C bus. e.g. 100000"); - i2cconfig_args.sda = arg_int0("d", "sda", "int", "Set the gpio for I2C SDA. e.g. 19"); - i2cconfig_args.scl = arg_int0("c", "scl", "int", "Set the gpio for I2C SCL. e.g. 18"); + i2cconfig_args.sda = arg_int0("d", "sda", get_gpio_list(), "Set the gpio for I2C SDA. e.g. 19"); + i2cconfig_args.scl = arg_int0("c", "scl", get_gpio_list(), "Set the gpio for I2C SCL. e.g. 18"); i2cconfig_args.load = arg_lit0("l", "load", "load existing configuration and return"); i2cconfig_args.end = arg_end(4); const esp_console_cmd_t i2cconfig_cmd = { @@ -1112,6 +1232,7 @@ static void register_i2cconfig(void) void register_i2ctools(void) { register_i2cconfig(); + register_spiconfig(); register_i2cdectect(); register_i2cget(); register_i2cset(); diff --git a/components/platform_console/cmd_system.c b/components/platform_console/cmd_system.c index 1d396252..fe0c6920 100644 --- a/components/platform_console/cmd_system.c +++ b/components/platform_console/cmd_system.c @@ -31,17 +31,22 @@ #include "driver/uart.h" // for the uart driver access #include "messaging.h" #include "platform_console.h" - +#include "trace.h" #ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS #define WITH_TASKS_INFO 1 #endif +static struct { + struct arg_str *name; + struct arg_end *end; +} name_args; static const char * TAG = "cmd_system"; static void register_setbtsource(); static void register_free(); +static void register_setdevicename(); static void register_heap(); static void register_version(); static void register_restart(); @@ -59,6 +64,7 @@ void register_system() register_setbtsource(); register_free(); register_heap(); + register_setdevicename(); register_version(); register_restart(); register_deep_sleep(); @@ -372,6 +378,61 @@ static int heap_size(int argc, char **argv) log_send_messaging(MESSAGING_INFO, "min heap size: %u", heap_size); return 0; } +cJSON * setdevicename_cb(){ + char * default_host_name = config_alloc_get_str("host_name",NULL,"Squeezelite"); + cJSON * values = cJSON_CreateObject(); + cJSON_AddStringToObject(values,"name",default_host_name); + free(default_host_name); + return values; +} +static int setnamevar(char * nvsname, FILE *f, char * value){ + esp_err_t err=ESP_OK; + if((err=config_set_value(NVS_TYPE_STR, nvsname, value))!=ESP_OK){ + fprintf(f,"Unable to set %s=%s. %s\n",nvsname,value,esp_err_to_name(err)); + } + return err==ESP_OK?0:1; +} +static int setdevicename(int argc, char **argv) +{ + char * name = NULL; + int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&name_args); + if (nerrors != 0) { + return 0; + } + + /* Check "--name" option */ + if (name_args.name->count) { + name=strdup(name_args.name->sval[0]); + } + else { + log_send_messaging(MESSAGING_ERROR,"Name must be specified."); + return 0; + } + + char *buf = NULL; + size_t buf_size = 0; + FILE *f = open_memstream(&buf, &buf_size); + if (f == NULL) { + log_send_messaging(MESSAGING_ERROR,"Unable to open memory stream."); + return 0; + } + nerrors+=setnamevar("a2dp_dev_name", f, name); + nerrors+=setnamevar("airplay_name", f, name); + nerrors+=setnamevar("ap_ssid", f, name); + nerrors+=setnamevar("bt_name", f, name); + nerrors+=setnamevar("host_name", f, name); + if(nerrors==0){ + fprintf(f,"Device name changed to %s\n",name); + } + + FREE_AND_NULL(name); + fflush (f); + log_send_messaging(nerrors>0?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf); + fclose(f); + FREE_AND_NULL(buf); + return nerrors==0; + +} static void register_heap() { @@ -386,6 +447,22 @@ static void register_heap() } + +static void register_setdevicename() +{ + char * default_host_name = config_alloc_get_str("host_name",NULL,"Squeezelite"); + name_args.name = arg_str0("n", "name", default_host_name, "Device name"); + name_args.end = arg_end(8); + const esp_console_cmd_t set_name= { + .command = "setname", + .help="Sets the name of the device (host, bluetooth, etc)", + .hint = NULL, + .func = &setdevicename, + .argtable = &name_args + }; + cmd_to_json_with_cb(&set_name,&setdevicename_cb); + ESP_ERROR_CHECK(esp_console_cmd_register(&set_name)); +} /** 'tasks' command prints the list of tasks and related information */ #if WITH_TASKS_INFO diff --git a/components/services/accessors.c b/components/services/accessors.c index 8715e720..c8fee533 100644 --- a/components/services/accessors.c +++ b/components/services/accessors.c @@ -36,6 +36,20 @@ esp_err_t config_i2c_set(const i2c_config_t * config, int port){ } return ESP_OK; } +/**************************************************************************************** + * + */ +esp_err_t config_spi_set(const spi_bus_config_t * config, int host, int dc){ + int buffer_size=255; + char * config_buffer=calloc(buffer_size,1); + if(config_buffer) { + snprintf(config_buffer,buffer_size,"data=%u,clk=%u,dc=%u,host=%u",config->mosi_io_num,config->sclk_io_num,dc,host); + ESP_LOGI(TAG,"Updating SPI configuration to %s",config_buffer); + config_set_value(NVS_TYPE_STR, "spi_config", config_buffer); + free(config_buffer); + } + return ESP_OK; +} /**************************************************************************************** * diff --git a/components/services/accessors.h b/components/services/accessors.h index 3c5f8484..69e9c6c8 100644 --- a/components/services/accessors.h +++ b/components/services/accessors.h @@ -27,6 +27,7 @@ typedef struct { } display_config_t; const display_config_t * config_display_get(); esp_err_t config_i2c_set(const i2c_config_t * config, int port); +esp_err_t config_spi_set(const spi_bus_config_t * config, int host, int dc); const i2c_config_t * config_i2c_get(int * i2c_port); const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host); void parse_set_GPIO(void (*cb)(int gpio, char *value)); diff --git a/components/wifi-manager/code.js b/components/wifi-manager/code.js index 3b51504e..03db2a2f 100644 --- a/components/wifi-manager/code.js +++ b/components/wifi-manager/code.js @@ -1033,12 +1033,10 @@ function checkStatus(){ } function runCommand(button,reboot) { - pardiv = button.parentNode.parentNode; cmdstring = button.attributes.cmdname.value; fields=document.getElementById("flds-"+cmdstring); cmdstring+=' '; if(fields){ - hint = pardiv.hint; allfields=fields.querySelectorAll("select,input"); for (i = 0; i < allfields.length; i++) { attr=allfields[i].attributes; @@ -1122,79 +1120,69 @@ function runCommand(button,reboot) { function getCommands() { $.getJSON("/commands.json", function(data) { console.log(data); - var advancedtabhtml=''; data.commands.forEach(function(command) { if($("#flds-"+command.name).length == 0){ isConfig=($('#'+command.name+'-list').length>0); innerhtml=''; - innerhtml+=''+(isConfig?'

':''); - innerhtml+=escapeHTML(command.help).replace(/\n/g, '
')+(isConfig?'

':'
'); - innerhtml+='
'; + //innerhtml+=''+(isConfig?'

':''); + innerhtml+='
' + escapeHTML(command.help).replace(/\n/g, '
')+'
'; if(command.hasOwnProperty("argtable")){ - innerhtml+=''; command.argtable.forEach(function (arg){ placeholder=arg?.datatype || ''; ctrlname=command.name+'-'+arg.longopts; curvalue=data.values?.[command.name]?.[arg.longopts] || ''; - innerhtml+=""; - var attributes ='datatype="'+arg.datatype+'" '; - attributes+='hasvalue='+arg.hasvalue+' '; + + + var attributes='hasvalue='+arg.hasvalue+' '; + //attributes +='datatype="'+arg.datatype+'" '; attributes+='longopts="'+arg.longopts+'" '; attributes+='shortopts="'+arg.shortopts+'" '; attributes+='checkbox='+arg.checkbox+' '; attributes+='cmdname="'+command.name+'" '; - attributes+= 'id="'+ctrlname+'" name="'+ctrlname+'" placeholder="'+placeholder+'" hasvalue="'+arg.hasvalue+'" '; - - - if(placeholder.includes('|')){ - placeholder = placeholder.replace('<','').replace('>',''); - innerhtml+=''; + attributes+= 'id="'+ctrlname+'" name="'+ctrlname+'" hasvalue="'+arg.hasvalue+'" '; + if(arg.checkbox){ + innerhtml+='
'; } else { - ctrltype="text"; - if(arg.checkbox){ - ctrltype="checkbox"; - } - - innerhtml+='
'; - innerhtml+=''+ curvalue.length>0?'':''; + innerhtml+=''; } + innerhtml+='Previous value: '+curvalue+''; } - innerhtml+=""; + innerhtml+=''; + }); - innerhtml+='
'+ arg.glossary+''; + if(placeholder.includes('|')){ + placeholder = placeholder.replace('<','').replace('>',''); + innerhtml+=''; } else { - innerhtml+='value="'+curvalue+'" '; - innerhtml+='>last: '+curvalue+'
'; - } + + if(isConfig){ + innerhtml+=''; + innerhtml+=''; + } + else { + innerhtml+=''; + } + innerhtml+='
'; + if(isConfig){ - innerhtml+='
'; - innerhtml+='

'; $('#'+command.name+'-list').append(innerhtml); } else { - advancedtabhtml+='
'+innerhtml; - advancedtabhtml+='
'; + $("#commands-list").append(innerhtml); } } }); - $("#commands-list").append(advancedtabhtml); + data.commands.forEach(function(command) { if(command.hasOwnProperty("argtable")){ @@ -1205,6 +1193,10 @@ function getCommands() { } else { $(ctrlselector)[0].value=data.values?.[command.name]?.[arg.longopts] || ''; + if($(ctrlselector)[0].value.length==0 && (arg?.datatype || '').includes('|')){ + $(ctrlselector)[0].value='--'; + } + } }); diff --git a/components/wifi-manager/index.html b/components/wifi-manager/index.html index 5403b0bd..a87ad94c 100644 --- a/components/wifi-manager/index.html +++ b/components/wifi-manager/index.html @@ -198,9 +198,11 @@
-
-
-
+
+
+
+
+
@@ -306,10 +308,7 @@
- - - -
+