Compare commits

..

9 Commits

Author SHA1 Message Date
Sebastien
5ff673ae7d Fix build issue - release 2020-09-08 17:11:52 -04:00
Sebastien
2eb995d621 Merge branch 'master-cmake' of https://github.com/sle118/squeezelite-esp32.git into master-cmake 2020-09-08 16:47:08 -04:00
Sebastien
573ddb6fda Bug fix - some values weren't passed back in the command call - release 2020-09-08 16:46:50 -04:00
Philippe G
708a3f9c4a small tweaks 2020-09-06 17:06:52 -07:00
Philippe G
a73c659a1e solving mistery of component made of external static libs only
(and I hate CMake)
2020-09-06 16:54:09 -07:00
Philippe G
b22143a3b6 typos 2020-09-06 00:49:04 -07:00
Sebastien
6195750b41 Minor fix to the UI and command line help text - release 2020-09-04 16:24:12 -04:00
Sebastien
889b1097cc Reorganize configuration UI - release
The System tab is now hidden by default and can be enabled via a toggle
under the Credits tab, similar to how NVS tab works.  A new tab was
created to hold configurations, and display configuration was added.
2020-09-04 16:02:53 -04:00
Sebastien
41cdb8bcdd Allow saving/loading nvs from the nvs editor - release 2020-09-02 13:09:46 -04:00
9 changed files with 434 additions and 180 deletions

View File

@@ -1,6 +1,5 @@
idf_component_register(SRC_DIRS . idf_component_register(
INCLUDE_DIRS . ./inc inc/alac inc/FLAC inc/helix-aac inc/mad inc/ogg inc/opus inc/opusfile inc/resample16 inc/soxr inc/vorbis INCLUDE_DIRS . ./inc inc/alac inc/FLAC inc/helix-aac inc/mad inc/ogg inc/opus inc/opusfile inc/resample16 inc/soxr inc/vorbis
PRIV_REQUIRES newlib
) )
add_prebuilt_library(libmad lib/libmad.a) add_prebuilt_library(libmad lib/libmad.a)
@@ -9,16 +8,16 @@ add_prebuilt_library(libhelix-aac lib/libhelix-aac.a )
add_prebuilt_library(libvorbisidec lib/libvorbisidec.a ) add_prebuilt_library(libvorbisidec lib/libvorbisidec.a )
add_prebuilt_library(libogg lib/libogg.a ) add_prebuilt_library(libogg lib/libogg.a )
add_prebuilt_library(libalac lib/libalac.a ) add_prebuilt_library(libalac lib/libalac.a )
add_prebuilt_library(libremple16 lib/libresample16.a ) add_prebuilt_library(libresample16 lib/libresample16.a )
add_prebuilt_library(libopusfile lib/libopusfile.a ) add_prebuilt_library(libopusfile lib/libopusfile.a )
add_prebuilt_library(libopus lib/libopus.a ) add_prebuilt_library(libopus lib/libopus.a )
target_link_libraries(${COMPONENT_LIB} PRIVATE libmad)
target_link_libraries(${COMPONENT_LIB} PRIVATE libFLAC)
target_link_libraries(${COMPONENT_LIB} PRIVATE libhelix-aac)
target_link_libraries(${COMPONENT_LIB} PRIVATE libvorbisidec)
target_link_libraries(${COMPONENT_LIB} PRIVATE libogg) target_link_libraries(${COMPONENT_LIB} INTERFACE libmad)
target_link_libraries(${COMPONENT_LIB} PRIVATE libalac) target_link_libraries(${COMPONENT_LIB} INTERFACE libFLAC)
target_link_libraries(${COMPONENT_LIB} PRIVATE libremple16) target_link_libraries(${COMPONENT_LIB} INTERFACE libhelix-aac)
target_link_libraries(${COMPONENT_LIB} PRIVATE libopusfile) target_link_libraries(${COMPONENT_LIB} INTERFACE libvorbisidec)
target_link_libraries(${COMPONENT_LIB} PRIVATE libopus) target_link_libraries(${COMPONENT_LIB} INTERFACE libogg)
target_link_libraries(${COMPONENT_LIB} INTERFACE libalac)
target_link_libraries(${COMPONENT_LIB} INTERFACE libresample16)
target_link_libraries(${COMPONENT_LIB} INTERFACE libopusfile)
target_link_libraries(${COMPONENT_LIB} INTERFACE libopus)

View File

@@ -1,3 +0,0 @@
void dummy_obj() {
return;
}

View File

@@ -396,3 +396,27 @@ const char *display_conf_get_driver_name(char * driver){
} }
return NULL; return NULL;
} }
/****************************************************************************************
*
*/
char * display_get_supported_drivers(void){
int total_size = 1;
char * supported_drivers=NULL;
const char * separator = "|";
int separator_len = strlen(separator);
for(uint8_t i=0;known_drivers[i]!=NULL && strlen(known_drivers[i])>0;i++ ){
total_size += strlen(known_drivers[i])+separator_len;
}
total_size+=2;
supported_drivers = malloc(total_size);
memset(supported_drivers,0x00,total_size);
strcat(supported_drivers,"<");
for(uint8_t i=0;known_drivers[i]!=NULL && strlen(known_drivers[i])>0;i++ ){
supported_drivers = strcat(supported_drivers,known_drivers[i]);
supported_drivers = strcat(supported_drivers,separator);
}
strcat(supported_drivers,">");
return supported_drivers;
}

View File

@@ -10,6 +10,7 @@
#include "gds.h" #include "gds.h"
/* /*
The displayer is not thread-safe and the caller must ensure use its own The displayer is not thread-safe and the caller must ensure use its own
mutexes if it wants something better. Especially, text() line() and draw() mutexes if it wants something better. Especially, text() line() and draw()
@@ -38,3 +39,4 @@ void displayer_scroll(char *string, int speed, int pause);
void displayer_control(enum displayer_cmd_e cmd, ...); void displayer_control(enum displayer_cmd_e cmd, ...);
void displayer_metadata(char *artist, char *album, char *title); void displayer_metadata(char *artist, char *album, char *title);
void displayer_timer(enum displayer_time_e mode, int elapsed, int duration); void displayer_timer(enum displayer_time_e mode, int elapsed, int duration);
char * display_get_supported_drivers(void);

View File

@@ -30,7 +30,8 @@
#define NACK_VAL 0x1 /*!< I2C nack value */ #define NACK_VAL 0x1 /*!< I2C nack value */
static const char *TAG = "cmd_i2ctools"; static const char *TAG = "cmd_i2ctools";
#define NOT_OUTPUT "has input capabilities only"
#define NOT_GPIO "is not a GPIO"
static gpio_num_t i2c_gpio_sda = 19; static gpio_num_t i2c_gpio_sda = 19;
static gpio_num_t i2c_gpio_scl = 18; static gpio_num_t i2c_gpio_scl = 18;
static uint32_t i2c_frequency = 100000; static uint32_t i2c_frequency = 100000;
@@ -62,11 +63,12 @@ static struct {
} i2cdump_args; } i2cdump_args;
static struct { static struct {
struct arg_lit *load;
struct arg_int *port; struct arg_int *port;
struct arg_int *freq; struct arg_int *freq;
struct arg_int *sda; struct arg_int *sda;
struct arg_int *scl; struct arg_int *scl;
struct arg_lit *load;
struct arg_lit *clear;
struct arg_end *end; struct arg_end *end;
} i2cconfig_args; } i2cconfig_args;
@@ -82,15 +84,17 @@ static struct {
} i2ccheck_args; } i2ccheck_args;
static struct { static struct {
struct arg_lit *clear;
struct arg_lit *hflip;
struct arg_lit *vflip;
struct arg_lit *rotate;
struct arg_int *address;
struct arg_int *width;
struct arg_int *height;
struct arg_str *name; struct arg_str *name;
struct arg_str *driver; struct arg_str *driver;
struct arg_int *width;
struct arg_int *height;
struct arg_int *address;
struct arg_lit *rotate;
struct arg_lit *hflip;
struct arg_lit *vflip;
struct arg_int *speed;
struct arg_int *back;
struct arg_lit *clear;
struct arg_end *end; struct arg_end *end;
} i2cdisp_args; } i2cdisp_args;
@@ -368,8 +372,7 @@ static int do_i2c_show_display(int argc, char **argv){
static int do_i2c_set_display(int argc, char **argv) static int do_i2c_set_display(int argc, char **argv)
{ {
int width=0, height=0, address=60; int width=0, height=0, address=60, back=-1, speed=8000000 ;
int result = 0;
char * name = NULL; char * name = NULL;
char * driver= NULL; char * driver= NULL;
char config_string[200]={}; char config_string[200]={};
@@ -426,6 +429,7 @@ static int do_i2c_set_display(int argc, char **argv)
fprintf(f,"Missing parameter: --height\n"); fprintf(f,"Missing parameter: --height\n");
nerrors ++; nerrors ++;
} }
/* Check "--name" option */ /* Check "--name" option */
if (i2cdisp_args.name->count) { if (i2cdisp_args.name->count) {
name=strdup(i2cdisp_args.name->sval[0]); name=strdup(i2cdisp_args.name->sval[0]);
@@ -436,7 +440,33 @@ static int do_i2c_set_display(int argc, char **argv)
driver=strdup(i2cdisp_args.driver->sval[0]); driver=strdup(i2cdisp_args.driver->sval[0]);
} }
/* 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 ++;
}
}
if(!name) name = strdup("I2C"); if(!name) name = strdup("I2C");
/* Check "--speed" option */
if (i2cdisp_args.speed->count) {
speed=i2cdisp_args.speed->ival[0];
}
else {
if(strcasestr(name,"I2C")){
speed = 250000;
}
else {
speed = 8000000;
}
}
if(!driver) driver = strdup("SSD1306"); if(!driver) driver = strdup("SSD1306");
@@ -456,33 +486,44 @@ static int do_i2c_set_display(int argc, char **argv)
bool rotate = i2cdisp_args.rotate->count>0; bool rotate = i2cdisp_args.rotate->count>0;
if(nerrors==0){ if(nerrors==0){
snprintf(config_string, sizeof(config_string),"%s:width=%i,height=%i,address=%i,driver=%s%s%s", snprintf(config_string, sizeof(config_string),"%s:back=%i,speed=%i,width=%i,height=%i,address=%i,driver=%s%s%s",
name,width,height,address,driver,rotate || i2cdisp_args.hflip->count?",HFlip":"",rotate || i2cdisp_args.vflip->count?",VFlip":"" ); name,back,speed,width,height,address,driver,rotate || i2cdisp_args.hflip->count?",HFlip":"",rotate || i2cdisp_args.vflip->count?",VFlip":"" );
fprintf(f,"Updating display configuration string configuration to :\n" fprintf(f,"Updating display configuration string configuration to :\n"
"display_config = \"%s\"",config_string ); "display_config = \"%s\"",config_string );
result = config_set_value(NVS_TYPE_STR, "display_config", config_string)!=ESP_OK; nerrors = config_set_value(NVS_TYPE_STR, "display_config", config_string)!=ESP_OK;
}
else {
result = 1;
} }
FREE_AND_NULL(name); FREE_AND_NULL(name);
FREE_AND_NULL(driver); FREE_AND_NULL(driver);
fflush (f); fflush (f);
log_send_messaging(nerrors>0?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf); log_send_messaging(nerrors>0?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf);
fclose(f); fclose(f);
FREE_AND_NULL(buf); FREE_AND_NULL(buf);
return result; return nerrors==0;
} }
static int do_i2cconfig_cmd(int argc, char **argv) static int do_i2cconfig_cmd(int argc, char **argv)
{ {
esp_err_t err=ESP_OK; esp_err_t err=ESP_OK;
int res=0;
char * err_message=malloc(1);
int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&i2cconfig_args); int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&i2cconfig_args);
if (nerrors != 0) { if (nerrors != 0) {
return 0; return 0;
} }
/* Check "--clear" option */
if (i2cconfig_args.clear->count) {
log_send_messaging(MESSAGING_WARNING,"i2c config cleared");
config_set_value(NVS_TYPE_STR, "i2c_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 "--load" option */ /* Check "--load" option */
if (i2cconfig_args.load->count) { if (i2cconfig_args.load->count) {
log_send_messaging(MESSAGING_WARNING,"Loading i2c config"); log_send_messaging(MESSAGING_WARNING,"Loading i2c config");
@@ -493,8 +534,8 @@ static int do_i2cconfig_cmd(int argc, char **argv)
/* Check "--port" option */ /* Check "--port" option */
if (i2cconfig_args.port->count) { if (i2cconfig_args.port->count) {
if (i2c_get_port(i2cconfig_args.port->ival[0], &i2c_port) != ESP_OK) { if (i2c_get_port(i2cconfig_args.port->ival[0], &i2c_port) != ESP_OK) {
log_send_messaging(MESSAGING_ERROR, "Invalid port %u ",i2cconfig_args.port->ival[0]); fprintf(f,"Invalid port %u \n",i2cconfig_args.port->ival[0]);
return 1; nerrors ++;
} }
} }
/* Check "--freq" option */ /* Check "--freq" option */
@@ -504,60 +545,67 @@ static int do_i2cconfig_cmd(int argc, char **argv)
if (i2cconfig_args.sda->count){ if (i2cconfig_args.sda->count){
/* Check "--sda" option */ /* Check "--sda" option */
i2c_gpio_sda = i2cconfig_args.sda->ival[0]; 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 { else {
REALLOC_CAT(err_message,"Missing --sda option."); fprintf(f,"Missing SDA GPIO\n");
res=1; nerrors ++;
} }
if (i2cconfig_args.scl->count){ if (i2cconfig_args.scl->count){
/* Check "--sda" option */ /* Check "--scl" option */
i2c_gpio_scl = i2cconfig_args.scl->ival[0]; 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 { else {
REALLOC_CAT(err_message,"Missing --scl option."); fprintf(f,"Missing SCL GPIO\n");
res=1; nerrors ++;
} }
} }
#ifdef CONFIG_SQUEEZEAMP #ifdef CONFIG_SQUEEZEAMP
if (i2c_port == I2C_NUM_0) { if (i2c_port == I2C_NUM_0) {
i2c_port = I2C_NUM_1; i2c_port = I2C_NUM_1;
log_send_messaging(MESSAGING_ERROR, "can't use i2c port 0 on SqueezeAMP. Changing to port 1."); fprintf(f,"can't use i2c port 0 on SqueezeAMP. Changing to port 1.\n");
} }
#endif #endif
if(!res){ if(!nerrors){
log_send_messaging(MESSAGING_INFO,"Uninstall i2c driver from port %u if needed",i2c_port); fprintf(f,"Uninstalling i2c driver from port %u if needed\n",i2c_port);
if(is_i2c_started(i2c_port)){ if(is_i2c_started(i2c_port)){
if((err=i2c_driver_delete(i2c_port))!=ESP_OK){ if((err=i2c_driver_delete(i2c_port))!=ESP_OK){
log_send_messaging(MESSAGING_ERROR, "i2c driver delete failed. %s", esp_err_to_name(err)); fprintf(f,"i2c driver delete failed. %s\n", esp_err_to_name(err));
res = 1; nerrors++;
} }
} }
} }
if(!res){ if(!nerrors){
log_send_messaging(MESSAGING_INFO, "Initializing driver with config scl=%u sda=%u speed=%u port=%u",i2c_gpio_scl,i2c_gpio_sda,i2c_frequency,i2c_port); fprintf(f,"Initializing driver with config scl=%u sda=%u speed=%u port=%u\n",i2c_gpio_scl,i2c_gpio_sda,i2c_frequency,i2c_port);
if((err=i2c_master_driver_initialize())==ESP_OK){ if((err=i2c_master_driver_initialize())==ESP_OK){
log_send_messaging(MESSAGING_INFO, "Initalize success."); fprintf(f,"Initalize success.\n");
// now start the i2c driver // now start the i2c driver
log_send_messaging(MESSAGING_INFO,"Starting the i2c driver."); fprintf(f,"Starting the i2c driver.");
if((err=i2c_master_driver_install())!=ESP_OK){ if((err=i2c_master_driver_install())!=ESP_OK){
log_send_messaging(MESSAGING_ERROR,"I2C master driver install failed. %s", esp_err_to_name(err)); fprintf(f,"I2C master driver install failed. %s\n", esp_err_to_name(err));
res=1; nerrors++;
} }
else else
{ {
log_send_messaging(MESSAGING_INFO,"i2c driver successfully started."); fprintf(f,"i2c driver successfully started.\n");
} }
} }
else { else {
log_send_messaging(MESSAGING_ERROR,"I2C initialization failed. %s", esp_err_to_name(err)); fprintf(f,"I2C initialization failed. %s\n", esp_err_to_name(err));
res=1; nerrors++;
} }
} }
if(!res && !i2cconfig_args.load->count){ if(!nerrors && !i2cconfig_args.load->count){
log_send_messaging(MESSAGING_INFO,"Storing i2c parameters."); fprintf(f,"Storing i2c parameters.\n");
i2c_config_t config={ i2c_config_t config={
.mode = I2C_MODE_MASTER, .mode = I2C_MODE_MASTER,
.sda_io_num = i2c_gpio_sda, .sda_io_num = i2c_gpio_sda,
@@ -568,11 +616,12 @@ static int do_i2cconfig_cmd(int argc, char **argv)
}; };
config_i2c_set(&config, i2c_port); config_i2c_set(&config, i2c_port);
} }
if(res){ fflush (f);
log_send_messaging(MESSAGING_ERROR,"%s", err_message); log_send_messaging(nerrors>0?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf);
} fclose(f);
free(err_message); FREE_AND_NULL(buf);
return res;
return nerrors==0;
} }
#define RUN_SHOW_ERROR(c) #define RUN_SHOW_ERROR(c)
@@ -897,15 +946,19 @@ cJSON * i2c_set_display_cb(){
} }
static void register_i2c_set_display(){ static void register_i2c_set_display(){
char * supported_drivers = display_get_supported_drivers();
i2cdisp_args.address = arg_int0("a", "address", "<n>", "Set the device address, default 60"); i2cdisp_args.address = arg_int0("a", "address", "<n>", "Set the device address, default 60");
i2cdisp_args.width = arg_int0("w", "width", "<n>", "Set the display width"); i2cdisp_args.width = arg_int0("w", "width", "<n>", "Set the display width");
i2cdisp_args.height = arg_int0("h", "height", "<n>", "Set the display height"); i2cdisp_args.height = arg_int0("h", "height", "<n>", "Set the display height");
i2cdisp_args.name = arg_str0("t", "type", "<I2C|SPI>", "Display type, I2C or SPI. Default I2C"); i2cdisp_args.name = arg_str0("t", "type", "<I2C|SPI>", "Display type, I2C or SPI. Default I2C");
i2cdisp_args.driver = arg_str0("d", "driver", "<string>", "Set the display driver name. Default SSD1306"); i2cdisp_args.driver = arg_str0("d", "driver", supported_drivers?supported_drivers:"<string>", "Set the display driver name. Default SSD1306");
i2cdisp_args.clear = arg_lit0(NULL, "clear", "clear configuration and return"); i2cdisp_args.clear = arg_lit0(NULL, "clear", "clear configuration and return");
i2cdisp_args.hflip = arg_lit0(NULL, "hf", "Flip picture horizontally"); i2cdisp_args.hflip = arg_lit0(NULL, "hf", "Flip picture horizontally");
i2cdisp_args.vflip = arg_lit0(NULL, "vf", "Flip picture vertically"); i2cdisp_args.vflip = arg_lit0(NULL, "vf", "Flip picture vertically");
i2cdisp_args.rotate = arg_lit0("r", "rotate", "Rotate the picture 180 deg"); i2cdisp_args.rotate = arg_lit0("r", "rotate", "Rotate the picture 180 deg");
i2cdisp_args.back = arg_int0("b", "back", "<n>","Backlight GPIO (if applicable)");
i2cdisp_args.speed = arg_int0("s", "speed", "<n>","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); i2cdisp_args.end = arg_end(8);
const esp_console_cmd_t i2c_set_display= { const esp_console_cmd_t i2c_set_display= {
.command = "setdisplay", .command = "setdisplay",
@@ -1038,6 +1091,7 @@ cJSON * i2config_cb(){
} }
static void register_i2cconfig(void) static void register_i2cconfig(void)
{ {
i2cconfig_args.clear = arg_lit0(NULL, "clear", "clear configuration and return");
i2cconfig_args.port = arg_int0("p", "port", "0|1", "Set the I2C bus port number"); 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.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.sda = arg_int0("d", "sda", "int", "Set the gpio for I2C SDA. e.g. 19");

View File

@@ -63,8 +63,19 @@ var checkStatusInterval = null;
var StatusIntervalActive = false; var StatusIntervalActive = false;
var RefreshAPIIntervalActive = false; var RefreshAPIIntervalActive = false;
var LastRecoveryState=null; var LastRecoveryState=null;
var LastCommandsState=null;
var output = ''; var output = '';
function delay_msg(t, v) {
return new Promise(function(resolve) {
setTimeout(resolve.bind(null, v), t)
});
}
Promise.prototype.delay = function(t) {
return this.then(function(v) {
return delay_msg(t, v);
});
}
function stopCheckStatusInterval(){ function stopCheckStatusInterval(){
if(checkStatusInterval != null){ if(checkStatusInterval != null){
clearTimeout(checkStatusInterval); clearTimeout(checkStatusInterval);
@@ -100,8 +111,98 @@ function RepeatRefreshAPInterval(){
if(RefreshAPIIntervalActive) if(RefreshAPIIntervalActive)
startRefreshAPInterval(); startRefreshAPInterval();
} }
function getConfigJson(slimMode){
var config = {};
$("input.nvs").each(function() {
var key = $(this)[0].id;
var val = $(this).val();
if(!slimMode){
var nvs_type = parseInt($(this)[0].attributes.nvs_type.nodeValue,10);
if (key != '') {
config[key] = {};
if(nvs_type == nvs_type_t.NVS_TYPE_U8
|| nvs_type == nvs_type_t.NVS_TYPE_I8
|| nvs_type == nvs_type_t.NVS_TYPE_U16
|| nvs_type == nvs_type_t.NVS_TYPE_I16
|| nvs_type == nvs_type_t.NVS_TYPE_U32
|| nvs_type == nvs_type_t.NVS_TYPE_I32
|| nvs_type == nvs_type_t.NVS_TYPE_U64
|| nvs_type == nvs_type_t.NVS_TYPE_I64) {
config[key].value = parseInt(val);
}
else {
config[key].value = val;
}
config[key].type = nvs_type;
}
}
else {
config[key] = val;
}
});
var key = $("#nvs-new-key").val();
var val = $("#nvs-new-value").val();
if (key != '') {
if(!slimMode){
config[key] = {};
config[key].value = val;
config[key].type = 33;
}
else {
config[key] = val;
}
}
return config;
}
$(document).ready(function(){
function onFileLoad(elementId, event) {
var data={};
try{
data = JSON.parse(elementId.srcElement.result);
}
catch (e){
alert('Parsing failed!\r\n '+ e);
}
$("input.nvs").each(function() {
var key = $(this)[0].id;
var val = $(this).val();
if(data[key]){
if(data[key] != val){
console.log("Changed "& key & " " & val & "==>" & data[key]);
$(this).val(data[key]);
}
}
else {
console.log("Value " & key & " missing from file");
}
});
}
function onChooseFile(event, onLoadFileHandler) {
if (typeof window.FileReader !== 'function')
throw ("The file API isn't supported on this browser.");
let input = event.target;
if (!input)
throw ("The browser does not properly implement the event object");
if (!input.files)
throw ("This browser does not support the `files` property of the file input.");
if (!input.files[0])
return undefined;
let file = input.files[0];
let fr = new FileReader();
fr.onload = onLoadFileHandler;
fr.readAsText(file);
input.value="";
}
$(document).ready(function(){
$("input#show-commands")[0].checked=LastCommandsState==1?true:false;
$('a[href^="#tab-commands"]').hide();
$("#load-nvs").click(function () {
$("#nvsfilename").trigger('click');
});
$("#wifi-status").on("click", ".ape", function() { $("#wifi-status").on("click", ".ape", function() {
$( "#wifi" ).slideUp( "fast", function() {}); $( "#wifi" ).slideUp( "fast", function() {});
$( "#connect-details" ).slideDown( "fast", function() {}); $( "#connect-details" ).slideDown( "fast", function() {});
@@ -210,6 +311,17 @@ $(document).ready(function(){
$( "#wifi" ).slideDown( "fast", function() {}) $( "#wifi" ).slideDown( "fast", function() {})
}); });
$("input#show-commands").on("click", function() {
this.checked=this.checked?1:0;
if(this.checked){
$('a[href^="#tab-commands"]').show();
LastCommandsState = 1;
} else {
LastCommandsState = 0;
$('a[href^="#tab-commands"]').hide();
}
});
$("input#show-nvs").on("click", function() { $("input#show-nvs").on("click", function() {
this.checked=this.checked?1:0; this.checked=this.checked?1:0;
if(this.checked){ if(this.checked){
@@ -334,42 +446,27 @@ $(document).ready(function(){
console.log('sent config JSON with data:', JSON.stringify(data)); console.log('sent config JSON with data:', JSON.stringify(data));
}); });
$("#save-as-nvs").on("click", function() {
var data = { 'timestamp': Date.now() };
var config = getConfigJson(true);
const a = document.createElement("a");
a.href = URL.createObjectURL(
new Blob([JSON.stringify(config, null, 2)], {
type: "text/plain"
}));
a.setAttribute("download", "nvs_config" + Date.now() +"json");
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
console.log('sent config JSON with headers:', JSON.stringify(headers));
console.log('sent config JSON with data:', JSON.stringify(data));
});
$("#save-nvs").on("click", function() { $("#save-nvs").on("click", function() {
var headers = {}; var headers = {};
var data = { 'timestamp': Date.now() }; var data = { 'timestamp': Date.now() };
var config = {}; var config = getConfigJson(false);
$("input.nvs").each(function() {
var key = $(this)[0].id;
var val = $(this).val();
var nvs_type = parseInt($(this)[0].attributes.nvs_type.nodeValue,10);
if (key != '') {
config[key] = {};
if(nvs_type == nvs_type_t.NVS_TYPE_U8
|| nvs_type == nvs_type_t.NVS_TYPE_I8
|| nvs_type == nvs_type_t.NVS_TYPE_U16
|| nvs_type == nvs_type_t.NVS_TYPE_I16
|| nvs_type == nvs_type_t.NVS_TYPE_U32
|| nvs_type == nvs_type_t.NVS_TYPE_I32
|| nvs_type == nvs_type_t.NVS_TYPE_U64
|| nvs_type == nvs_type_t.NVS_TYPE_I64) {
config[key].value = parseInt(val);
}
else {
config[key].value = val;
}
config[key].type = nvs_type;
}
});
var key = $("#nvs-new-key").val();
var val = $("#nvs-new-value").val();
if (key != '') {
// headers["X-Custom-" +key] = val;
config[key] = {};
config[key].value = val;
config[key].type = 33;
}
data['config'] = config; data['config'] = config;
$.ajax({ $.ajax({
url: '/config.json', url: '/config.json',
@@ -421,7 +518,6 @@ $(document).ready(function(){
fwurl : { fwurl : {
value : url, value : url,
type : 33 type : 33
} }
}; };
@@ -935,19 +1031,22 @@ function checkStatus(){
blockAjax = false; blockAjax = false;
}); });
} }
function runCommand(button) {
function runCommand(button,reboot) {
pardiv = button.parentNode.parentNode; pardiv = button.parentNode.parentNode;
fields=document.getElementById("flds-"+button.value); cmdstring = button.attributes.cmdname.value;
cmdstring=button.value+' '; fields=document.getElementById("flds-"+cmdstring);
cmdstring+=' ';
if(fields){ if(fields){
hint = pardiv.hint; hint = pardiv.hint;
allfields=fields.getElementsByTagName("input"); allfields=fields.querySelectorAll("select,input");
for (i = 0; i < allfields.length; i++) { for (i = 0; i < allfields.length; i++) {
attr=allfields[i].attributes; attr=allfields[i].attributes;
qts=''; qts='';
opt=''; opt='';
optspacer=' '; optspacer=' ';
isSelect=allfields[i].attributes?.class?.value=="custom-select";
if(( isSelect && allfields[i].selectedIndex != 0 )|| !isSelect ){
if (attr.longopts.value!== "undefined"){ if (attr.longopts.value!== "undefined"){
opt+= '--' + attr.longopts.value; opt+= '--' + attr.longopts.value;
optspacer='='; optspacer='=';
@@ -968,6 +1067,7 @@ function runCommand(button) {
} }
} }
} }
}
console.log(cmdstring); console.log(cmdstring);
var data = { 'timestamp': Date.now() }; var data = { 'timestamp': Date.now() };
@@ -984,6 +1084,35 @@ function runCommand(button) {
console.log(xhr.status); console.log(xhr.status);
console.log(thrownError); console.log(thrownError);
if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR'); if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR');
},
complete: function(response) {
//var returnedResponse = JSON.parse(response.responseText);
console.log(response.responseText);
if(reboot){
showMessage('Applying. Please wait for the ESP32 to reboot', 'MESSAGING_WARNING');
console.log('now triggering reboot');
$.ajax({
url: '/reboot.json',
dataType: 'text',
method: 'POST',
cache: false,
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ 'timestamp': Date.now()}),
error: function (xhr, ajaxOptions, thrownError) {
console.log(xhr.status);
console.log(thrownError);
if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR');
},
complete: function(response) {
console.log('reboot call completed');
Promise.resolve().delay(5000).then(function(v) {
console.log('Getting updated commands');
getCommands();
});
}
});
}
} }
}); });
enableStatusTimer = true; enableStatusTimer = true;
@@ -993,43 +1122,54 @@ function runCommand(button) {
function getCommands() { function getCommands() {
$.getJSON("/commands.json", function(data) { $.getJSON("/commands.json", function(data) {
console.log(data); console.log(data);
innerhtml=''; var advancedtabhtml='';
data.commands.forEach(function(command) { data.commands.forEach(function(command) {
innerhtml+='<tr><td>'; if($("#flds-"+command.name).length == 0){
innerhtml+=escapeHTML(command.help).replace(/\n/g, '<br />')+'<br>'; isConfig=($('#'+command.name+'-list').length>0);
innerhtml='';
innerhtml+='<tr><td>'+(isConfig?'<h1>':'');
innerhtml+=escapeHTML(command.help).replace(/\n/g, '<br />')+(isConfig?'</h1>':'<br>');
innerhtml+='<div >'; innerhtml+='<div >';
if(command.hasOwnProperty("argtable")){ if(command.hasOwnProperty("argtable")){
innerhtml+='<table class="table table-hover" id="flds-'+command.name+'"><tbody>'; innerhtml+='<table class="table table-hover" id="flds-'+command.name+'"><tbody>';
command.argtable.forEach(function (arg){ command.argtable.forEach(function (arg){
innerhtml+="<tr>"; placeholder=arg?.datatype || '';
ctrlname=command.name+'-'+arg.longopts; ctrlname=command.name+'-'+arg.longopts;
innerhtml+='<td><label for="'+ctrlname+'">'+ arg.glossary+'</label></td>'; curvalue=data.values?.[command.name]?.[arg.longopts] || '';
innerhtml+="<tr>";
var attributes ='datatype="'+arg.datatype+'" ';
attributes+='hasvalue='+arg.hasvalue+' ';
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+='<td><select ';
innerhtml+=attributes;
innerhtml+=' class="custom-select">';
innerhtml+='<option '+(curvalue.length>0?'value':'selected')+'>'+arg.glossary+'</option>'
placeholder.split('|').forEach(function(choice){
innerhtml+='<option '+(curvalue.length>0&&curvalue==choice?'selected':'value')+'="'+choice+'">'+choice+'</option>';
});
innerhtml+='</select></td>';
}
else {
ctrltype="text"; ctrltype="text";
if(arg.checkbox){ if(arg.checkbox){
ctrltype="checkbox"; ctrltype="checkbox";
} }
curvalue=data.values?.[command.name]?.[arg.longopts] || '';
placeholder=arg?.datatype || '';
innerhtml+='<td><input type="'+ctrltype+'" id="'+ctrlname+'" name="'+ctrlname+'" placeholder="'+placeholder+'" hasvalue="'+arg.hasvalue+'" ';
innerhtml+='datatype="'+arg.datatype+'" ';
innerhtml+='hasvalue='+arg.hasvalue+' ';
innerhtml+='longopts="'+arg.longopts+'" ';
innerhtml+='shortopts="'+arg.shortopts+'" ';
innerhtml+='checkbox='+arg.checkbox+' ';
innerhtml+='<td><label for="'+ctrlname+'">'+ arg.glossary+'</label></td>';
innerhtml+='<td><input type="'+ctrltype+'"';
innerhtml+=attributes;
if(arg.checkbox){ if(arg.checkbox){
if(curvalue=data.values?.[command.name]?.[arg.longopts] ){ if(data.values?.[command.name]?.[arg.longopts] ){
innerhtml+='checked=true '; innerhtml+='checked ';
} }
else{
innerhtml+='checked=false ';
}
innerhtml+='></input></td>'; innerhtml+='></input></td>';
} }
@@ -1037,16 +1177,40 @@ function getCommands() {
innerhtml+='value="'+curvalue+'" '; innerhtml+='value="'+curvalue+'" ';
innerhtml+='></input></td>'+ curvalue.length>0?'<td>last: '+curvalue+'</td>':''; innerhtml+='></input></td>'+ curvalue.length>0?'<td>last: '+curvalue+'</td>':'';
} }
}
innerhtml+="</tr>"; innerhtml+="</tr>";
}); });
innerhtml+='</tbody></table><br>'; innerhtml+='</tbody></table>';
} }
innerhtml+='<div class="buttons"><input id="btn-'+ command.name + '" type="button" class="btn btn-danger btn-sm" value="'+command.name+'" onclick="runCommand(this);"></div></div><td></tr>'; if(isConfig){
innerhtml+='<div class="buttons"><input id="btn-'+ command.name + '" type="button" class="btn btn-success" cmdname="'+command.name+'" value="Save" onclick="runCommand(this,false);">';
innerhtml+='<input id="btn-'+ command.name + '-apply" type="button" class="btn btn-success" cmdname="'+command.name+'" value="Apply" onclick="runCommand(this,true);"></div></div><td></tr>';
$('#'+command.name+'-list').append(innerhtml);
}
else {
advancedtabhtml+='<br>'+innerhtml;
advancedtabhtml+='<div class="buttons"><input id="btn-'+ command.name + '" type="button" class="btn btn-danger btn-sm" cmdname="'+command.name+'" value="'+command.name+'" onclick="runCommand(this, false);"></div></div><td></tr>';
}
}
});
$("#commands-list").append(advancedtabhtml);
data.commands.forEach(function(command) {
if(command.hasOwnProperty("argtable")){
command.argtable.forEach(function (arg){
ctrlselector='#'+command.name+'-'+arg.longopts;
if(arg.checkbox){
$(ctrlselector)[0].checked=data.values?.[command.name]?.[arg.longopts];
}
else {
$(ctrlselector)[0].value=data.values?.[command.name]?.[arg.longopts] || '';
}
}); });
$("#commands-list").append(innerhtml); }
});
}) })
.fail(function(xhr, ajaxOptions, thrownError) { .fail(function(xhr, ajaxOptions, thrownError) {
@@ -1114,7 +1278,6 @@ function getConfig() {
}); });
} }
function showMessage(message, severity, age=0) { function showMessage(message, severity, age=0) {
if (severity == 'MESSAGING_INFO') { if (severity == 'MESSAGING_INFO') {
$('#message').css('background', '#6af'); $('#message').css('background', '#6af');
@@ -1145,4 +1308,4 @@ function inRange(x, min, max) {
function sleep(ms) { function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms)); return new Promise(resolve => setTimeout(resolve, ms));
} }

View File

@@ -721,6 +721,7 @@ esp_err_t config_post_handler(httpd_req_t *req){
if(err==ESP_OK){ if(err==ESP_OK){
httpd_resp_sendstr(req, "{ \"result\" : \"OK\" }"); httpd_resp_sendstr(req, "{ \"result\" : \"OK\" }");
messaging_post_message(MESSAGING_INFO,MESSAGING_CLASS_SYSTEM,"Save Success");
} }
cJSON_Delete(root); cJSON_Delete(root);
if(bOTA) { if(bOTA) {

View File

@@ -67,11 +67,14 @@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#tab-firmware">Firmware</a> <a class="nav-link" data-toggle="tab" href="#tab-firmware">Firmware</a>
</li> </li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#tab-setdisplay">Configuration</a>
</li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#tab-syslog">Syslog</a> <a class="nav-link" data-toggle="tab" href="#tab-syslog">Syslog</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#tab-commands">System</a> <a class="nav-link" data-toggle="tab" href="#tab-commands">Advanced</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#tab-nvs">NVS editor</a> <a class="nav-link" data-toggle="tab" href="#tab-nvs">NVS editor</a>
@@ -81,7 +84,6 @@
</li> </li>
</ul> </ul>
<div id="message"></div> <div id="message"></div>
<div id="content"> <div id="content">
<div id="myTabContent" class="tab-content"> <div id="myTabContent" class="tab-content">
<div class="tab-pane fade active show" id="tab-wifi"> <div class="tab-pane fade active show" id="tab-wifi">
@@ -195,6 +197,11 @@
</div> </div>
</div> </div>
</div> <!-- wifi --> </div> <!-- wifi -->
<div class="tab-pane fade" id="tab-setdisplay">
<table class="table table-hover" id="setdisplay-table"><tbody id="setdisplay-list"></tbody></table>
<table class="table table-hover" id="i2cconfig-table"><tbody id="i2cconfig-list"></tbody></table>
<table class="table table-hover" id="spiset-table"><tbody id="spiset-list"></tbody></table>
</div> <!-- display -->
<div class="tab-pane fade" id="tab-audio"> <div class="tab-pane fade" id="tab-audio">
<div id="audioout"> <div id="audioout">
@@ -304,7 +311,6 @@
</tbody> </tbody>
</table> </table>
</div> <!-- system --> </div> <!-- system -->
<div class="tab-pane fade" id="tab-syslog"> <div class="tab-pane fade" id="tab-syslog">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
@@ -332,13 +338,16 @@
<tbody id="nvsTable"> <tbody id="nvsTable">
</tbody> </tbody>
</table> </table>
<div class="buttons"> <div class="buttons">
<div id="boot-div"> <div id="boot-div">
<form id="reboot-form" action="/reboot.json" method="post" target="dummyframe"> <form id="reboot-form" action="/reboot.json" method="post" target="dummyframe">
<button id="reboot-button" type="submit" class="btn btn-primary">Reboot</button> <button id="reboot-button" type="submit" class="btn btn-primary">Reboot</button>
</form> </form>
</div> </div>
<input id="save-nvs" type="button" class="btn btn-success" value="Save" /> <input id="save-nvs" type="button" class="btn btn-success" value="Commit">
<input id="save-as-nvs" type="button" class="btn btn-success" value="Download config">
<input id="load-nvs" type="button" class="btn btn-success" value="Load File">
<input aria-describedby="fileHelp" onchange="onChooseFile(event, onFileLoad.bind(this))" id="nvsfilename" type="file" style="display:none">
</div> </div>
</div> <!-- nvs --> </div> <!-- nvs -->
@@ -363,6 +372,11 @@
<input type="checkbox" class="custom-control-input" id="show-nvs" checked="checked"> <input type="checkbox" class="custom-control-input" id="show-nvs" checked="checked">
<label class="custom-control-label" for="show-nvs"></label> <label class="custom-control-label" for="show-nvs"></label>
</div> </div>
<h2>Show Advanced Commands</h2>
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="show-commands" checked="checked">
<label class="custom-control-label" for="show-commands"></label>
</div>
</div> <!-- credits --> </div> <!-- credits -->
</div> </div>
<footer class="footer"><span id="foot-fw"></span><span id="foot-wifi"></span></footer> <footer class="footer"><span id="foot-fw"></span><span id="foot-wifi"></span></footer>