Przeglądaj źródła

system config UI work in progress

Sebastien 4 lat temu
rodzic
commit
293d08deec

+ 1 - 1
CMakeLists.txt

@@ -12,4 +12,4 @@ include(squeezelite.cmake)
 set(PROJECT_VER $ENV{PROJECT_VER})
   
 #target_compile_definitions(__idf_squeezelite-ota PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_VERBOSE)
-target_compile_definitions(__idf_driver_bt PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_VERBOSE)
+#target_compile_definitions(__idf_driver_bt PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_VERBOSE)

+ 2 - 2
build-scripts/ESP32-A1S-sdkconfig.defaults

@@ -191,9 +191,9 @@ CONFIG_BT_RESERVE_DRAM=0xdb5c
 # CONFIG_BLE_MESH is not set
 # CONFIG_ADC_FORCE_XPD_FSM is not set
 CONFIG_ADC_DISABLE_DAC=y
-# CONFIG_SPI_MASTER_IN_IRAM is not set
+CONFIG_SPI_MASTER_IN_IRAM=y
 CONFIG_SPI_MASTER_ISR_IN_IRAM=y
-# CONFIG_SPI_SLAVE_IN_IRAM is not set
+CONFIG_SPI_SLAVE_IN_IRAM=y
 CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
 # CONFIG_EFUSE_CUSTOM_TABLE is not set
 # CONFIG_EFUSE_VIRTUAL is not set

+ 2 - 2
build-scripts/I2S-4MFlash-sdkconfig.defaults

@@ -183,9 +183,9 @@ CONFIG_BT_RESERVE_DRAM=0xdb5c
 # CONFIG_BLE_MESH is not set
 # CONFIG_ADC_FORCE_XPD_FSM is not set
 CONFIG_ADC_DISABLE_DAC=y
-# CONFIG_SPI_MASTER_IN_IRAM is not set
+CONFIG_SPI_MASTER_IN_IRAM=y
 CONFIG_SPI_MASTER_ISR_IN_IRAM=y
-# CONFIG_SPI_SLAVE_IN_IRAM is not set
+CONFIG_SPI_SLAVE_IN_IRAM=y
 CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
 # CONFIG_EFUSE_CUSTOM_TABLE is not set
 # CONFIG_EFUSE_VIRTUAL is not set

+ 2 - 2
build-scripts/SqueezeAmp4MBFlash-sdkconfig.defaults

@@ -204,9 +204,9 @@ CONFIG_BT_RESERVE_DRAM=0xdb5c
 # CONFIG_BLE_MESH is not set
 # CONFIG_ADC_FORCE_XPD_FSM is not set
 CONFIG_ADC_DISABLE_DAC=y
-# CONFIG_SPI_MASTER_IN_IRAM is not set
+CONFIG_SPI_MASTER_IN_IRAM=y
 CONFIG_SPI_MASTER_ISR_IN_IRAM=y
-# CONFIG_SPI_SLAVE_IN_IRAM is not set
+CONFIG_SPI_SLAVE_IN_IRAM=y
 CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
 # CONFIG_EFUSE_CUSTOM_TABLE is not set
 # CONFIG_EFUSE_VIRTUAL is not set

+ 2 - 2
build-scripts/SqueezeAmp8MBFlash-sdkconfig.defaults

@@ -203,9 +203,9 @@ CONFIG_BT_RESERVE_DRAM=0xdb5c
 # CONFIG_BLE_MESH is not set
 # CONFIG_ADC_FORCE_XPD_FSM is not set
 CONFIG_ADC_DISABLE_DAC=y
-# CONFIG_SPI_MASTER_IN_IRAM is not set
+CONFIG_SPI_MASTER_IN_IRAM=y
 CONFIG_SPI_MASTER_ISR_IN_IRAM=y
-# CONFIG_SPI_SLAVE_IN_IRAM is not set
+CONFIG_SPI_SLAVE_IN_IRAM=y
 CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
 # CONFIG_EFUSE_CUSTOM_TABLE is not set
 # CONFIG_EFUSE_VIRTUAL is not set

+ 2 - 1
components/display/core/ifaces/default_if_spi.c

@@ -12,6 +12,7 @@
 #include <string.h>
 #include <driver/spi_master.h>
 #include <driver/gpio.h>
+#include "freertos/FreeRTOS.h"
 #include <freertos/task.h>
 #include "gds.h"
 #include "gds_err.h"
@@ -106,4 +107,4 @@ static bool SPIDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data,
     NullCheck( Device->SPIHandle, return false );
 
     return SPIDefaultWriteBytes( Device->SPIHandle, GDS_SPI_Data_Mode, Data, DataLength );
-}
+}

+ 24 - 1
components/display/display.c

@@ -56,6 +56,14 @@ static EXT_RAM_ATTR struct {
 	TickType_t tick;
 } displayer;
 
+static const char *known_drivers[] = {"SH1106",
+		"SSD1306",
+		"SSD1322",
+		"SSD1326",
+		"SSD1327",
+		"SSD1675",
+		NULL
+	};
 static void displayer_task(void *args);
 
 struct GDS_Device *display;   
@@ -71,7 +79,7 @@ void display_init(char *welcome) {
 
 	if (!config) {
 		ESP_LOGI(TAG, "no display");
-		return false;
+		return;
 	}	
 	
 	int width = -1, height = -1;
@@ -377,3 +385,18 @@ void displayer_control(enum displayer_cmd_e cmd, ...) {
 	xSemaphoreGive(displayer.mutex);
 	va_end(args);
 }
+
+/****************************************************************************************
+ *
+ */
+bool display_is_valid_driver(char * driver){
+	return display_conf_get_driver_name(driver)!=NULL;
+}
+char * display_conf_get_driver_name(char * driver){
+	for(uint8_t i=0;known_drivers[i]!=NULL && strlen(known_drivers[i])>0;i++ ){
+		if(strcasestr(driver,known_drivers[i])){
+			return known_drivers[i];
+		}
+	}
+	return NULL;
+}

+ 2 - 0
components/display/display.h

@@ -41,6 +41,8 @@ enum displayer_time_e 	{ DISPLAYER_ELAPSED, DISPLAYER_REMAINING };
 
 enum display_bus_cmd_e { DISPLAY_BUS_TAKE, DISPLAY_BUS_GIVE };
 bool (*display_bus)(void *from, enum display_bus_cmd_e cmd);
+char * display_conf_get_driver_name(char * driver);
+bool display_is_valid_driver(char * driver);
 
 void displayer_scroll(char *string, int speed, int pause);
 void displayer_control(enum displayer_cmd_e cmd, ...);

+ 1 - 1
components/platform_console/CMakeLists.txt

@@ -7,6 +7,6 @@ idf_component_register( SRCS
 							platform_console.c
 						INCLUDE_DIRS .   
 						REQUIRES nvs_flash 
-						PRIV_REQUIRES console app_update tools services spi_flash  platform_config vfs pthread wifi-manager platform_config newlib  telnet )
+						PRIV_REQUIRES console app_update tools services spi_flash  platform_config vfs pthread wifi-manager platform_config newlib  telnet display )
 target_link_libraries(${COMPONENT_LIB}   "-Wl,--undefined=GDS_DrawPixelFast")
 target_link_libraries(${COMPONENT_LIB} ${build_dir}/esp-idf/$<TARGET_PROPERTY:RECOVERY_PREFIX>/lib$<TARGET_PROPERTY:RECOVERY_PREFIX>.a 	)

+ 209 - 94
components/platform_console/cmd_i2ctools.c

@@ -18,6 +18,8 @@
 #include "platform_config.h"
 #include "accessors.h"
 #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 */
@@ -251,7 +253,7 @@ const char * i2c_get_description(uint8_t address){
 static esp_err_t i2c_get_port(int port, i2c_port_t *i2c_port)
 {
     if (port >= I2C_NUM_MAX) {
-        ESP_LOGE(TAG, "Wrong port number: %d", port);
+    	log_send_messaging(MESSAGING_ERROR,"Wrong port number: %d", port);
         return ESP_FAIL;
     }
     switch (port) {
@@ -271,7 +273,7 @@ static esp_err_t i2c_master_driver_install(){
 	esp_err_t err=ESP_OK;
 	ESP_LOGD(TAG,"Installing i2c driver on port %u", i2c_port);
 	if((err=i2c_driver_install(i2c_port, I2C_MODE_MASTER, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0))!=ESP_OK){
-		ESP_LOGE(TAG,"Driver install failed! %s", esp_err_to_name(err));
+		log_send_messaging(MESSAGING_ERROR,"Driver install failed! %s", esp_err_to_name(err));
 	}
 	return err;
 }
@@ -287,9 +289,9 @@ static esp_err_t i2c_master_driver_initialize()
         .scl_pullup_en = GPIO_PULLUP_ENABLE,
         .master.clk_speed = i2c_frequency
     };
-    ESP_LOGI(TAG,"Initializing i2c driver configuration.\n   mode = I2C_MODE_MASTER, \n   scl_pullup_en = GPIO_PULLUP_ENABLE, \n   i2c port = %u, \n   sda_io_num = %u, \n   sda_pullup_en = GPIO_PULLUP_ENABLE, \n   scl_io_num = %u, \n   scl_pullup_en = GPIO_PULLUP_ENABLE, \n   master.clk_speed = %u", i2c_port, i2c_gpio_sda,i2c_gpio_scl,i2c_frequency);
+    log_send_messaging(MESSAGING_INFO,"Initializing i2c driver configuration.\n   mode = I2C_MODE_MASTER, \n   scl_pullup_en = GPIO_PULLUP_ENABLE, \n   i2c port = %u, \n   sda_io_num = %u, \n   sda_pullup_en = GPIO_PULLUP_ENABLE, \n   scl_io_num = %u, \n   scl_pullup_en = GPIO_PULLUP_ENABLE, \n   master.clk_speed = %u", i2c_port, i2c_gpio_sda,i2c_gpio_scl,i2c_frequency);
     if((err=i2c_param_config(i2c_port, &conf))!=ESP_OK){
-    	ESP_LOGE(TAG,"i2c driver config load failed. %s", esp_err_to_name(err));
+    	log_send_messaging(MESSAGING_ERROR,"i2c driver config load failed. %s", esp_err_to_name(err));
     }
     return err;
 }
@@ -299,10 +301,10 @@ esp_err_t i2c_initialize_driver_from_config(){
 	ESP_LOGD(TAG,"Initializing driver from configuration.");
 	i2c_load_configuration();
 	if(is_i2c_started(i2c_port)){
-		ESP_LOGW(TAG, "Stopping i2c driver on port %u", i2c_port);
+		log_send_messaging(MESSAGING_WARNING,"Stopping i2c driver on port %u", i2c_port);
 		//  stop the current driver instance
 		if((err=i2c_driver_delete(i2c_port))!=ESP_OK){
-			ESP_LOGE(TAG,"i2c driver delete failed. %s", esp_err_to_name(err));
+			log_send_messaging(MESSAGING_ERROR,"i2c driver delete failed. %s", esp_err_to_name(err));
 		}
 	}
 	if(err==ESP_OK){
@@ -317,24 +319,23 @@ esp_err_t i2c_initialize_driver_from_config(){
 
 static int do_i2c_stop(int argc, char **argv ){
 
-    int nerrors = arg_parse(argc, argv, (void **)&i2cstop_args);
+    int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&i2cstop_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, i2cstop_args.end, argv[0]);
         return 0;
     }
     if (i2cstop_args.port->count && i2c_get_port(i2cstop_args.port->ival[0], &i2c_port) != ESP_OK) {
         return 1;
     }
-	ESP_LOGW(TAG,"Stopping i2c on port %u.",i2c_port);
+    log_send_messaging(MESSAGING_WARNING,"Stopping i2c on port %u.",i2c_port);
 	i2c_driver_delete(i2c_port);
 	return 0;
 }
 static int do_i2c_check(int argc, char **argv ){
 
 	i2c_port_t port=0;
-    int nerrors = arg_parse(argc, argv, (void **)&i2ccheck_args);
+    int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&i2ccheck_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, i2ccheck_args.end, argv[0]);
+
         return 0;
     }
     port=i2c_port;
@@ -343,22 +344,22 @@ static int do_i2c_check(int argc, char **argv ){
         return 1;
     }
     bool started=is_i2c_started(port);
-	ESP_LOGI(TAG,"i2c is %s on port %u.", started?"started":"not started",port );
+    log_send_messaging(MESSAGING_INFO,"i2c is %s on port %u.", started?"started":"not started",port );
 	return 0;
 }
 static int do_i2c_show_display(int argc, char **argv){
 	char * config_string = (char * )config_alloc_get(NVS_TYPE_STR, "display_config") ;
 	if(config_string){
-		ESP_LOGI(TAG,"Display configuration string is : \n"
-					"display_config = \"%s\"",config_string);
+		log_send_messaging(MESSAGING_INFO,"Display configuration string is : \n"
+				"display_config = \"%s\"",config_string);
 		free(config_string);
 	}
 	else {
-		ESP_LOGW(TAG,"No display configuration found in nvs config display_config");
+		log_send_messaging(MESSAGING_WARNING,"No display configuration found in nvs config display_config");
 	}
 	char * nvs_item = config_alloc_get(NVS_TYPE_STR, "i2c_config");
 	if (nvs_item) {
-		ESP_LOGI(TAG,"I2C configuration is: %s", nvs_item);
+		log_send_messaging(MESSAGING_INFO,"I2C configuration is: %s", nvs_item);
 		free(nvs_item);
 	}
 	return 0;
@@ -367,22 +368,43 @@ static int do_i2c_show_display(int argc, char **argv){
 static int do_i2c_set_display(int argc, char **argv)
 {
 	int width=0, height=0, address=60;
+	int result = 0;
 	char * name = NULL;
 	char * driver= NULL;
+	char * err_message=malloc(1);
 	char config_string[200]={};
-    int nerrors = arg_parse(argc, argv, (void **)&i2cdisp_args);
+	bool bHasi2cConfig = false, bHasSpiConfig=false;
+    int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&i2cdisp_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, i2cdisp_args.end, argv[0]);
         return 0;
     }
 
-	/* Check "--clear" option */
+    char * nvs_item = config_alloc_get(NVS_TYPE_STR, "i2c_config");
+	if (nvs_item && strlen(nvs_item)>0) {
+		bHasi2cConfig=true;
+		FREE_AND_NULL(nvs_item);
+	}
+
+	nvs_item = config_alloc_get(NVS_TYPE_STR, "spi_config");
+	if (nvs_item && strlen(nvs_item)>0) {
+		bHasSpiConfig=true;
+		FREE_AND_NULL(nvs_item);
+	}
+
+		/* Check "--clear" option */
 	if (i2cdisp_args.clear->count) {
-		ESP_LOGW(TAG,"Clearing display config");
+		log_send_messaging(MESSAGING_WARNING,"Display config cleared");
 		config_set_value(NVS_TYPE_STR, "display_config", "");
+		FREE_AND_NULL(err_message);
+		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 "--address" option */
 	if (i2cdisp_args.address->count) {
 		address=i2cdisp_args.address->ival[0];
@@ -393,7 +415,7 @@ static int do_i2c_set_display(int argc, char **argv)
 		width=i2cdisp_args.width->ival[0];
 	}
 	else {
-		ESP_LOGE(TAG,"Missing parameter: --width");
+		fprintf(f,"Missing parameter: --width\n");
 		nerrors ++;
 	}
 
@@ -402,7 +424,7 @@ static int do_i2c_set_display(int argc, char **argv)
 		height=i2cdisp_args.height->ival[0];
 	}
 	else {
-		ESP_LOGE(TAG,"Missing parameter: --height");
+		fprintf(f,"Missing parameter: --height\n");
 		nerrors ++;
 	}
 	/* Check "--name" option */
@@ -418,35 +440,53 @@ static int do_i2c_set_display(int argc, char **argv)
 	if(!name) name = strdup("I2C");
 	if(!driver) driver = strdup("SSD1306");
 
-	bool rotate = i2cdisp_args.rotate->count>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":"" );
-	free(name);
-	free(driver);
 
-	if(nerrors!=0){
-		return 0;
+	if(!display_is_valid_driver(driver)){
+		fprintf(f,"Unsupported display driver %s\n",driver);
+		nerrors++;
 	}
 
-	ESP_LOGI(TAG,"Updating display configuration string configuration to :\n"
-			"display_config = \"%s\"",config_string );
+	if(strcasestr(name,"I2C") && !bHasi2cConfig){
+		fprintf(f,"Please configure I2C bus first. \n");
+	}else if(strcasestr(name,"SPI") && !bHasSpiConfig){
+		fprintf(f,"Please configure SPI bus first. \n");
+	}
+	else if(!strcasestr(name,"I2C") && !strcasestr(name,"SPI")){
+		fprintf(f,"Invalid display type %s\n",name);
+	}
+	bool rotate = i2cdisp_args.rotate->count>0;
 
-	return config_set_value(NVS_TYPE_STR, "display_config", config_string)!=ESP_OK;
+	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":"" );
+		fprintf(f,"Updating display configuration string configuration to :\n"
+				"display_config = \"%s\"",config_string );
+		result = config_set_value(NVS_TYPE_STR, "display_config", config_string)!=ESP_OK;
+	}
+	else {
+		result = 1;
+	}
+	FREE_AND_NULL(name);
+	FREE_AND_NULL(driver);
+	fflush (f);
+	log_send_messaging(nerrors>0?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf);
+	fclose(f);
+	FREE_AND_NULL(buf);
+	return result;
 }
 
 static int do_i2cconfig_cmd(int argc, char **argv)
 {
 	esp_err_t err=ESP_OK;
 	int res=0;
-    int nerrors = arg_parse(argc, argv, (void **)&i2cconfig_args);
+	char * err_message=malloc(1);
+	int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&i2cconfig_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, i2cconfig_args.end, argv[0]);
         return 0;
     }
     /* Check "--load" option */
     if (i2cconfig_args.load->count) {
-    	ESP_LOGW(TAG,"Loading i2c config");
+    	log_send_messaging(MESSAGING_WARNING,"Loading i2c config");
     	i2c_load_configuration();
     }
     else {
@@ -454,6 +494,7 @@ static int do_i2cconfig_cmd(int argc, char **argv)
 		/* Check "--port" option */
 		if (i2cconfig_args.port->count) {
 			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]);
 				return 1;
 			}
 		}
@@ -466,7 +507,7 @@ static int do_i2cconfig_cmd(int argc, char **argv)
 			i2c_gpio_sda = i2cconfig_args.sda->ival[0];
 		}
 		else {
-			ESP_LOGE(TAG,"Missing --sda option.");
+			REALLOC_CAT(err_message,"Missing --sda option.");
 			res=1;
 		}
 
@@ -475,7 +516,7 @@ static int do_i2cconfig_cmd(int argc, char **argv)
 			i2c_gpio_scl = i2cconfig_args.scl->ival[0];
 		}
 		else {
-			ESP_LOGE(TAG,"Missing --scl option.");
+			REALLOC_CAT(err_message,"Missing --scl option.");
 			res=1;
 		}
     }
@@ -483,39 +524,41 @@ static int do_i2cconfig_cmd(int argc, char **argv)
 #ifdef CONFIG_SQUEEZEAMP
 	if (i2c_port == I2C_NUM_0) {
 		i2c_port = I2C_NUM_1;
-		ESP_LOGE(TAG, "can't use i2c port 0 on SqueezeAMP. Changing to port 1.");
+		log_send_messaging(MESSAGING_ERROR, "can't use i2c port 0 on SqueezeAMP. Changing to port 1.");
 	}
 #endif
 	if(!res){
-		ESP_LOGI(TAG, "Uninstall i2c driver from port %u if needed",i2c_port);
+		log_send_messaging(MESSAGING_INFO,"Uninstall i2c driver from port %u if needed",i2c_port);
 		if(is_i2c_started(i2c_port)){
 			if((err=i2c_driver_delete(i2c_port))!=ESP_OK){
-				ESP_LOGE(TAG,"i2c driver delete failed. %s", esp_err_to_name(err));
+				log_send_messaging(MESSAGING_ERROR, "i2c driver delete failed. %s", esp_err_to_name(err));
 				res = 1;
 			}
 		}
 	}
 	if(!res){
-		ESP_LOGI(TAG,"Initializing driver with config scl=%u sda=%u speed=%u port=%u",i2c_gpio_scl,i2c_gpio_sda,i2c_frequency,i2c_port);
+		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);
 		if((err=i2c_master_driver_initialize())==ESP_OK){
-			ESP_LOGI(TAG,"Initalize success.");
+			log_send_messaging(MESSAGING_INFO, "Initalize success.");
 			// now start the i2c driver
-			ESP_LOGI(TAG,"Starting the i2c driver.");
+			log_send_messaging(MESSAGING_INFO,"Starting the i2c driver.");
 			if((err=i2c_master_driver_install())!=ESP_OK){
-				 res=1;
+				log_send_messaging(MESSAGING_ERROR,"I2C master driver install failed. %s", esp_err_to_name(err));
+				res=1;
 			}
 			else
 			{
-				ESP_LOGI(TAG,"i2c driver successfully started.");
+				log_send_messaging(MESSAGING_INFO,"i2c driver successfully started.");
 			}
 		}
 		else {
-			ESP_LOGE(TAG,"I2C initialization failed. %s", esp_err_to_name(err));
+
+			log_send_messaging(MESSAGING_ERROR,"I2C initialization failed. %s", esp_err_to_name(err));
 			res=1;
 		}
 	}
 	if(!res && !i2cconfig_args.load->count){
-			ESP_LOGI(TAG,"Storing i2c parameters.");
+		log_send_messaging(MESSAGING_INFO,"Storing i2c parameters.");
 			i2c_config_t config={
 				.mode = I2C_MODE_MASTER,
 				.sda_io_num = i2c_gpio_sda,
@@ -526,7 +569,10 @@ static int do_i2cconfig_cmd(int argc, char **argv)
 			};
 			config_i2c_set(&config, i2c_port);
 	}
-
+	if(res){
+		log_send_messaging(MESSAGING_ERROR,"%s", err_message);
+	}
+	free(err_message);
     return res;
 }
 
@@ -535,9 +581,8 @@ static int do_i2cconfig_cmd(int argc, char **argv)
 
 static int do_i2cdump_cmd(int argc, char **argv)
 {
-    int nerrors = arg_parse(argc, argv, (void **)&i2cdump_args);
+	int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&i2cdump_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, i2cdump_args.end, argv[0]);
         return 0;
     }
 
@@ -549,19 +594,27 @@ static int do_i2cdump_cmd(int argc, char **argv)
         size = i2cdump_args.size->ival[0];
     }
     if (size != 1 && size != 2 && size != 4) {
-        ESP_LOGE(TAG, "Wrong read size. Only support 1,2,4");
+        log_send_messaging(MESSAGING_ERROR, "Wrong read size. Only support 1,2,4");
         return 1;
     }
     esp_err_t ret = i2c_initialize_driver_from_config();
 	if(ret!=ESP_OK) 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;
+	}
+
     uint8_t data_addr;
     uint8_t data[4];
     int32_t block[16];
-    printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f"
+    fprintf(f,"    00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f"
            "    0123456789abcdef\r\n");
     for (int i = 0; i < 128; i += 16) {
-        printf("%02x: ", i);
+        fprintf(f,"%02x: ", i);
         for (int j = 0; j < 16; j += size) {
             fflush(stdout);
             data_addr = i + j;
@@ -580,40 +633,46 @@ static int do_i2cdump_cmd(int argc, char **argv)
             i2c_cmd_link_delete(cmd);
             if (ret == ESP_OK) {
                 for (int k = 0; k < size; k++) {
-                    printf("%02x ", data[k]);
+                    fprintf(f,"%02x ", data[k]);
                     block[j + k] = data[k];
                 }
             } else {
                 for (int k = 0; k < size; k++) {
-                    printf("XX ");
+                    fprintf(f,"XX ");
                     block[j + k] = -1;
                 }
             }
         }
-        printf("   ");
+        fprintf(f,"   ");
         for (int k = 0; k < 16; k++) {
             if (block[k] < 0) {
-                printf("X");
+                fprintf(f,"X");
             }
             if ((block[k] & 0xff) == 0x00 || (block[k] & 0xff) == 0xff) {
-                printf(".");
+                fprintf(f,".");
             } else if ((block[k] & 0xff) < 32 || (block[k] & 0xff) >= 127) {
-                printf("?");
+                fprintf(f,"?");
             } else {
-                printf("%c", block[k] & 0xff);
+                fprintf(f,"%c", block[k] & 0xff);
             }
         }
-        printf("\r\n");
+        fprintf(f,"\r\n");
     }
     // Don't stop the driver;  our firmware may be using it for screen, etc
     //i2c_driver_delete(i2c_port);
+	fflush (f);
+	log_send_messaging(MESSAGING_INFO,"%s", buf);
+	fclose(f);
+	FREE_AND_NULL(buf);
+
+
     return 0;
 }
 static int do_i2cset_cmd(int argc, char **argv)
 {
-    int nerrors = arg_parse(argc, argv, (void **)&i2cset_args);
+
+	int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&i2cset_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, i2cset_args.end, argv[0]);
         return 0;
     }
 
@@ -645,11 +704,11 @@ static int do_i2cset_cmd(int argc, char **argv)
     esp_err_t ret = i2c_master_cmd_begin(i2c_port, cmd, 1000 / portTICK_RATE_MS);
     i2c_cmd_link_delete(cmd);
     if (ret == ESP_OK) {
-        ESP_LOGI(TAG, "Write OK");
+    	log_send_messaging(MESSAGING_INFO, "i2c Write OK");
     } else if (ret == ESP_ERR_TIMEOUT) {
-        ESP_LOGW(TAG, "Bus is busy");
+    	log_send_messaging(MESSAGING_WARNING, "i2c Bus is busy");
     } else {
-        ESP_LOGW(TAG, "Write Failed");
+    	log_send_messaging(MESSAGING_ERROR,"i2c Read failed");
     }
     // Don't stop the driver;  our firmware may be using it for screen, etc
     //i2c_driver_delete(i2c_port);
@@ -659,9 +718,8 @@ static int do_i2cset_cmd(int argc, char **argv)
 static int do_i2cget_cmd(int argc, char **argv)
 {
 	esp_err_t err=ESP_OK;
-    int nerrors = arg_parse(argc, argv, (void **)&i2cget_args);
+    int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&i2cget_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, i2cget_args.end, argv[0]);
         return 0;
     }
 
@@ -680,13 +738,19 @@ static int do_i2cget_cmd(int argc, char **argv)
 
 
     if((err=i2c_master_driver_initialize())!=ESP_OK){
-      	ESP_LOGE(TAG,"Error initializing i2c driver. %s",esp_err_to_name(err));
+    	log_send_messaging(MESSAGING_ERROR,"Error initializing i2c driver. %s",esp_err_to_name(err));
       	return 1;
      }
 	if((err=i2c_master_driver_install())!=ESP_OK){
 		 return 1;
 	}
-
+	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;
+	}
     i2c_cmd_handle_t cmd = i2c_cmd_link_create();
     i2c_master_start(cmd);
     uint8_t *data = malloc(len);
@@ -705,22 +769,28 @@ static int do_i2cget_cmd(int argc, char **argv)
     i2c_cmd_link_delete(cmd);
     if (ret == ESP_OK) {
         for (int i = 0; i < len; i++) {
-            printf("0x%02x ", data[i]);
+            fprintf(f,"0x%02x ", data[i]);
             if ((i + 1) % 16 == 0) {
-                printf("\r\n");
+                fprintf(f,"\r\n");
             }
         }
         if (len % 16) {
-            printf("\r\n");
+            fprintf(f,"\r\n");
         }
     } else if (ret == ESP_ERR_TIMEOUT) {
-        ESP_LOGW(TAG, "Bus is busy");
+    	log_send_messaging(MESSAGING_WARNING, "i2c Bus is busy");
     } else {
-        ESP_LOGW(TAG, "Read failed");
+    	log_send_messaging(MESSAGING_ERROR,"i2c Read failed");
     }
     free(data);
+
     // Don't stop the driver;  our firmware may be using it for screen, etc
     //i2c_driver_delete(i2c_port);
+	fflush (f);
+	log_send_messaging(MESSAGING_INFO,"%s", buf);
+	fclose(f);
+	FREE_AND_NULL(buf);
+
     return 0;
 }
 
@@ -729,13 +799,24 @@ static int do_i2cdetect_cmd(int argc, char **argv)
 	uint8_t matches[128]={};
 	int last_match=0;
 	esp_err_t ret = i2c_initialize_driver_from_config();
-	if(ret!=ESP_OK) return 0;
+	if(ret!=ESP_OK) {
+		log_send_messaging(MESSAGING_ERROR,"i2c driver init failed.");
+		return 0;
+	}
     uint8_t address;
-    printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\r\n");
+    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;
+	}
+
+
+    fprintf(f,"     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\r\n");
     for (int i = 0; i < 128 ; i += 16) {
-        printf("%02x: ", i);
+        fprintf(f,"%02x: ", i);
         for (int j = 0; j < 16 ; j++) {
-            fflush(stdout);
             address = i + j;
             i2c_cmd_handle_t cmd = i2c_cmd_link_create();
             i2c_master_start(cmd);
@@ -744,36 +825,62 @@ static int do_i2cdetect_cmd(int argc, char **argv)
             ret = i2c_master_cmd_begin(i2c_port, cmd, 50 / portTICK_RATE_MS);
             i2c_cmd_link_delete(cmd);
             if (ret == ESP_OK) {
-                printf("%02x ", address);
+                fprintf(f,"%02x ", address);
                 matches[++last_match-1] = address;
             } else if (ret == ESP_ERR_TIMEOUT) {
-                printf("UU ");
+                fprintf(f,"UU ");
             } else {
-                printf("-- ");
+                fprintf(f,"-- ");
             }
         }
 
-        printf("\r\n");
+        fprintf(f,"\r\n");
 
     }
     if(last_match) {
-    	printf("\r\n------------------------------------------------------------------------------------"
+    	fprintf(f,"\r\n------------------------------------------------------------------------------------"
     		   "\r\nDetected the following devices (names provided by https://i2cdevices.org/addresses).");
 
 		for(int i=0;i<last_match;i++){
 			//printf("%02x = %s\r\n", matches[i], i2c_get_description(matches[i]));
-			printf("\r\n%u [%02xh]- %s", matches[i], matches[i], i2c_get_description(matches[i]));
+			fprintf(f,"\r\n%u [%02xh]- %s", matches[i], matches[i], i2c_get_description(matches[i]));
 		}
-		printf("\r\n------------------------------------------------------------------------------------\r\n");
+		fprintf(f,"\r\n------------------------------------------------------------------------------------\r\n");
     }
 
+	fflush (f);
+	log_send_messaging(MESSAGING_INFO,"%s", buf);
+	fclose(f);
+	FREE_AND_NULL(buf);
+
     return 0;
 }
+cJSON * i2c_set_display_cb(){
+	cJSON * values = cJSON_CreateObject();
+	const display_config_t * conf= config_display_get();
+	if(conf){
+		cJSON_AddNumberToObject(values,"address",conf->address);
+		cJSON_AddNumberToObject(values,"width",conf->width);
+		cJSON_AddNumberToObject(values,"height",conf->height);
+		cJSON_AddStringToObject(values,"type",conf->type);
+		cJSON_AddStringToObject(values,"driver",conf->drivername);
+		cJSON_AddBoolToObject(values,"hf",conf->hflip);
+		cJSON_AddBoolToObject(values,"vf",conf->vflip);
+		if(conf->vflip && conf->hflip){
+			cJSON_AddBoolToObject(values,"rotate",true);
+		}
+		else {
+			cJSON_AddBoolToObject(values,"rotate",false);
+		}
+	}
+	return values;
+}
+
 static void register_i2c_set_display(){
 	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.height = arg_int0("h", "height", "<n>", "Set the display height");
-	i2cdisp_args.name = arg_str0("t", "type", "<I2C|SPI>", "Set the display type. 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.clear = arg_lit0(NULL, "clear", "clear configuration and return");
 	i2cdisp_args.hflip = arg_lit0(NULL, "hf", "Flip picture horizontally");
@@ -795,7 +902,7 @@ static void register_i2c_set_display(){
 			.func = &do_i2c_show_display,
 			.argtable = NULL
 	};
-	cmd_to_json(&i2c_set_display);
+	cmd_to_json_with_cb(&i2c_set_display,&i2c_set_display_cb);
 	cmd_to_json(&i2c_show_display);
 	ESP_ERROR_CHECK(esp_console_cmd_register(&i2c_set_display));
 	ESP_ERROR_CHECK(esp_console_cmd_register(&i2c_show_display));
@@ -830,7 +937,6 @@ static void register_i2cget(void)
     ESP_ERROR_CHECK(esp_console_cmd_register(&i2cget_cmd));
 }
 
-
 static void register_i2cset(void)
 {
     i2cset_args.chip_address = arg_int1("c", "chip", "<chip_addr>", "Specify the address of the chip on that bus");
@@ -883,7 +989,7 @@ static void register_i2ccheck(){
 
 
 static void register_i2cstop(){
-	i2cstop_args.port = arg_int0("p", "port", "<0|1>", "Set the I2C bus port number");
+	i2cstop_args.port = arg_int0("p", "port", "<0|1>", "I2C bus port number");
 	i2cstop_args.end = arg_end(2);
 
     const esp_console_cmd_t i2cconfig_cmd = {
@@ -897,7 +1003,16 @@ static void register_i2cstop(){
     ESP_ERROR_CHECK(esp_console_cmd_register(&i2cconfig_cmd));
 }
 
-
+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);
+	return values;
+}
 static void register_i2cconfig(void)
 {
     i2cconfig_args.port = arg_int0("p", "port", "0|1", "Set the I2C bus port number");
@@ -913,7 +1028,7 @@ static void register_i2cconfig(void)
         .func = &do_i2cconfig_cmd,
         .argtable = &i2cconfig_args
     };
-    cmd_to_json(&i2cconfig_cmd);
+    cmd_to_json_with_cb(&i2cconfig_cmd,&i2config_cb);
     ESP_ERROR_CHECK(esp_console_cmd_register(&i2cconfig_cmd));
 }
 

+ 31 - 46
components/platform_console/cmd_nvs.c

@@ -26,7 +26,7 @@ extern "C" {
 #include "nvs.h"
 #include "nvs_utilities.h"
 #include "platform_console.h"
-
+#include "messaging.h"
 
 
 static const char *ARG_TYPE_STR = "type can be: i8, u8, i16, u16 i32, u32 i64, u64, str, blob";
@@ -71,7 +71,7 @@ static esp_err_t store_blob(nvs_handle nvs, const char *key, const char *str_val
     size_t blob_len = str_len / 2;
 
     if (str_len % 2) {
-        ESP_LOGE(TAG, "Blob data must contain even number of characters");
+    	log_send_messaging(MESSAGING_ERROR, "Blob data must contain even number of characters");
         return ESP_ERR_NVS_TYPE_MISMATCH;
     }
 
@@ -89,7 +89,7 @@ static esp_err_t store_blob(nvs_handle nvs, const char *key, const char *str_val
         } else if (ch >= 'a' && ch <= 'f') {
             value = ch - 'a' + 10;
         } else {
-            ESP_LOGE(TAG, "Blob data contain invalid character");
+        	log_send_messaging(MESSAGING_ERROR, "Blob data contain invalid character");
             free(blob);
             return ESP_ERR_NVS_TYPE_MISMATCH;
         }
@@ -188,10 +188,10 @@ static esp_err_t set_value_in_nvs(const char *key, const char *str_type, const c
     }
 
     if (err == ESP_OK) {
-    	ESP_LOGI(TAG, "Set value ok. Committing '%s'", key);
+    	log_send_messaging(MESSAGING_INFO, "Set value ok. Committing '%s'", key);
         err = nvs_commit(nvs);
         if (err == ESP_OK) {
-            ESP_LOGI(TAG, "Value stored under key '%s'", key);
+        	log_send_messaging(MESSAGING_INFO, "Value stored under key '%s'", key);
         }
     }
 
@@ -219,51 +219,51 @@ static esp_err_t get_value_from_nvs(const char *key, const char *str_type)
         int8_t value;
         err = nvs_get_i8(nvs, key, &value);
         if (err == ESP_OK) {
-            printf("Value associated with key '%s' is %d \n", key, value);
+        	log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %d \n", key, value);
         }
     } else if (type == NVS_TYPE_U8) {
         uint8_t value;
         err = nvs_get_u8(nvs, key, &value);
         if (err == ESP_OK) {
-            printf("Value associated with key '%s' is %u \n", key, value);
+        	log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %u \n", key, value);
         }
     } else if (type == NVS_TYPE_I16) {
         int16_t value;
         err = nvs_get_i16(nvs, key, &value);
         if (err == ESP_OK) {
-            printf("Value associated with key '%s' is %d \n", key, value);
+        	log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %d \n", key, value);
         }
     } else if (type == NVS_TYPE_U16) {
         uint16_t value;
         if ((err = nvs_get_u16(nvs, key, &value)) == ESP_OK) {
-            printf("Value associated with key '%s' is %u", key, value);
+        	log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %u", key, value);
         }
     } else if (type == NVS_TYPE_I32) {
         int32_t value;
         if ((err = nvs_get_i32(nvs, key, &value)) == ESP_OK) {
-            printf("Value associated with key '%s' is %d \n", key, value);
+        	log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %d \n", key, value);
         }
     } else if (type == NVS_TYPE_U32) {
         uint32_t value;
         if ((err = nvs_get_u32(nvs, key, &value)) == ESP_OK) {
-            printf("Value associated with key '%s' is %u \n", key, value);
+        	log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %u \n", key, value);
         }
     } else if (type == NVS_TYPE_I64) {
         int64_t value;
         if ((err = nvs_get_i64(nvs, key, &value)) == ESP_OK) {
-            printf("Value associated with key '%s' is %lld \n", key, value);
+        	log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %lld \n", key, value);
         }
     } else if (type == NVS_TYPE_U64) {
         uint64_t value;
         if ( (err = nvs_get_u64(nvs, key, &value)) == ESP_OK) {
-            printf("Value associated with key '%s' is %llu \n", key, value);
+        	log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %llu \n", key, value);
         }
     } else if (type == NVS_TYPE_STR) {
         size_t len=0;
         if ( (err = nvs_get_str(nvs, key, NULL, &len)) == ESP_OK) {
             char *str = (char *)malloc(len);
             if ( (err = nvs_get_str(nvs, key, str, &len)) == ESP_OK) {
-                printf("String associated with key '%s' is %s \n", key, str);
+            	log_send_messaging(MESSAGING_INFO,"String associated with key '%s' is %s \n", key, str);
             }
             free(str);
         }
@@ -272,7 +272,7 @@ static esp_err_t get_value_from_nvs(const char *key, const char *str_type)
         if ( (err = nvs_get_blob(nvs, key, NULL, &len)) == ESP_OK) {
             char *blob = (char *)malloc(len);
             if ( (err = nvs_get_blob(nvs, key, blob, &len)) == ESP_OK) {
-                printf("Blob associated with key '%s' is %d bytes long: \n", key, len);
+            	log_send_messaging(MESSAGING_INFO,"Blob associated with key '%s' is %d bytes long: \n", key, len);
                 print_blob(blob, len);
             }
             free(blob);
@@ -293,7 +293,7 @@ static esp_err_t erase(const char *key)
         if (err == ESP_OK) {
             err = nvs_commit(nvs);
             if (err == ESP_OK) {
-                ESP_LOGI(TAG, "Value with key '%s' erased", key);
+            	log_send_messaging(MESSAGING_INFO, "Value with key '%s' erased", key);
             }
         }
         nvs_close(nvs);
@@ -314,7 +314,7 @@ static esp_err_t erase_all(const char *name)
         }
     }
 
-    ESP_LOGI(TAG, "Namespace '%s' was %s erased", name, (err == ESP_OK) ? "" : "not");
+    log_send_messaging(MESSAGING_INFO, "Namespace '%s' was %s erased", name, (err == ESP_OK) ? "" : "not");
     nvs_close(nvs);
     return ESP_OK;
 }
@@ -322,22 +322,19 @@ static esp_err_t erase_all(const char *name)
 static int set_value(int argc, char **argv)
 {
 	ESP_LOGD(TAG, "%s %u - Parsing keys ",__func__,__LINE__);
-    int nerrors = arg_parse(argc, argv, (void **) &set_args);
-
+    int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&set_args);
     if (nerrors != 0) {
-    	ESP_LOGE(TAG, "%s %u - Error Parsing keys ",__func__,__LINE__);
-        arg_print_errors(stderr, set_args.end, argv[0]);
         return 1;
     }
 
     const char *key = set_args.key->sval[0];
     const char *type = set_args.type->sval[0];
     const char *values = set_args.value->sval[0];
-    ESP_LOGI(TAG, "Setting '%s' (type %s)", key,type);
+    log_send_messaging(MESSAGING_INFO, "Setting '%s' (type %s)", key,type);
     esp_err_t err = set_value_in_nvs(key, type, values);
 
     if (err != ESP_OK) {
-        ESP_LOGE(TAG, "%s", esp_err_to_name(err));
+    	log_send_messaging(MESSAGING_ERROR, "%s", esp_err_to_name(err));
         return 1;
     }
 
@@ -347,9 +344,8 @@ static int set_value(int argc, char **argv)
 
 static int get_value(int argc, char **argv)
 {
-    int nerrors = arg_parse(argc, argv, (void **) &get_args);
+	int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&get_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, get_args.end, argv[0]);
         return 1;
     }
 
@@ -359,7 +355,7 @@ static int get_value(int argc, char **argv)
     esp_err_t err = get_value_from_nvs(key, type);
 
     if (err != ESP_OK) {
-        ESP_LOGE(TAG, "%s", esp_err_to_name(err));
+    	log_send_messaging(MESSAGING_ERROR, "%s", esp_err_to_name(err));
         return 1;
     }
 
@@ -368,9 +364,8 @@ static int get_value(int argc, char **argv)
 
 static int erase_value(int argc, char **argv)
 {
-    int nerrors = arg_parse(argc, argv, (void **) &erase_args);
+	int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&erase_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, erase_args.end, argv[0]);
         return 1;
     }
 
@@ -379,7 +374,7 @@ static int erase_value(int argc, char **argv)
     esp_err_t err = erase(key);
 
     if (err != ESP_OK) {
-        ESP_LOGE(TAG, "%s", esp_err_to_name(err));
+    	log_send_messaging(MESSAGING_ERROR, "%s", esp_err_to_name(err));
         return 1;
     }
 
@@ -388,9 +383,8 @@ static int erase_value(int argc, char **argv)
 
 static int erase_namespace(int argc, char **argv)
 {
-    int nerrors = arg_parse(argc, argv, (void **) &erase_all_args);
+	int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&erase_all_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, erase_all_args.end, argv[0]);
         return 1;
     }
 
@@ -398,7 +392,7 @@ static int erase_namespace(int argc, char **argv)
 
     esp_err_t err = erase_all(name);
     if (err != ESP_OK) {
-        ESP_LOGE(TAG, "%s", esp_err_to_name(err));
+    	log_send_messaging(MESSAGING_ERROR, "%s", esp_err_to_name(err));
         return 1;
     }
 
@@ -417,11 +411,11 @@ static int erase_wifi_manager(int argc, char **argv)
 	}
 	nvs_close(nvs);
 	if (err != ESP_OK) {
-		ESP_LOGE(TAG, "wifi manager configuration was not erase. %s", esp_err_to_name(err));
+		log_send_messaging(MESSAGING_ERROR,  "wifi manager configuration was not erase. %s", esp_err_to_name(err));
 		return 1;
 	}
 	else {
-		ESP_LOGW(TAG, "Wifi manager configuration was erased");
+		log_send_messaging(MESSAGING_WARNING,  "Wifi manager configuration was erased");
 	}
 	return 0;
 }
@@ -433,7 +427,7 @@ static int list(const char *part, const char *name, const char *str_type)
 
     nvs_iterator_t it = nvs_entry_find(part, NULL, type);
     if (it == NULL) {
-        ESP_LOGE(TAG, "No such enty was found");
+    	log_send_messaging(MESSAGING_ERROR, "No such enty was found");
         return 1;
     }
 
@@ -442,7 +436,7 @@ static int list(const char *part, const char *name, const char *str_type)
         nvs_entry_info(it, &info);
         it = nvs_entry_next(it);
 
-        printf("namespace '%s', key '%s', type '%s' \n",
+        log_send_messaging(MESSAGING_INFO, "namespace '%s', key '%s', type '%s' \n",
                info.namespace_name, info.key, type_to_str(info.type));
     } while (it != NULL);
 
@@ -454,9 +448,8 @@ static int list_entries(int argc, char **argv)
     list_args.namespace->sval[0] = "";
     list_args.type->sval[0] = "";
 
-    int nerrors = arg_parse(argc, argv, (void **) &list_args);
+    int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&list_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, list_args.end, argv[0]);
         return 1;
     }
 
@@ -548,14 +541,6 @@ void register_nvs()
     ESP_ERROR_CHECK(esp_console_cmd_register(&erase_cmd));
     ESP_ERROR_CHECK(esp_console_cmd_register(&erase_namespace_cmd));
     ESP_ERROR_CHECK(esp_console_cmd_register(&erase_wifimanager_cmd));
-    cmd_to_json(&list_entries_cmd);
-    cmd_to_json(&set_cmd);
-    cmd_to_json(&get_cmd);
-    cmd_to_json(&erase_cmd);
-    cmd_to_json(&erase_namespace_cmd);
-    cmd_to_json(&erase_wifimanager_cmd);
-
-
 
 }
 #ifdef __cplusplus

+ 3 - 2
components/platform_console/cmd_ota.c

@@ -25,6 +25,8 @@
 #include "soc/rtc_cntl_reg.h"
 #include "esp32/rom/uart.h"
 #include "sdkconfig.h"
+#include "platform_console.h"
+#include "messaging.h"
 
 static const char * TAG = "ota";
 extern esp_err_t start_ota(const char * bin_url);
@@ -35,9 +37,8 @@ static struct {
 /* 'heap' command prints minumum heap size */
 static int perform_ota_update(int argc, char **argv)
 {
-    int nerrors = arg_parse(argc, argv, (void **) &ota_args);
+	int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&ota_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, ota_args.end, argv[0]);
         return 1;
     }
 

+ 53 - 59
components/platform_console/cmd_system.c

@@ -72,17 +72,19 @@ static int get_version(int argc, char **argv)
 {
     esp_chip_info_t info;
     esp_chip_info(&info);
-    printf("IDF Version:%s\r\n", esp_get_idf_version());
-    printf("Chip info:\r\n");
-    printf("\tmodel:%s\r\n", info.model == CHIP_ESP32 ? "ESP32" : "Unknow");
-    printf("\tcores:%d\r\n", info.cores);
-    printf("\tfeature:%s%s%s%s%d%s\r\n",
-           info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "",
-           info.features & CHIP_FEATURE_BLE ? "/BLE" : "",
-           info.features & CHIP_FEATURE_BT ? "/BT" : "",
-           info.features & CHIP_FEATURE_EMB_FLASH ? "/Embedded-Flash:" : "/External-Flash:",
-           spi_flash_get_chip_size() / (1024 * 1024), " MB");
-    printf("\trevision number:%d\r\n", info.revision);
+    log_send_messaging(MESSAGING_INFO,
+    "IDF Version:%s\r\n"
+    "Chip info:\r\n"
+    "\tmodel:%s\r\n"
+    "\tcores:%d\r\n"
+    "\tfeature:%s%s%s%s%d%s\r\n"
+    "\trevision number:%d\r\n",
+		esp_get_idf_version(), info.model == CHIP_ESP32 ? "ESP32" : "Unknow", info.cores,
+		info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "",
+		info.features & CHIP_FEATURE_BLE ? "/BLE" : "",
+		info.features & CHIP_FEATURE_BT ? "/BT" : "",
+		info.features & CHIP_FEATURE_EMB_FLASH ? "/Embedded-Flash:" : "/External-Flash:",
+		spi_flash_get_chip_size() / (1024 * 1024), " MB", info.revision);
     return 0;
 }
 
@@ -105,9 +107,9 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
 {
 if(is_recovery_running){
 	if(partition_subtype ==ESP_PARTITION_SUBTYPE_APP_FACTORY){
-		ESP_LOGW(TAG,"RECOVERY application is already active");
+		log_send_messaging(MESSAGING_WARNING,"RECOVERY application is already active");
 		if(!wait_for_commit()){
-			ESP_LOGW(TAG,"Unable to commit configuration. ");
+			log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. ");
 		}
 		
 		vTaskDelay(750/ portTICK_PERIOD_MS);
@@ -117,9 +119,9 @@ if(is_recovery_running){
 }
 else {
 	if(partition_subtype !=ESP_PARTITION_SUBTYPE_APP_FACTORY){
-		ESP_LOGW(TAG,"SQUEEZELITE application is already active");
+		log_send_messaging(MESSAGING_WARNING,"SQUEEZELITE application is already active");
 		if(!wait_for_commit()){
-			ESP_LOGW(TAG,"Unable to commit configuration. ");
+			log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. ");
 		}
 		
 		vTaskDelay(750/ portTICK_PERIOD_MS);
@@ -129,13 +131,12 @@ else {
 }
 	esp_err_t err = ESP_OK;
 	bool bFound=false;
-    ESP_LOGI(TAG, "Looking for partition type %u",partition_subtype);
+    log_send_messaging(MESSAGING_INFO, "Looking for partition type %u",partition_subtype);
     const esp_partition_t *partition;
 	esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, partition_subtype, NULL);
 
 	if(it == NULL){
-		ESP_LOGE(TAG,"Unable initialize partition iterator!");
-		messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Reboot failed. Cannot iterate through partitions");
+		log_send_messaging(MESSAGING_ERROR,"Reboot failed. Cannot iterate through partitions");
 	}
 	else
 	{
@@ -144,31 +145,29 @@ else {
 		ESP_LOGD(TAG, "Releasing partition iterator");
 		esp_partition_iterator_release(it);
 		if(partition != NULL){
-			ESP_LOGI(TAG, "Found application partition %s sub type %u", partition->label,partition_subtype);
+			log_send_messaging(MESSAGING_INFO, "Found application partition %s sub type %u", partition->label,partition_subtype);
 			err=esp_ota_set_boot_partition(partition);
 			if(err!=ESP_OK){
-				ESP_LOGE(TAG,"Unable to set partition as active for next boot. %s",esp_err_to_name(err));
 				bFound=false;
-				messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Unable to select partition for reboot: %s",esp_err_to_name(err));
+				log_send_messaging(MESSAGING_ERROR,"Unable to select partition for reboot: %s",esp_err_to_name(err));
 			}
 			else{
-				ESP_LOGW(TAG, "Application partition %s sub type %u is selected for boot", partition->label,partition_subtype);
+				log_send_messaging(MESSAGING_WARNING, "Application partition %s sub type %u is selected for boot", partition->label,partition_subtype);
 				bFound=true;
 				messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"Reboot failed. Cannot iterate through partitions");
 			}
 		}
 		else
 		{
-			ESP_LOGE(TAG,"partition type %u not found!  Unable to reboot to recovery.",partition_subtype);
-			messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"partition type %u not found!  Unable to reboot to recovery.",partition_subtype);
+			log_send_messaging(MESSAGING_ERROR,"partition type %u not found!  Unable to reboot to recovery.",partition_subtype);
 
 		}
 		ESP_LOGD(TAG, "Yielding to other processes");
 		taskYIELD();
 		if(bFound) {
-			ESP_LOGW(TAG,"Configuration %s changes. ",config_has_changes()?"has":"does not have");
+			log_send_messaging(MESSAGING_WARNING,"Configuration %s changes. ",config_has_changes()?"has":"does not have");
 			if(!wait_for_commit()){
-				ESP_LOGW(TAG,"Unable to commit configuration. ");
+				log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. ");
 			}
 			vTaskDelay(750/ portTICK_PERIOD_MS);
 			esp_restart();
@@ -180,9 +179,9 @@ else {
 
 static int restart(int argc, char **argv)
 {
-	ESP_LOGW(TAG, "\n\nPerforming a simple restart to the currently active partition.");
+	log_send_messaging(MESSAGING_WARNING, "\n\nPerforming a simple restart to the currently active partition.");
 	if(!wait_for_commit()){
-		ESP_LOGW(TAG,"Unable to commit configuration. ");
+		log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. ");
 	}
     vTaskDelay(750/ portTICK_PERIOD_MS);
     esp_restart();
@@ -191,9 +190,9 @@ static int restart(int argc, char **argv)
 
 void simple_restart()
 {
-	ESP_LOGW(TAG,"\n\n Called to perform a simple system reboot.");
+	log_send_messaging(MESSAGING_WARNING,"\n\n Called to perform a simple system reboot.");
 	if(!wait_for_commit()){
-		ESP_LOGW(TAG,"Unable to commit configuration. ");
+		log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. ");
 	}
 
 											   
@@ -202,24 +201,24 @@ void simple_restart()
 }
 
 esp_err_t guided_restart_ota(){
-	ESP_LOGW(TAG,"\n\nCalled for a reboot to OTA Application");
+	log_send_messaging(MESSAGING_WARNING,"\n\nCalled for a reboot to OTA Application");
     guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0);
 	return ESP_FAIL; // return fail.  This should never return... we're rebooting!
 }
 esp_err_t guided_factory(){
-	ESP_LOGW(TAG,"\n\nCalled for a reboot to recovery application");
+	log_send_messaging(MESSAGING_WARNING,"\n\nCalled for a reboot to recovery application");
 	guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY);
 	return ESP_FAIL; // return fail.  This should never return... we're rebooting!
 }
 static int restart_factory(int argc, char **argv)
 {
-	ESP_LOGW(TAG, "Executing guided boot into recovery");
+	log_send_messaging(MESSAGING_WARNING, "Executing guided boot into recovery");
 	guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY);
 	return 0; // return fail.  This should never return... we're rebooting!
 }
 static int restart_ota(int argc, char **argv)
 {
-	ESP_LOGW(TAG, "Executing guided boot into ota app 0");
+	log_send_messaging(MESSAGING_WARNING, "Executing guided boot into ota app 0");
 	guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0);
 	return 0; // return fail.  This should never return... we're rebooting!
 }
@@ -261,7 +260,7 @@ static void register_factory_boot()
 
 static int free_mem(int argc, char **argv)
 {
-    printf("%d\n", esp_get_free_heap_size());
+	log_send_messaging(MESSAGING_INFO,"%d", esp_get_free_heap_size());
     return 0;
 }
 
@@ -281,7 +280,7 @@ static void register_free()
 static int heap_size(int argc, char **argv)
 {
     uint32_t heap_size = heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT);
-    ESP_LOGI(TAG, "min heap size: %u", heap_size);
+    log_send_messaging(MESSAGING_INFO, "min heap size: %u", heap_size);
     return 0;
 }
 
@@ -289,7 +288,7 @@ static void register_heap()
 {
     const esp_console_cmd_t heap_cmd = {
         .command = "heap",
-        .help = "Get minimum size of free heap memory that was available during program execution",
+        .help = "Get minimum size of free heap memory found during execution",
         .hint = NULL,
         .func = &heap_size,
     };
@@ -306,16 +305,16 @@ static int tasks_info(int argc, char **argv)
     const size_t bytes_per_task = 40; /* see vTaskList description */
     char *task_list_buffer = malloc(uxTaskGetNumberOfTasks() * bytes_per_task);
     if (task_list_buffer == NULL) {
-        ESP_LOGE(TAG, "failed to allocate buffer for vTaskList output");
+    	log_send_messaging(MESSAGING_ERROR, "failed to allocate buffer for vTaskList output");
         return 1;
     }
-    fputs("Task Name\tStatus\tPrio\tHWM\tTask#", stdout);
+    log_send_messaging(MESSAGING_INFO,"Task Name\tStatus\tPrio\tHWM\tTask#"
 #ifdef CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID
-    fputs("\tAffinity", stdout);
+    "\tAffinity"
 #endif
-    fputs("\n", stdout);
+    "\n");
     vTaskList(task_list_buffer);
-    fputs(task_list_buffer, stdout);
+    log_send_messaging(MESSAGING_INFO,"%s", task_list_buffer);
     free(task_list_buffer);
     return 0;
 }
@@ -328,7 +327,6 @@ static void register_tasks()
         .hint = NULL,
         .func = &tasks_info,
     };
-    cmd_to_json(&cmd);
     ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
 }
 
@@ -346,31 +344,30 @@ static struct {
 
 static int deep_sleep(int argc, char **argv)
 {
-    int nerrors = arg_parse(argc, argv, (void **) &deep_sleep_args);
+	int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&deep_sleep_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, deep_sleep_args.end, argv[0]);
         return 1;
     }
     if (deep_sleep_args.wakeup_time->count) {
         uint64_t timeout = 1000ULL * deep_sleep_args.wakeup_time->ival[0];
-        ESP_LOGI(TAG, "Enabling timer wakeup, timeout=%lluus", timeout);
+        log_send_messaging(MESSAGING_INFO, "Enabling timer wakeup, timeout=%lluus", timeout);
         ESP_ERROR_CHECK( esp_sleep_enable_timer_wakeup(timeout) );
     }
     if (deep_sleep_args.wakeup_gpio_num->count) {
         int io_num = deep_sleep_args.wakeup_gpio_num->ival[0];
         if (!rtc_gpio_is_valid_gpio(io_num)) {
-            ESP_LOGE(TAG, "GPIO %d is not an RTC IO", io_num);
+        	log_send_messaging(MESSAGING_ERROR, "GPIO %d is not an RTC IO", io_num);
             return 1;
         }
         int level = 0;
         if (deep_sleep_args.wakeup_gpio_level->count) {
             level = deep_sleep_args.wakeup_gpio_level->ival[0];
             if (level != 0 && level != 1) {
-                ESP_LOGE(TAG, "Invalid wakeup level: %d", level);
+            	log_send_messaging(MESSAGING_ERROR, "Invalid wakeup level: %d", level);
                 return 1;
             }
         }
-        ESP_LOGI(TAG, "Enabling wakeup on GPIO%d, wakeup on %s level",
+        log_send_messaging(MESSAGING_INFO, "Enabling wakeup on GPIO%d, wakeup on %s level",
                  io_num, level ? "HIGH" : "LOW");
 
         ESP_ERROR_CHECK( esp_sleep_enable_ext1_wakeup(1ULL << io_num, level) );
@@ -399,7 +396,6 @@ static void register_deep_sleep()
         .func = &deep_sleep,
         .argtable = &deep_sleep_args
     };
-    cmd_to_json(&cmd);
     ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
 }
 
@@ -414,30 +410,29 @@ static struct {
 
 static int light_sleep(int argc, char **argv)
 {
-    int nerrors = arg_parse(argc, argv, (void **) &light_sleep_args);
+	int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&light_sleep_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, light_sleep_args.end, argv[0]);
         return 1;
     }
     esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
     if (light_sleep_args.wakeup_time->count) {
         uint64_t timeout = 1000ULL * light_sleep_args.wakeup_time->ival[0];
-        ESP_LOGI(TAG, "Enabling timer wakeup, timeout=%lluus", timeout);
+        log_send_messaging(MESSAGING_INFO, "Enabling timer wakeup, timeout=%lluus", timeout);
         ESP_ERROR_CHECK( esp_sleep_enable_timer_wakeup(timeout) );
     }
     int io_count = light_sleep_args.wakeup_gpio_num->count;
     if (io_count != light_sleep_args.wakeup_gpio_level->count) {
-        ESP_LOGE(TAG, "Should have same number of 'io' and 'io_level' arguments");
+    	log_send_messaging(MESSAGING_INFO,  "Should have same number of 'io' and 'io_level' arguments");
         return 1;
     }
     for (int i = 0; i < io_count; ++i) {
         int io_num = light_sleep_args.wakeup_gpio_num->ival[i];
         int level = light_sleep_args.wakeup_gpio_level->ival[i];
         if (level != 0 && level != 1) {
-            ESP_LOGE(TAG, "Invalid wakeup level: %d", level);
+        	log_send_messaging(MESSAGING_ERROR, "Invalid wakeup level: %d", level);
             return 1;
         }
-        ESP_LOGI(TAG, "Enabling wakeup on GPIO%d, wakeup on %s level",
+        log_send_messaging(MESSAGING_INFO,  "Enabling wakeup on GPIO%d, wakeup on %s level",
                  io_num, level ? "HIGH" : "LOW");
 
         ESP_ERROR_CHECK( gpio_wakeup_enable(io_num, level ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL) );
@@ -446,7 +441,7 @@ static int light_sleep(int argc, char **argv)
         ESP_ERROR_CHECK( esp_sleep_enable_gpio_wakeup() );
     }
     if (CONFIG_ESP_CONSOLE_UART_NUM <= UART_NUM_1) {
-        ESP_LOGI(TAG, "Enabling UART wakeup (press ENTER to exit light sleep)");
+    	log_send_messaging(MESSAGING_INFO,  "Enabling UART wakeup (press ENTER to exit light sleep)");
         ESP_ERROR_CHECK( uart_set_wakeup_threshold(CONFIG_ESP_CONSOLE_UART_NUM, 3) );
         ESP_ERROR_CHECK( esp_sleep_enable_uart_wakeup(CONFIG_ESP_CONSOLE_UART_NUM) );
     }
@@ -469,7 +464,7 @@ static int light_sleep(int argc, char **argv)
         cause_str = "unknown";
         printf("%d\n", cause);
     }
-    ESP_LOGI(TAG, "Woke up from: %s", cause_str);
+    log_send_messaging(MESSAGING_INFO, "Woke up from: %s", cause_str);
     return 0;
 }
 
@@ -496,6 +491,5 @@ static void register_light_sleep()
         .argtable = &light_sleep_args
     };
     ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
-    cmd_to_json(&cmd);
 }
 

+ 1 - 2
components/platform_console/cmd_wifi.c

@@ -158,9 +158,8 @@ static int set_auto_connect(int argc, char **argv)
 }
 static int connect(int argc, char **argv)
 {
-    int nerrors = arg_parse(argc, argv, (void **) &join_args);
+	int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&join_args);
     if (nerrors != 0) {
-        arg_print_errors(stderr, join_args.end, argv[0]);
         return 1;
     }
     ESP_LOGI(__func__, "Connecting to '%s'",

+ 70 - 7
components/platform_console/platform_console.c

@@ -30,6 +30,7 @@
 #include "platform_config.h"
 #include "telnet.h"
 
+#include "messaging.h"
 
 #include "config.h"
 pthread_t thread_console;
@@ -56,8 +57,36 @@ void run_command(char * line);
 #define ADD_TO_JSON(o,t,n) if (t->n) cJSON_AddStringToObject(o,QUOTE(n),t->n);
 #define ADD_PARMS_TO_CMD(o,t,n) { cJSON * parms = ParmsToJSON(&t.n->hdr); if(parms) cJSON_AddItemToObject(o,QUOTE(n),parms); }
 cJSON * cmdList;
+cJSON * values_fn_list;
 cJSON * get_cmd_list(){
-	return cmdList;
+	cJSON * element;
+	cJSON * values=cJSON_CreateObject();
+	cJSON * list = cJSON_CreateObject();
+	cJSON_AddItemReferenceToObject(list,"commands",cmdList);
+	cJSON_AddItemToObject(list,"values",values);
+	cJSON_ArrayForEach(element,cmdList){
+		cJSON * name = cJSON_GetObjectItem(element,"name");
+		cJSON * vals_fn = cJSON_GetObjectItem(values_fn_list,cJSON_GetStringValue(name));
+		if(vals_fn!=NULL ){
+			parm_values_fn_t *parm_values_fn = (parm_values_fn_t *)strtoul(cJSON_GetStringValue(vals_fn), NULL, 16);;
+
+			if(parm_values_fn){
+				cJSON_AddItemToObject(values,cJSON_GetStringValue(name),parm_values_fn());
+			}
+		}
+	}
+	return list;
+}
+
+struct arg_end *getParmsEnd(struct arg_hdr * * argtable){
+	if(!argtable) return NULL;
+	struct arg_hdr * *table = (struct arg_hdr * *)argtable;
+	int tabindex = 0;
+	while (!(table[tabindex]->flag & ARG_TERMINATOR))
+	{
+		tabindex++;
+	}
+	return (struct arg_end *)table[tabindex];
 }
 cJSON * ParmsToJSON(struct arg_hdr * * argtable){
 	if(!argtable) return NULL;
@@ -78,11 +107,19 @@ cJSON * ParmsToJSON(struct arg_hdr * * argtable){
 	}
 	return arg_list;
 }
-esp_err_t cmd_to_json(const esp_console_cmd_t *cmd)
-{
+
+esp_err_t cmd_to_json(const esp_console_cmd_t *cmd){
+	return cmd_to_json_with_cb(cmd, NULL);
+}
+
+esp_err_t cmd_to_json_with_cb(const esp_console_cmd_t *cmd, parm_values_fn_t parm_values_fn){
 	if(!cmdList){
-		cmdList=cJSON_CreateObject();
+		cmdList=cJSON_CreateArray();
+	}
+	if(!values_fn_list){
+		values_fn_list=cJSON_CreateObject();
 	}
+
     if (cmd->command == NULL) {
         return ESP_ERR_INVALID_ARG;
     }
@@ -92,6 +129,13 @@ esp_err_t cmd_to_json(const esp_console_cmd_t *cmd)
     cJSON * jsoncmd = cJSON_CreateObject();
     ADD_TO_JSON(jsoncmd,cmd,help);
     ADD_TO_JSON(jsoncmd,cmd,hint);
+	if(parm_values_fn){
+		char addr[11]={0};
+		snprintf(addr,sizeof(addr),"%lx",(unsigned long)parm_values_fn);
+		cJSON_AddStringToObject(values_fn_list,cmd->command,addr);
+	}
+	cJSON_AddBoolToObject(jsoncmd,"hascb",parm_values_fn!=NULL);
+
     if(cmd->argtable){
     	cJSON_AddItemToObject(jsoncmd,"argtable",ParmsToJSON(cmd->argtable));
     }
@@ -105,19 +149,38 @@ esp_err_t cmd_to_json(const esp_console_cmd_t *cmd)
         FILE *f = open_memstream(&buf, &buf_size);
         if (f != NULL) {
             arg_print_syntax(f, cmd->argtable, NULL);
+            fflush(f);
             fclose(f);
         }
         cJSON_AddStringToObject(jsoncmd, "hint", buf);
-        free(buf);
+        FREE_AND_NULL(buf);
     }
+    cJSON_AddStringToObject(jsoncmd, "name", cmd->command);
     char * b=cJSON_Print(jsoncmd);
     if(b){
-    	ESP_LOGI(TAG,"Adding command table %s",b);
+    	ESP_LOGD(TAG,"Adding command table %s",b);
     	free(b);
     }
-    cJSON_AddItemToObject(cmdList, cmd->command,jsoncmd);
+    cJSON_AddItemToArray(cmdList, jsoncmd);
     return ESP_OK;
 }
+int arg_parse_msg(int argc, char **argv, struct arg_hdr ** args){
+    int nerrors = arg_parse(argc, argv, (void **)args);
+
+    if (nerrors != 0) {
+    	char *buf = NULL;
+		size_t buf_size = 0;
+		FILE *f = open_memstream(&buf, &buf_size);
+		if (f != NULL) {
+			arg_print_errors(f, getParmsEnd(args), argv[0]);
+			fflush (f);
+			log_send_messaging(MESSAGING_ERROR,"%s", buf);
+		}
+        fclose(f);
+        FREE_AND_NULL(buf);
+    }
+    return nerrors;
+}
 void process_autoexec(){
 	int i=1;
 	char autoexec_name[21]={0};

+ 4 - 0
components/platform_console/platform_console.h

@@ -8,11 +8,15 @@
 */
 #pragma once
 #include "esp_console.h"
+#include "argtable3/argtable3.h"
 #include "cJSON.h"
 #ifdef __cplusplus
 extern "C" {
 #endif
+typedef cJSON * parm_values_fn_t(void);
 esp_err_t cmd_to_json(const esp_console_cmd_t *cmd);
+esp_err_t cmd_to_json_with_cb(const esp_console_cmd_t *cmd, parm_values_fn_t parm_values_fn);
+int arg_parse_msg(int argc, char **argv, struct arg_hdr ** args);
 cJSON * get_cmd_list();
 #ifdef __cplusplus
 }

+ 1 - 1
components/services/CMakeLists.txt

@@ -1,6 +1,6 @@
 idf_component_register(SRC_DIRS .
 						INCLUDE_DIRS . 
-						REQUIRES json tools platform_config
+						REQUIRES json tools platform_config display
 
 )
 

+ 40 - 0
components/services/accessors.c

@@ -14,8 +14,11 @@
 #include "platform_config.h"
 #include "accessors.h"
 #include "globdefs.h"
+#include "display.h"
 
 static const char *TAG = "services";
+static char *i2c_name="I2C";
+static char *spi_name="SPI";
 
 #define min(a,b) (((a) < (b)) ? (a) : (b))
 
@@ -34,6 +37,43 @@ esp_err_t config_i2c_set(const i2c_config_t * config, int port){
 	return ESP_OK;
 }
 
+void config_display_free(display_config_t ** disp ){
+	if(disp && *disp){
+		free((*disp)->drivername);
+		free((*disp)->type);
+		free(*disp);
+		*disp=NULL;
+	}
+}
+
+const display_config_t * config_display_get(){
+	static display_config_t dstruct;
+	char *config = config_alloc_get(NVS_TYPE_STR, "display_config");
+	if (!config) {
+		return NULL;
+	}
+
+	char * p=NULL;
+
+	if ((p = strcasestr(config, "driver")) != NULL){
+		dstruct.drivername = display_conf_get_driver_name(strchr(p, '=') + 1);
+	}
+
+	dstruct.drivername=dstruct.drivername?dstruct.drivername:"SSD1306";
+	if ((p = strcasestr(config, "width")) != NULL) dstruct.width = atoi(strchr(p, '=') + 1);
+	if ((p = strcasestr(config, "height")) != NULL) dstruct.height = atoi(strchr(p, '=') + 1);
+	if ((p = strcasestr(config, "reset")) != NULL) dstruct.RST_pin = atoi(strchr(p, '=') + 1);
+	dstruct.i2c_system_port=i2c_system_port;
+	if (strstr(config, "I2C") ) dstruct.type=i2c_name;
+	if ((p = strcasestr(config, "address")) != NULL) dstruct.address = atoi(strchr(p, '=') + 1);
+	if (strstr(config, "SPI") ) dstruct.type=spi_name;
+	if ((p = strcasestr(config, "cs")) != NULL) dstruct.CS_pin = atoi(strchr(p, '=') + 1);
+	if ((p = strcasestr(config, "speed")) != NULL) dstruct.speed = atoi(strchr(p, '=') + 1);
+	dstruct.hflip= strcasestr(config, "HFlip") ? true : false;
+	dstruct.vflip= strcasestr(config, "VFlip") ? true : false;
+	return &dstruct;
+}
+
 /****************************************************************************************
  * 
  */

+ 14 - 1
components/services/accessors.h

@@ -11,7 +11,20 @@
 #include "esp_system.h"
 #include "driver/i2c.h"
 #include "driver/spi_master.h"
-
+typedef struct {
+	int width;
+	int height;
+	int RST_pin;
+	int i2c_system_port;
+	int address;
+	int CS_pin;
+	int speed;
+	char *drivername;
+	char *type;
+	bool hflip;
+	bool vflip;
+} display_config_t;
+const display_config_t * config_display_get();
 esp_err_t 					config_i2c_set(const i2c_config_t * config, int port);
 const i2c_config_t * 		config_i2c_get(int * i2c_port);
 const spi_bus_config_t * 	config_spi_get(spi_host_device_t * spi_host);

+ 17 - 0
components/services/messaging.c

@@ -245,3 +245,20 @@ void messaging_post_message(messaging_types type,messaging_classes msg_class, co
 	return;
 
 }
+void log_send_messaging(messaging_types msgtype,const char *fmt, ...) {
+	va_list va;
+	va_start(va, fmt);
+	size_t ln = vsnprintf(NULL, 0, fmt, va)+1;
+	char * message_txt = malloc(ln);
+	if(message_txt){
+		vsprintf(message_txt, fmt, va);
+		va_end(va);
+		ESP_LOG_LEVEL_LOCAL(messaging_type_to_err_type(msgtype),tag, "%s",message_txt);
+		messaging_post_message(msgtype, MESSAGING_CLASS_SYSTEM, message_txt );
+		free(message_txt);
+	}
+	else{
+		ESP_LOGE(tag, "Memory allocation failed while sending message");
+	}
+
+}

+ 2 - 1
components/services/messaging.h

@@ -29,10 +29,11 @@ esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_m
 void messaging_post_message(messaging_types type,messaging_classes msg_class, const char * fmt, ...);
 cJSON *  messaging_retrieve_messages(RingbufHandle_t buf_handle);
 single_message_t *  messaging_retrieve_message(RingbufHandle_t buf_handle);
+void log_send_messaging(messaging_types msgtype,const char *fmt, ...);
 esp_err_t messaging_type_to_err_type(messaging_types type);
 void messaging_service_init();
 
-
+#define REALLOC_CAT(e,n) e=realloc(e,strlen(n)); e=strcat(e,n)
 #define LOG_SEND(y, ...) \
 {  \
 ESP_LOG_LEVEL_LOCAL(messaging_type_to_err_type(y),TAG,   ##__VA_ARGS__); \

+ 124 - 1
components/wifi-manager/code.js

@@ -32,6 +32,20 @@ var task_state_t = {
 		 4 : "eDeleted"				
 
 }
+var escapeHTML = function(unsafe) {
+	  return unsafe.replace(/[&<"']/g, function(m) {
+	    switch (m) {
+	      case '&':
+	        return '&amp;';
+	      case '<':
+	        return '&lt;';
+	      case '"':
+	        return '&quot;';
+	      default:
+	        return '&#039;';
+	    }
+	  });
+	};
 var releaseURL = 'https://api.github.com/repos/sle118/squeezelite-esp32/releases';
 var recovery = false;
 var enableAPTimer = true;
@@ -737,7 +751,7 @@ function getMessages() {
                         $("#syslogTable").append(
                             "<tr class='"+msg["type"]+"'>"+
                                 "<td>"+msg_time.toLocaleString()+"</td>"+
-                                "<td>"+msg["message"]+"</td>"+
+                                "<td>"+escapeHTML(msg["message"]).replace(/\n/g, '<br />')+"</td>"+
                             "</tr>"
                         );
 	        			break;
@@ -921,15 +935,124 @@ function checkStatus(){
         blockAjax = false;
     });
 }
+function runCommand(button) {
+	pardiv = button.parentNode.parentNode;
+	fields=document.getElementById("flds-"+button.value);
+	cmdstring=button.value+' ';
+	if(fields){
+		hint = pardiv.hint;
+		allfields=fields.getElementsByTagName("input");
+		for (i = 0; i < allfields.length; i++) {
+			attr=allfields[i].attributes;
+			qts='';
+			opt='';
+			optspacer=' ';
+			
+			if (attr.longopts.value!== "undefined"){
+				opt+= '--' + attr.longopts.value;
+				optspacer='=';
+			}
+			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+optspacer+qts +allfields[i].value +qts+ ' ';
+				}
+			}
+			else {
+				// this is a checkbox
+				if(allfields[i].checked) cmdstring+=opt+ ' ';	
+			}
+		}
+	}
+	console.log(cmdstring);
+
+	var data = { 'timestamp': Date.now() };
+	data['command'] = cmdstring;
+	
+	$.ajax({
+		url: '/commands.json',
+		dataType: 'text',
+		method: 'POST',
+		cache: false,
+		contentType: 'application/json; charset=utf-8',
+		data:  JSON.stringify(data),
+		error: function (xhr, ajaxOptions, thrownError) {
+			console.log(xhr.status);
+			console.log(thrownError);
+			if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR');
+		}
+	});
+	enableStatusTimer = true;
+}
 
 
 function getCommands() {
     $.getJSON("/commands.json", function(data) {
         console.log(data);
+		innerhtml='';
+		
+		data.commands.forEach(function(command) {
+			innerhtml+='<tr><td>';
+			innerhtml+=escapeHTML(command.help).replace(/\n/g, '<br />')+'<br>';
+			innerhtml+='<div >';
+			if(command.hasOwnProperty("argtable")){
+			innerhtml+='<table class="table table-hover" id="flds-'+command.name+'"><tbody>';
+				command.argtable.forEach(function (arg){
+					innerhtml+="<tr>";
+					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] || '';
+					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>';
+					}
+					else {
+						innerhtml+='value="'+curvalue+'" ';
+						innerhtml+='></input></td>'+ curvalue.length>0?'<td>last: '+curvalue+'</td>':'';
+					}
+					
+					innerhtml+="</tr>";
+				});
+			innerhtml+='</tbody></table><br>';
+			
+			}
+			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);
+		
     })
     .fail(function(xhr, ajaxOptions, thrownError) {
         console.log(xhr.status);
         console.log(thrownError);
+        $("#commands-list").empty();
         if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR');
         blockAjax = false;
     });

+ 49 - 1
components/wifi-manager/http_server_handlers.c

@@ -80,7 +80,7 @@ union sockaddr_aligned {
     struct sockaddr_in  sin;
     struct sockaddr_in6 sin6;
 } aligned_sockaddr_t;
-
+esp_err_t post_handler_buff_receive(httpd_req_t * req);
 static const char redirect_payload1[]="<html><head><title>Redirecting to Captive Portal</title><meta http-equiv='refresh' content='0; url=";
 static const char redirect_payload2[]="'></head><body><p>Please wait, refreshing.  If page does not refresh, click <a href='";
 static const char redirect_payload3[]="'>here</a> to login.</p></body></html>";
@@ -483,6 +483,54 @@ esp_err_t console_cmd_get_handler(httpd_req_t *req){
 		ESP_LOGD_LOC(TAG,  "Error retrieving command json string. ");
 		httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Unable to format command");
 	}
+	cJSON_free(cmdlist);
+	ESP_LOGD_LOC(TAG, "done serving [%s]", req->uri);
+	return err;
+}
+esp_err_t console_cmd_post_handler(httpd_req_t *req){
+	char success[]="{}";
+	ESP_LOGD_LOC(TAG, "serving [%s]", req->uri);
+	bool bOTA=false;
+	char * otaURL=NULL;
+	esp_err_t err = post_handler_buff_receive(req);
+	if(err!=ESP_OK){
+		return err;
+	}
+	if(!is_user_authenticated(req)){
+		// todo:  redirect to login page
+		// return ESP_OK;
+	}
+	err = set_content_type_from_req(req);
+	if(err != ESP_OK){
+		return err;
+	}
+
+	char *command= ((rest_server_context_t *)(req->user_ctx))->scratch;
+
+	cJSON *root = cJSON_Parse(command);
+	if(root == NULL){
+		ESP_LOGE_LOC(TAG, "Parsing command. Received content was: %s",command);
+		httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Malformed command json.  Unable to parse content.");
+		return ESP_FAIL;
+	}
+	char * root_str = cJSON_Print(root);
+	if(root_str!=NULL){
+		ESP_LOGD(TAG, "Processing command item: \n%s", root_str);
+		free(root_str);
+	}
+	cJSON *item=cJSON_GetObjectItemCaseSensitive(root, "command");
+	if(!item){
+		ESP_LOGE_LOC(TAG, "Command not found. Received content was: %s",command);
+		httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Malformed command json.  Unable to parse content.");
+		err = ESP_FAIL;
+	}
+	else{
+		// navigate to the first child of the config structure
+		run_command(cJSON_GetStringValue(item));
+	}
+
+	httpd_resp_send(req, (const char *)success, strlen(success));
+
 	ESP_LOGD_LOC(TAG, "done serving [%s]", req->uri);
 	return err;
 }

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

@@ -92,6 +92,7 @@ esp_err_t flash_post_handler(httpd_req_t *req);
 esp_err_t status_get_handler(httpd_req_t *req);
 esp_err_t messages_get_handler(httpd_req_t *req);
 esp_err_t console_cmd_get_handler(httpd_req_t *req);
+esp_err_t console_cmd_post_handler(httpd_req_t *req);
 esp_err_t ap_scan_handler(httpd_req_t *req);
 esp_err_t redirect_ev_handler(httpd_req_t *req);
 esp_err_t redirect_200_ev_handler(httpd_req_t *req);

+ 9 - 0
components/wifi-manager/index.html

@@ -70,6 +70,9 @@
             <li class="nav-item">
                 <a class="nav-link" data-toggle="tab" href="#tab-syslog">Syslog</a>
             </li>
+            <li class="nav-item">
+                <a class="nav-link" data-toggle="tab" href="#tab-commands">System</a>
+            </li>			
             <li class="nav-item">
                 <a class="nav-link" data-toggle="tab" href="#tab-nvs">NVS editor</a>
             </li>
@@ -295,6 +298,12 @@
                         </div>
                     </div>
                 </div> <!-- firmware -->
+                <div class="tab-pane fade" id="tab-commands">
+                    <table class="table table-hover" id="commands-list-table">
+					<tbody id="commands-list">
+                    </tbody>
+                    </table>
+                </div> <!-- system -->
 
                 <div class="tab-pane fade" id="tab-syslog">
                     <table class="table table-hover">

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

@@ -60,6 +60,8 @@ void register_regular_handlers(httpd_handle_t server){
 
 	httpd_uri_t commands_get = { .uri = "/commands.json", .method = HTTP_GET, .handler = console_cmd_get_handler, .user_ctx = rest_context };
 	httpd_register_uri_handler(server, &commands_get);
+	httpd_uri_t commands_post = { .uri = "/commands.json", .method = HTTP_POST, .handler = console_cmd_post_handler, .user_ctx = rest_context };
+	httpd_register_uri_handler(server, &commands_post);
 
 	httpd_uri_t config_post = { .uri = "/config.json", .method = HTTP_POST, .handler = config_post_handler, .user_ctx = rest_context };
 	httpd_register_uri_handler(server, &config_post);

+ 9 - 9
main/esp_app_main.c

@@ -190,7 +190,7 @@ esp_err_t update_certificates(){
 		}
 		free(str);
 	}
-	else {
+	else if(str==NULL){
 		ESP_LOGW(TAG,"No certificate found. Adding certificates");
 		changed=true;
 	}
@@ -199,20 +199,20 @@ esp_err_t update_certificates(){
 
 		esp_err = nvs_set_blob(handle, certs_key, server_cert_pem_start, (server_cert_pem_end-server_cert_pem_start));
 		if(esp_err!=ESP_OK){
-			LOG_SEND_ERROR("Failed to store certificate data: %s", esp_err_to_name(esp_err));
+			log_send_messaging(MESSAGING_ERROR,"Failed to store certificate data: %s", esp_err_to_name(esp_err));
 		}
 		else {
 			esp_err = nvs_set_str(handle,  certs_version, running_app_info.version);
 			if(esp_err!=ESP_OK){
-				LOG_SEND_ERROR("Unable to update HTTPS Certificates version: %s",esp_err_to_name(esp_err));
+				log_send_messaging(MESSAGING_ERROR,"Unable to update HTTPS Certificates version: %s",esp_err_to_name(esp_err));
 			}
 			else {
 				esp_err = nvs_commit(handle);
 				if(esp_err!=ESP_OK){
-					LOG_SEND_ERROR("Failed to commit certificates changes : %s",esp_err_to_name(esp_err));
+					log_send_messaging(MESSAGING_ERROR,"Failed to commit certificates changes : %s",esp_err_to_name(esp_err));
 				}
 				else {
-					LOG_SEND_INFO("HTTPS Certificates were updated with version: %s",running_app_info.version);
+					log_send_messaging(MESSAGING_INFO,"HTTPS Certificates were updated with version: %s",running_app_info.version);
 				}
 			}
 		}
@@ -234,7 +234,7 @@ const char * get_certificate(){
         if( esp_err == ESP_OK) {
             blob = (char *) heap_caps_malloc(len+1, (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT));
             if(!blob){
-            	LOG_SEND_ERROR("Unable to retrieve HTTPS certificates. %s","Memory allocation failed");
+            	log_send_messaging(MESSAGING_ERROR,"Unable to retrieve HTTPS certificates. %s","Memory allocation failed");
         		return "";
             }
             memset(blob,0x00,len+1);
@@ -243,16 +243,16 @@ const char * get_certificate(){
             	ESP_LOGD(TAG,"Certificates content is %d bytes long: ", len);
             }
             else {
-            	LOG_SEND_ERROR("Unable to retrieve HTTPS certificates. Get blob failed: %s", esp_err_to_name(esp_err));
+            	log_send_messaging(MESSAGING_ERROR,"Unable to retrieve HTTPS certificates. Get blob failed: %s", esp_err_to_name(esp_err));
             }
         }
         else{
-        	LOG_SEND_ERROR("Unable to retrieve HTTPS certificates. Get blob failed: %s",esp_err_to_name(esp_err));
+        	log_send_messaging(MESSAGING_ERROR,"Unable to retrieve HTTPS certificates. Get blob failed: %s",esp_err_to_name(esp_err));
         }
         nvs_close(handle);
 	}
 	else{
-    	LOG_SEND_ERROR("Unable to retrieve HTTPS certificates. NVS name space %s open failed: %s",certs_namespace, esp_err_to_name(esp_err));
+    	log_send_messaging(MESSAGING_ERROR,"Unable to retrieve HTTPS certificates. NVS name space %s open failed: %s",certs_namespace, esp_err_to_name(esp_err));
 	}
 	return blob;
 }

+ 2 - 2
sdkconfig.defaults

@@ -356,9 +356,9 @@ CONFIG_BT_RESERVE_DRAM=0xdb5c
 CONFIG_ADC_DISABLE_DAC=y
 
 CONFIG_SPI_MASTER_ISR_IN_IRAM=y
-
 CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
-
+CONFIG_SPI_MASTER_IN_IRAM=y
+CONFIG_SPI_SLAVE_IN_IRAM=y
 
 
 CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4=y

+ 1 - 0
version.txt

@@ -0,0 +1 @@
+custom.build