浏览代码

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.
Sebastien 4 年之前
父节点
当前提交
889b1097cc

+ 24 - 0
components/display/display.c

@@ -396,3 +396,27 @@ const char *display_conf_get_driver_name(char * driver){
 	}
 	}
 	return NULL;
 	return NULL;
 }
 }
+
+/****************************************************************************************
+ *
+ */
+char * display_get_supported_drivers(){
+	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;
+}

+ 2 - 0
components/display/display.h

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

+ 33 - 11
components/platform_console/cmd_i2ctools.c

@@ -82,15 +82,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,7 +370,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;
 	int result = 0;
 	char * name = NULL;
 	char * name = NULL;
 	char * driver= NULL;
 	char * driver= NULL;
@@ -426,6 +428,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,6 +439,21 @@ 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 "--speed" option */
+	if (i2cdisp_args.speed->count) {
+		speed=i2cdisp_args.speed->ival[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)?"has input capabilities only":"is not a GPIO");
+			back=-1;
+			nerrors ++;
+		}
+	}
+
+
 	if(!name) name = strdup("I2C");
 	if(!name) name = strdup("I2C");
 	if(!driver) driver = strdup("SSD1306");
 	if(!driver) driver = strdup("SSD1306");
 
 
@@ -456,8 +474,8 @@ 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",
-				name,width,height,address,driver,rotate || i2cdisp_args.hflip->count?",HFlip":"",rotate || i2cdisp_args.vflip->count?",VFlip":"" );
+		snprintf(config_string, sizeof(config_string),"%s:back=%i,speed=%i,width=%i,height=%i,address=%i,driver=%s%s%s",
+				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;
 		result = config_set_value(NVS_TYPE_STR, "display_config", config_string)!=ESP_OK;
@@ -897,15 +915,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) but SPI can work up to 26MHz or even 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",

+ 105 - 42
components/wifi-manager/code.js

@@ -63,6 +63,7 @@ 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 stopCheckStatusInterval(){
 function stopCheckStatusInterval(){
@@ -169,6 +170,7 @@ function getConfigJson(slimMode){
 
 
 	}
 	}
 	
 	
+	
 	function onChooseFile(event, onLoadFileHandler) {
 	function onChooseFile(event, onLoadFileHandler) {
 	    if (typeof window.FileReader !== 'function')
 	    if (typeof window.FileReader !== 'function')
 	        throw ("The file API isn't supported on this browser.");
 	        throw ("The file API isn't supported on this browser.");
@@ -186,7 +188,9 @@ function getConfigJson(slimMode){
 	    input.value="";
 	    input.value="";
 	}
 	}
 	$(document).ready(function(){
 	$(document).ready(function(){
-		$("#load-nvs").click(function () {
+        $("input#show-commands")[0].checked=LastCommandsState==1?true:false;
+        $('a[href^="#tab-commands"]').hide();
+        $("#load-nvs").click(function () {
 		    $("#nvsfilename").trigger('click');
 		    $("#nvsfilename").trigger('click');
 		});
 		});
     $("#wifi-status").on("click", ".ape", function() {
     $("#wifi-status").on("click", ".ape", function() {
@@ -296,6 +300,17 @@ function getConfigJson(slimMode){
         $( "#connect-details" ).slideUp( "fast", function() {});
         $( "#connect-details" ).slideUp( "fast", 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;
@@ -1006,7 +1021,8 @@ 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);
 	fields=document.getElementById("flds-"+button.value);
 	cmdstring=button.value+' ';
 	cmdstring=button.value+' ';
@@ -1055,7 +1071,32 @@ 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');
+	                }
+	            });
+            }
+        }
 	});
 	});
 	enableStatusTimer = true;
 	enableStatusTimer = true;
 }
 }
@@ -1064,60 +1105,82 @@ 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>';
-			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>';
-					ctrltype="text";
-					if(arg.checkbox){
-						ctrltype="checkbox";
-					}
 					curvalue=data.values?.[command.name]?.[arg.longopts] || '';
 					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+' ';
-
-					
-					
-					if(arg.checkbox){
-						if(curvalue=data.values?.[command.name]?.[arg.longopts] ){
-							innerhtml+='checked=true ';							
-						}
-						else{
-							innerhtml+='checked=false ';							
-						}
-							
-
-						innerhtml+='></input></td>';
+					innerhtml+="<tr>";
+					var attributes ='datatype="'+arg.datatype+'" ';
+					attributes+='hasvalue='+arg.hasvalue+' ';
+					attributes+='longopts="'+arg.longopts+'" ';
+					attributes+='shortopts="'+arg.shortopts+'" ';
+					attributes+='checkbox='+arg.checkbox+' ';
+
+
+					if(placeholder.includes('|')){
+						placeholder = placeholder.replace('<','').replace('>','');
+						innerhtml+='<td><select name="'+ctrlname+'" ';
+						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 {
 					else {
-						innerhtml+='value="'+curvalue+'" ';
-						innerhtml+='></input></td>'+ curvalue.length>0?'<td>last: '+curvalue+'</td>':'';
+						ctrltype="text";
+						if(arg.checkbox){
+							ctrltype="checkbox";
+						}
+						
+						innerhtml+='<td><label for="'+ctrlname+'">'+ arg.glossary+'</label></td>';
+						innerhtml+='<td><input type="'+ctrltype+'" id="'+ctrlname+'" name="'+ctrlname+'" placeholder="'+placeholder+'" hasvalue="'+arg.hasvalue+'"   ';
+						innerhtml+=attributes;
+						if(arg.checkbox){
+							if(data.values?.[command.name]?.[arg.longopts] ){
+								innerhtml+='checked=true ';							
+							}
+							else{
+								innerhtml+='checked=false ';							
+							}
+								
+	
+							innerhtml+='></input></td>';
+						}
+						else {
+							innerhtml+='value="'+curvalue+'" ';
+							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>';
-
-            });		
-		$("#commands-list").append(innerhtml);
+			if(isConfig){
+				innerhtml+='<div class="buttons"><input id="btn-'+ command.name + '" type="button" class="btn btn-success" value="Save" onclick="runCommand(this,false);">';
+				innerhtml+='<input id="btn-'+ command.name + '-apply" type="button" class="btn btn-success" 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" value="'+command.name+'" onclick="runCommand(this);"></div></div><td></tr>';
+			}
+			
+           });
+		$("#commands-list").append(advancedtabhtml);
+		
 		
 		
     })
     })
     .fail(function(xhr, ajaxOptions, thrownError) {
     .fail(function(xhr, ajaxOptions, thrownError) {

+ 15 - 2
components/wifi-manager/index.html

@@ -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">Display</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>
@@ -195,6 +198,12 @@
                         </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>
+                </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 +313,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>
@@ -366,6 +374,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>