Bläddra i källkod

cpp state machine for ethernet

Sebastien L 3 år sedan
förälder
incheckning
81756a7649
43 ändrade filer med 4065 tillägg och 2552 borttagningar
  1. 95 2
      CMakeLists.txt
  2. 1 0
      components/cpp-stateless
  3. 3 3
      components/platform_console/cmd_wifi.c
  4. 6 5
      components/platform_console/platform_console.c
  5. 1 2
      components/raop/raop_sink.c
  6. 1 1
      components/raop/util.c
  7. 81 28
      components/services/accessors.c
  8. 4 1
      components/services/accessors.h
  9. 1 1
      components/services/buttons.c
  10. 33 32
      components/services/i2s.c.0
  11. 10 1
      components/services/messaging.c
  12. 7 0
      components/services/messaging.h
  13. 1 1
      components/squeezelite-ota/protocol_examples_common.h
  14. 1 2
      components/squeezelite-ota/squeezelite-ota.c
  15. 0 2
      components/telnet/telnet.c
  16. 4 1
      components/tools/trace.h
  17. 1 1
      components/wifi-manager/CMakeLists.txt
  18. 117 63
      components/wifi-manager/Kconfig.projbuild
  19. 1 1
      components/wifi-manager/dns_server.c
  20. 11 9
      components/wifi-manager/http_server_handlers.c
  21. 1 1
      components/wifi-manager/http_server_handlers.h
  22. 38 0
      components/wifi-manager/network_driver_DM9051.c
  23. 47 0
      components/wifi-manager/network_driver_LAN8720.c
  24. 43 0
      components/wifi-manager/network_driver_W5500.c
  25. 283 0
      components/wifi-manager/network_ethernet.c
  26. 30 0
      components/wifi-manager/network_ethernet.h
  27. 120 0
      components/wifi-manager/network_manager.c
  28. 59 116
      components/wifi-manager/network_manager.h
  29. 381 0
      components/wifi-manager/network_status.c
  30. 59 0
      components/wifi-manager/network_status.h
  31. 990 0
      components/wifi-manager/network_wifi.c
  32. 61 0
      components/wifi-manager/network_wifi.h
  33. 793 0
      components/wifi-manager/state_machine.cpp
  34. 108 0
      components/wifi-manager/state_machine.h
  35. 0 1803
      components/wifi-manager/wifi_manager.c
  36. BIN
      file-size.txt
  37. BIN
      file_size.txt
  38. 17 67
      main/Kconfig.projbuild
  39. 80 155
      main/esp_app_main.c
  40. 567 241
      sdkconfig
  41. 3 3
      sdkconfig.defaults
  42. 5 9
      squeezelite.cmake
  43. 1 1
      test/main/unit_tests.c

+ 95 - 2
CMakeLists.txt

@@ -10,5 +10,98 @@ project(recovery)
 set_property(TARGET recovery.elf PROPERTY RECOVERY_PREFIX app_recovery )
 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_DEBUG)
+
+#target_compile_definitions(__idf_wifi-manager PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO)
+target_compile_definitions(__idf_esp_wifi PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO)
+
+target_compile_definitions(__idf_app_recovery PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO)
+# target_compile_definitions(__idf_esp_eth PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO)
+# target_compile_definitions(__idf_esp_event PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO)
+# target_compile_definitions(__idf_esp_netif PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+
+# target_compile_definitions(__idf_freertos PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_bt PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_mdns PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_tcpip_adapter PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_tcp_transport PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+
+#target_compile_definitions(__idf_app_squeezelite PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_app_trace PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_app_update PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_asio PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_audio PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_bootloader_support PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+
+# target_compile_definitions(__idf_cbor PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_cmock PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_coap PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_console PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_cxx PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_display PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_driver PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_driver_bt PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_efuse PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp-dsp PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp-tls PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp32 PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_espcoredump PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_adc_cal PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_common PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_gdbstub PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_hid PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_https_ota PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_http_client PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_http_server PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_hw_support PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_ipc PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_local_ctrl PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_pm PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_ringbuf PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_rom PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_serial_slave_link PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_system PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_timer PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_esp_websocket_client PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_expat PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_fatfs PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_freemodbus PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_hal PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_heap PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_jsmn PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_json PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_libsodium PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_log PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_lwip PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_main PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_mbedtls PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(mbedcrypto PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(mbedtls PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(mbedx509 PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_mqtt PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_newlib PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_nghttp PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_nvs_flash PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_openssl PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_perfmon PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_platform_config PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_platform_console PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_protobuf-c PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_protocomm PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_pthread PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_raop PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_sdmmc PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_services PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_soc PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_spiffs PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_spi_flash PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_squeezelite PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_squeezelite-ota PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_telnet PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_tools PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_ulp PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_unity PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_vfs PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_wear_levelling PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_wifi_provisioning PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_wpa_supplicant PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
+# target_compile_definitions(__idf_xtensa PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)

+ 1 - 0
components/cpp-stateless

@@ -0,0 +1 @@
+Subproject commit 9e7138f8fe164d64deb73b2b23994eeb9abe3e0b

+ 3 - 3
components/platform_console/cmd_wifi.c

@@ -8,7 +8,7 @@
 */
 
 // cmd_wifi has been replaced by wifi-manager
-/* Console example  WiFi commands
+/* Console example � WiFi commands
 
    This example code is in the Public Domain (or CC0 licensed, at your option.)
 
@@ -29,7 +29,7 @@
 #include "freertos/FreeRTOS.h"
 #include "freertos/event_groups.h"
 #include "esp_wifi.h"
-#include "tcpip_adapter.h"
+#include "esp_netif.h"
 #include "esp_event.h"
 #include "led.h"
 extern bool bypass_wifi_manager;
@@ -98,7 +98,7 @@ static void initialise_wifi(void)
     if (initialized) {
         return;
     }
-    tcpip_adapter_init();
+    esp_netif_init();
     // Now moved to esp_app_main: wifi_event_group = xEventGroupCreate();
     ESP_ERROR_CHECK(esp_event_loop_create_default());
     wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();

+ 6 - 5
components/platform_console/platform_console.c

@@ -236,16 +236,17 @@ void initialize_console() {
 	/* Disable buffering on stdin */
 	setvbuf(stdin, NULL, _IONBF, 0);
 
-	/* Minicom, screen, idf_monitor send CR when ENTER key is pressed */
-	esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR);
-	/* Move the caret to the beginning of the next line on '\n' */
-	esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
+/* Minicom, screen, idf_monitor send CR when ENTER key is pressed */
+    esp_vfs_dev_uart_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR);
+    /* Move the caret to the beginning of the next line on '\n' */
+    esp_vfs_dev_uart_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF);
+
 
 	/* Configure UART. Note that REF_TICK is used so that the baud rate remains
 	 * correct while APB frequency is changing in light sleep mode.
 	 */
 	const uart_config_t uart_config = { .baud_rate =
-			CONFIG_CONSOLE_UART_BAUDRATE, .data_bits = UART_DATA_8_BITS,
+			CONFIG_ESP_CONSOLE_UART_BAUDRATE, .data_bits = UART_DATA_8_BITS,
 			.parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1,
 			.use_ref_tick = true };
 	ESP_ERROR_CHECK(uart_param_config(CONFIG_ESP_CONSOLE_UART_NUM, &uart_config));

+ 1 - 2
components/raop/raop_sink.c

@@ -5,8 +5,7 @@
 
 #include "mdns.h"
 #include "nvs.h"
-#include "tcpip_adapter.h"
-// IDF-V4++ #include "esp_netif.h"
+#include "esp_netif.h"
 #include "esp_log.h"
 #include "esp_console.h"
 #include "esp_pthread.h"

+ 1 - 1
components/raop/util.c

@@ -13,7 +13,7 @@
 #ifdef WIN32
 #include <iphlpapi.h>
 #else
-#include "tcpip_adapter.h"
+#include "esp_netif.h"
 // IDF-V4++ #include "esp_netif.h"
 #include <ctype.h>
 #endif

+ 81 - 28
components/services/accessors.c

@@ -15,7 +15,6 @@
 #include "accessors.h"
 #include "globdefs.h"
 #include "display.h"
-#include "display.h"
 #include "cJSON.h"
 #include "driver/gpio.h"
 #include "stdbool.h"
@@ -118,13 +117,8 @@ static void set_i2s_pin(char *config, i2s_pin_config_t *pin_config) {
  * Get i2s config structure from config string
  */
 const i2s_platform_config_t * config_get_i2s_from_str(char * dac_config ){
-	static EXT_RAM_ATTR i2s_platform_config_t i2s_dac_pin = {
-		.i2c_addr = -1,
-		.sda= -1,
-		.scl = -1,
-		.mute_gpio = -1,
-		.mute_level = -1
-	};
+	static EXT_RAM_ATTR i2s_platform_config_t i2s_dac_pin;
+	memset(&i2s_dac_pin, 0xFF, sizeof(i2s_dac_pin));
 	set_i2s_pin(dac_config, &i2s_dac_pin.pin);
 	strcpy(i2s_dac_pin.model, "i2s");
 	char * p=NULL;
@@ -146,11 +140,12 @@ const i2s_platform_config_t * config_get_i2s_from_str(char * dac_config ){
  * Get eth config structure from config string
  */
 const eth_config_t * config_get_eth_from_str(char * eth_config ){
-	static EXT_RAM_ATTR eth_config_t eth_pin = {
-		.rmii = false,
-		.model = "",
-	};
 	char * p=NULL;
+	static EXT_RAM_ATTR eth_config_t eth_pin; 
+	memset(&eth_pin, 0xFF, sizeof(eth_pin));
+	memset(&eth_pin.model, 0xFF, sizeof(eth_pin.model));
+	eth_pin.spi = false;		
+	eth_pin.rmii = false;
 
 	if ((p = strcasestr(eth_config, "model")) != NULL) sscanf(p, "%*[^=]=%15[^,]", eth_pin.model);
 	if ((p = strcasestr(eth_config, "mdc")) != NULL) eth_pin.mdc = atoi(strchr(p, '=') + 1);
@@ -163,9 +158,16 @@ const eth_config_t * config_get_eth_from_str(char * eth_config ){
 	if ((p = strcasestr(eth_config, "speed")) != NULL) eth_pin.speed = atoi(strchr(p, '=') + 1);
 	if ((p = strcasestr(eth_config, "clk")) != NULL) eth_pin.clk = atoi(strchr(p, '=') + 1);
 	if ((p = strcasestr(eth_config, "host")) != NULL) eth_pin.host = atoi(strchr(p, '=') + 1);
+	eth_pin.valid = eth_pin.model && strlen(eth_pin.model)>0 && GPIO_IS_VALID_GPIO(eth_pin.mdio) && GPIO_IS_VALID_GPIO(eth_pin.mdc);
 	
-	if (strcasestr(eth_pin.model, "lan8720")) eth_pin.rmii = true;
-	
+	if(strcasestr(eth_pin.model, "LAN8720")){
+		eth_pin.rmii = true;
+	}
+	else {
+		eth_pin.spi = true;
+		/* here we must also check that we have at least a CS gpio */
+		eth_pin.valid = eth_pin.valid && GPIO_IS_VALID_GPIO(eth_pin.cs);
+	}
 	return &eth_pin;
 }
 
@@ -196,22 +198,37 @@ const i2s_platform_config_t * config_dac_get(){
  */
 const eth_config_t * config_eth_get( ){
 	char * config = config_alloc_get_str("eth_config", CONFIG_ETH_CONFIG, "rst=" STR(CONFIG_ETH_PHY_RST_IO) 
-#if defined(CONFIG_ETH_LAN8720)	
-										 ",model=lan8720"
-#elif defined(CONFIG_ETH_DM9051)									
+	#if defined(ETH_LAN8720)
+	#else 
+#if defined(CONFIG_ETH_USE_SPI_ETHERNET)
+#if defined(CONFIG_ETH_DM9051)
 										 ",model=dm9051"
-#endif										 
-										 ",mdc=" STR(CONFIG_ETH_MDC_IO) ",mdio=" STR(CONFIG_ETH_MDIO_IO) 
+#elif defined(CONFIG_ETH_W5500)
+										 ",model=w5500"
+#endif
 										 ",host=" STR(CONFIG_ETH_SPI_HOST) ",cs=" STR(CONFIG_ETH_SPI_CS_IO)
 										 ",mosi=" STR(CONFIG_ETH_SPI_MOSI_IO) ",miso=" STR(CONFIG_ETH_SPI_MISO_IO) 
 										 ",intr=" STR(CONFIG_ETH_SPI_INTR_IO)
-										 ",clk=" STR(CONFIG_ETH_SPI_CLK_IO) ",speed=" STR(CONFIG_ETH_SPI_SPEED) );
+										 ",clk=" STR(CONFIG_ETH_SPI_CLK_IO) ",speed=" STR(CONFIG_ETH_SPI_SPEED) 
+
+#elif defined(CONFIG_ETH_PHY_INTERFACE_RMII)
+										 ",model=lan8720, tx_en=21, tx0=19, tx1=22, rx0=25, rx1=26, crs_dv=27"
+#endif
+#endif
+										",mdc=" STR(CONFIG_ETH_MDC_IO) ",mdio=" STR(CONFIG_ETH_MDIO_IO)) ;
 	static EXT_RAM_ATTR eth_config_t eth_config;
 	ESP_LOGD(TAG, "Ethernet config string %s", config);	
 	memcpy(&eth_config, config_get_eth_from_str(config), sizeof(eth_config));
 	free(config);
 	return &eth_config;
 }
+/****************************************************************************************
+ * Get ethernet config structure and assign to eth config structure
+ */
+void config_eth_init( eth_config_t *  target ){
+	const eth_config_t * source =  config_eth_get();
+	memcpy(target,source,sizeof(eth_config_t));
+}
 
 /****************************************************************************************
  * 
@@ -561,14 +578,9 @@ const set_GPIO_struct_t * get_gpio_struct(){
  */
 const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host) {
 	char *nvs_item, *p;
-	static EXT_RAM_ATTR spi_bus_config_t spi = {
-		.mosi_io_num = -1,
-        .sclk_io_num = -1,
-        .miso_io_num = -1,
-        .quadwp_io_num = -1,
-        .quadhd_io_num = -1
-    };
-
+	static EXT_RAM_ATTR spi_bus_config_t spi;
+	memset(&spi, 0xFF, sizeof(spi));
+	
 	nvs_item = config_alloc_get_str("spi_config", CONFIG_SPI_CONFIG, NULL);
 	if (nvs_item) {
 		if ((p = strcasestr(nvs_item, "data")) != NULL) spi.mosi_io_num = atoi(strchr(p, '=') + 1);
@@ -770,6 +782,46 @@ cJSON * get_SPI_GPIO(cJSON * list){
 	return llist;
 }
 
+/****************************************************************************************
+ *
+ */
+cJSON * get_eth_GPIO(cJSON * list){
+	cJSON * llist = list;
+	if(!llist){
+		llist = cJSON_CreateArray();
+	}	
+	spi_host_device_t spi_host;
+	const eth_config_t * eth_config = config_eth_get(&spi_host);
+	#if defined(CONFIG_ETH_CONFIG)
+		bool fixed = strlen(CONFIG_ETH_CONFIG)>0;
+	#else
+		bool fixed =false;
+	#endif 
+	if(eth_config->valid ){
+		add_gpio_for_value(llist,"mdc",eth_config->mdc,"ethernet",fixed);
+		add_gpio_for_value(llist,"rst",eth_config->rst,"ethernet",fixed);
+		add_gpio_for_value(llist,"mdio",eth_config->mdio,"ethernet",fixed);
+		if(eth_config->rmii){
+			add_gpio_for_value(llist,"tx_en", 21,"ethernet",true);
+			add_gpio_for_value(llist,"tx0",   19 ,"ethernet",true);
+			add_gpio_for_value(llist,"tx1",   22 ,"ethernet",true);
+			add_gpio_for_value(llist,"rx0",   25 ,"ethernet",true);
+			add_gpio_for_value(llist,"rx1",   26 ,"ethernet",true);
+			add_gpio_for_value(llist,"crs_dv",27 ,"ethernet",true);
+		}
+		else if(eth_config->spi) {
+			/* SPI ethernet */
+			add_gpio_for_value(llist,"cs",eth_config->cs,"ethernet",fixed);
+			add_gpio_for_value(llist,"mosi",eth_config->mosi,"ethernet",fixed);
+			add_gpio_for_value(llist,"miso",eth_config->miso,"ethernet",fixed);
+			add_gpio_for_value(llist,"intr",eth_config->intr,"ethernet",fixed);
+			add_gpio_for_value(llist,"clk",eth_config->clk,"ethernet",fixed);
+		}
+	}
+	return llist;
+}
+
+
 /****************************************************************************************
  *
  */
@@ -1013,5 +1065,6 @@ cJSON * get_gpio_list(bool refresh) {
 	gpio_list=get_I2C_GPIO(gpio_list);
 	gpio_list=get_DAC_GPIO(gpio_list);
 	gpio_list=get_psram_gpio_list(gpio_list);
+	gpio_list=get_eth_GPIO(gpio_list);
 	return gpio_list;
 }

+ 4 - 1
components/services/accessors.h

@@ -31,8 +31,10 @@ typedef struct {
 } display_config_t;
 
 typedef struct {
-	bool rmii;
 	char model[16];
+	bool valid;
+	bool rmii;
+	bool spi;
 	int rst;
 	int mdc, mdio;
 	int host;
@@ -86,6 +88,7 @@ typedef struct {
 
 const display_config_t * 	config_display_get();
 const eth_config_t * 		config_eth_get( );
+void 						config_eth_init( eth_config_t *  target );
 esp_err_t 					config_display_set(const display_config_t * config);
 esp_err_t 					config_i2c_set(const i2c_config_t * config, int port);
 esp_err_t 					config_i2s_set(const i2s_platform_config_t * config, const char * nvs_name);

+ 1 - 1
components/services/buttons.c

@@ -47,7 +47,7 @@ static EXT_RAM_ATTR struct button_s {
 	TimerHandle_t timer;
 } buttons[MAX_BUTTONS];
 
-static EXT_RAM_ATTR struct {
+static struct {
 	int gpio, level;
 	struct button_s *button;
 } polled_gpio[] = { {36, -1, NULL}, {39, -1, NULL}, {-1, -1, NULL} };

+ 33 - 32
components/services/i2s.c → components/services/i2s.c.0

@@ -28,7 +28,7 @@
 #include "driver/i2s.h"
 #include "driver/rtc_io.h"
 #include "driver/dac.h"
-#include <adc1_i2s_private.h>
+#include "adc1_private.h"
 
 #include "esp_intr_alloc.h"
 #include "esp_err.h"
@@ -880,7 +880,7 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co
         //initialize the specific ADC channel.
         //in the current stage, we only support ADC1 and single channel mode.
         //In default data mode, the ADC data is in 12-bit resolution mode.
-        adc_power_always_on();
+        // todo: fix this - adc_power_always_on();
     }
     // configure I2S data port interface.
     i2s_reset_fifo(i2s_num);
@@ -974,35 +974,36 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co
         I2S[i2s_num]->pdm_conf.rx_pdm_en = 0;
         I2S[i2s_num]->pdm_conf.tx_pdm_en = 0;
     }
-    if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S) {
-        I2S[i2s_num]->conf.tx_short_sync = 0;
-        I2S[i2s_num]->conf.rx_short_sync = 0;
-        I2S[i2s_num]->conf.tx_msb_shift = 1;
-        I2S[i2s_num]->conf.rx_msb_shift = 1;
-        if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S_LSB) {
-            if (i2s_config->mode & I2S_MODE_TX) {
-                I2S[i2s_num]->conf.tx_msb_shift = 0;
-            }
-            if (i2s_config->mode & I2S_MODE_RX) {
-                I2S[i2s_num]->conf.rx_msb_shift = 0;
-            }
-        }
-    }
-
-    if (i2s_config->communication_format & I2S_COMM_FORMAT_PCM) {
-        I2S[i2s_num]->conf.tx_msb_shift = 0;
-        I2S[i2s_num]->conf.rx_msb_shift = 0;
-        I2S[i2s_num]->conf.tx_short_sync = 0;
-        I2S[i2s_num]->conf.rx_short_sync = 0;
-        if (i2s_config->communication_format & I2S_COMM_FORMAT_PCM_SHORT) {
-            if (i2s_config->mode & I2S_MODE_TX) {
-                I2S[i2s_num]->conf.tx_short_sync = 1;
-            }
-            if (i2s_config->mode & I2S_MODE_RX) {
-                I2S[i2s_num]->conf.rx_short_sync = 1;
-            }
-        }
-    }
+    // todo: fix this below!!
+    // if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S) {
+    //     I2S[i2s_num]->conf.tx_short_sync = 0;
+    //     I2S[i2s_num]->conf.rx_short_sync = 0;
+    //     I2S[i2s_num]->conf.tx_msb_shift = 1;
+    //     I2S[i2s_num]->conf.rx_msb_shift = 1;
+    //     if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S_LSB) {
+    //         if (i2s_config->mode & I2S_MODE_TX) {
+    //             I2S[i2s_num]->conf.tx_msb_shift = 0;
+    //         }
+    //         if (i2s_config->mode & I2S_MODE_RX) {
+    //             I2S[i2s_num]->conf.rx_msb_shift = 0;
+    //         }
+    //     }
+    // }
+
+    // if (i2s_config->communication_format & I2S_COMM_FORMAT_PCM) {
+    //     I2S[i2s_num]->conf.tx_msb_shift = 0;
+    //     I2S[i2s_num]->conf.rx_msb_shift = 0;
+    //     I2S[i2s_num]->conf.tx_short_sync = 0;
+    //     I2S[i2s_num]->conf.rx_short_sync = 0;
+    //     if (i2s_config->communication_format & I2S_COMM_FORMAT_PCM_SHORT) {
+    //         if (i2s_config->mode & I2S_MODE_TX) {
+    //             I2S[i2s_num]->conf.tx_short_sync = 1;
+    //         }
+    //         if (i2s_config->mode & I2S_MODE_RX) {
+    //             I2S[i2s_num]->conf.rx_short_sync = 1;
+    //         }
+    //     }
+    // }
     if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) &&  (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX)) {
         I2S[i2s_num]->conf.sig_loopback = 1;
         if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) {
@@ -1217,7 +1218,7 @@ esp_err_t i2s_adc_enable(i2s_port_t i2s_num)
     I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE);
     I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE);
 
-    adc1_i2s_mode_acquire();
+    // todo: fix this adc1_i2s_mode_acquire();
     _i2s_adc_mode_recover();
     return i2s_set_clk(i2s_num, p_i2s_obj[i2s_num]->sample_rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num);
 }

+ 10 - 1
components/services/messaging.c

@@ -238,7 +238,16 @@ void messaging_post_message(messaging_types type,messaging_classes msg_class, co
 	message->type = type;
 	message->msg_class = msg_class;
 	message->sent_time = esp_timer_get_time() / 1000;
-	ESP_LOGD(tag,"Post: %s",message->message);
+	if(type==MESSAGING_WARNING) {
+		ESP_LOGW(tag,"%s",message->message);	
+	}
+	else if(type==MESSAGING_ERROR) {
+		ESP_LOGE(tag,"%s",message->message);	
+	}
+	else {
+		ESP_LOGD(tag,"Post: %s",message->message);
+	}
+
 	while(cur){
 		messaging_post_to_queue(get_handle_ptr(cur),  message, msg_size);
 		cur = get_struct_ptr(cur->next);

+ 7 - 0
components/services/messaging.h

@@ -3,6 +3,10 @@
 #include "freertos/ringbuf.h"
 #include "cJSON.h"
 #pragma once
+#ifdef __cplusplus
+extern "C" {
+
+#endif
 typedef enum {
 	MESSAGING_INFO,
 	MESSAGING_WARNING,
@@ -48,3 +52,6 @@ messaging_post_message(y, MESSAGING_CLASS_SYSTEM,  ##__VA_ARGS__); }
 #define LOG_SEND_WARN( ...) LOG_SEND(MESSAGING_WARNING,##__VA_ARGS__)
 
 
+#ifdef __cplusplus
+} 
+#endif

+ 1 - 1
components/squeezelite-ota/protocol_examples_common.h

@@ -14,7 +14,7 @@ extern "C" {
 #endif
 
 #include "esp_err.h"
-#include "tcpip_adapter.h"
+#include "esp_netif.h"
 // IDF-V4++ #include "esp_netif.h"
 
 #ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET

+ 1 - 2
components/squeezelite-ota/squeezelite-ota.c

@@ -20,8 +20,7 @@
 #include "cmd_system.h"
 #include "esp_err.h"
 #include "squeezelite-ota.h"
-#include "tcpip_adapter.h"
-// IDF-V4++ #include "esp_netif.h"
+#include "esp_netif.h"
 #include "platform_config.h"
 #include <time.h>
 #include <sys/time.h>

+ 0 - 2
components/telnet/telnet.c

@@ -117,9 +117,7 @@ void init_telnet(){
 	uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(sizeof(uint8_t)*log_buf_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT );
 	buf_handle = xRingbufferCreateStatic(log_buf_size, RINGBUF_TYPE_BYTEBUF, buffer_storage, buffer_struct);
 	if (buf_handle == NULL) {
-		ESP_LOGE(TAG,"Failed to create ring buffer for telnet!");
 		messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Failed to allocate memory for telnet buffer");
-
 		return;
 	}
 

+ 4 - 1
components/tools/trace.h

@@ -21,7 +21,10 @@
 #ifndef STR_OR_ALT
 #define STR_OR_ALT(str,alt) (str?str:alt)
 #endif
-
+#define ENUM_TO_STRING(g) \
+    case g:     \
+        return STR(g);    \
+        break;
 extern const char unknown_string_placeholder[];
 extern const char * str_or_unknown(const char * str);
 extern const char * str_or_null(const char * str);

+ 1 - 1
components/wifi-manager/CMakeLists.txt

@@ -3,7 +3,7 @@ set( WEBPACK_DIR webapp/webpack/dist )
 idf_component_register( SRC_DIRS . webapp
 						INCLUDE_DIRS . webapp ${IDF_PATH}/components/esp_http_server/src ${IDF_PATH}/components/esp_http_server/src/port/esp32  ${IDF_PATH}/components/esp_http_server/src/util ${IDF_PATH}/components/esp_http_server/src/
 						REQUIRES squeezelite-ota json mdns 
-						PRIV_REQUIRES tools services platform_config esp_common json newlib freertos  spi_flash nvs_flash mdns pthread wpa_supplicant platform_console esp_http_server console driver_bt
+						PRIV_REQUIRES tools cpp-stateless services platform_config esp_common json newlib freertos  spi_flash nvs_flash mdns pthread wpa_supplicant platform_console esp_http_server console driver_bt
 )
 
  

+ 117 - 63
components/wifi-manager/Kconfig.projbuild

@@ -1,67 +1,121 @@
-menu "Wifi Manager Configuration"
+menu "Network Manager Configuration"
+    
+    menu "WiFi Options"
+        config WIFI_MANAGER_TASK_PRIORITY
+            int "RTOS Task Priority for the wifi_manager"
+            default 1
+            help
+            Tasks spawn by the manager will have a priority of WIFI_MANAGER_TASK_PRIORITY-1. For this particular reason, minimum recommended task priority is 2.
 
-config WIFI_MANAGER_TASK_PRIORITY
-    int "RTOS Task Priority for the wifi_manager"
-    default 1
-    help
-	Tasks spawn by the manager will have a priority of WIFI_MANAGER_TASK_PRIORITY-1. For this particular reason, minimum recommended task priority is 2.
+        config WIFI_MANAGER_MAX_RETRY
+            int "Max Retry on failed connection"
+            default 2
+            help
+            Defines when a connection is lost/attempt to connect is made, how many retries should be made before giving up.
+            
+        config DEFAULT_AP_SSID
+            string "Access Point SSID"
+            default "esp32"
+            help
+            SSID (network name) the the esp32 will broadcast.
 
-config WIFI_MANAGER_MAX_RETRY
-	int "Max Retry on failed connection"
-    default 2
-    help
-	Defines when a connection is lost/attempt to connect is made, how many retries should be made before giving up.
-	
-config DEFAULT_AP_SSID
-    string "Access Point SSID"
-    default "esp32"
-    help
-	SSID (network name) the the esp32 will broadcast.
+        config DEFAULT_AP_PASSWORD
+            string "Access Point Password"
+            default "esp32pwd"
+            help
+            Password used for the Access Point. Leave empty and set AUTH MODE to WIFI_AUTH_OPEN for no password.
 
-config DEFAULT_AP_PASSWORD
-    string "Access Point Password"
-    default "esp32pwd"
-    help
-	Password used for the Access Point. Leave empty and set AUTH MODE to WIFI_AUTH_OPEN for no password.
-
-config DEFAULT_AP_CHANNEL
-    int "Access Point WiFi Channel"
-    default 1
-    help
-	Be careful you might not see the access point if you use a channel not allowed in your country.
-	
-config DEFAULT_AP_IP
-    string "Access Point IP Address"
-    default "10.10.0.1"
-    help
-	This is used for the redirection to the captive portal. It is recommended to leave unchanged.
-	
-config DEFAULT_AP_GATEWAY
-    string "Access Point IP Gateway"
-    default "10.10.0.1"
-    help
-	This is used for the redirection to the captive portal. It is recommended to leave unchanged.
-	
-config DEFAULT_AP_NETMASK
-    string "Access Point Netmask"
-    default "255.255.255.0"
-    help
-	This is used for the redirection to the captive portal. It is recommended to leave unchanged.
-	
-config DEFAULT_AP_MAX_CONNECTIONS
-    int "Access Point Max Connections"
-    default 4
-    help
-	Max is 4.
-	
-config DEFAULT_AP_BEACON_INTERVAL
-    int "Access Point Beacon Interval (ms)"
-    default 100
-    help
-	100ms is the recommended default.
-config DEFAULT_COMMAND_LINE
-    string "Default command line to execute"
-    default "squeezelite -o I2S -b 500:2000 -d all=info -C 30"
-    help
-	This is the command to run when starting the device
+        config DEFAULT_AP_CHANNEL
+            int "Access Point WiFi Channel"
+            default 1
+            help
+            Be careful you might not see the access point if you use a channel not allowed in your country.
+            
+        config DEFAULT_AP_IP
+            string "Access Point IP Address"
+            default "10.10.0.1"
+            help
+            This is used for the redirection to the captive portal. It is recommended to leave unchanged.
+            
+        config DEFAULT_AP_GATEWAY
+            string "Access Point IP Gateway"
+            default "10.10.0.1"
+            help
+            This is used for the redirection to the captive portal. It is recommended to leave unchanged.
+            
+        config DEFAULT_AP_NETMASK
+            string "Access Point Netmask"
+            default "255.255.255.0"
+            help
+            This is used for the redirection to the captive portal. It is recommended to leave unchanged.
+            
+        config DEFAULT_AP_MAX_CONNECTIONS
+            int "Access Point Max Connections"
+            default 4
+            help
+            Max is 4.
+            
+        config DEFAULT_AP_BEACON_INTERVAL
+            int "Access Point Beacon Interval (ms)"
+            default 100
+            help
+            100ms is the recommended default.
+    endmenu
+    menu "Ethernet Options"
+		visible if BASIC_I2C_BT && (ETH_USE_ESP32_EMAC || ETH_USE_SPI_ETHERNET)
+		choice 
+			prompt "Ethernet Chipset"
+			default ETH_NODRIVER
+			config ETH_NODRIVER
+				bool "Defined in NVS"			   
+			config ETH_LAN8720
+				bool "Microchip LAN8720 (RMII)"
+			config ETH_DM9051
+				bool "Davicom 9051 (SPI)"				
+			config ETH_W5500
+				bool "WIZnet 5500 (SPI)"
+		endchoice	
+        comment  "LAN8720 is an RMII interface and most of the required GPIOs aren't user selectable. They are defined as follow tx_en=21, tx0=19, tx1=22, rx0=25, rx1=26, crs_dv=27"
+            depends on ETH_LAN8720        
+		config ETH_PHY_RST_IO
+			int "PHY Reset GPIO number" if !ETH_NODRIVER
+			default -1
+			help
+				Set the GPIO number used to reset PHY chip.
+				Set to -1 to disable PHY chip hardware reset.		
+		config ETH_MDC_IO
+			int "SMI MDC GPIO number" if ETH_LAN8720
+			default -1
+			help
+				Set the GPIO number used by SMI MDC.		
+		config ETH_MDIO_IO
+			int "SMI MDIO GPIO number" if ETH_LAN8720
+			default -1
+			help
+				Set the GPIO number used by SMI MDIO.		
+		config ETH_SPI_HOST
+			int "SPI host number (-1,1 or 2)" if ETH_DM9051 || ETH_W5500
+			default -1
+			help
+				Set to -1 to use system's SPI config (see Various I/O)
+				Set to 2 or 3 to use a dedicated bus 
+		config ETH_SPI_INTR_IO
+			int "interrupt" if ETH_DM9051 || ETH_W5500
+			default -1													
+		config ETH_SPI_CS_IO
+			int "Chip Select" if ETH_DM9051 || ETH_W5500
+			default -1								
+		config ETH_SPI_CLK_IO
+			int "SPI clock" if ETH_SPI_HOST != -1 && (ETH_DM9051 || ETH_W5500)
+			default -1
+		config ETH_SPI_MOSI_IO
+			int "Data Out" if ETH_SPI_HOST != -1 && (ETH_DM9051 || ETH_W5500)
+			default -1				
+		config ETH_SPI_MISO_IO
+			int "Data In"  if ETH_SPI_HOST != -1 && (ETH_DM9051 || ETH_W5500)
+			default -1
+		config ETH_SPI_SPEED
+			int "SPI speed (Hz)" if ETH_SPI_HOST != -1 && (ETH_DM9051 || ETH_W5500)
+			default 20000000
+	endmenu    
 endmenu

+ 1 - 1
components/wifi-manager/dns_server.c

@@ -53,7 +53,7 @@ Contains the freeRTOS task for the DNS server that processes the requests.
 
 #include <byteswap.h>
 #include "squeezelite-ota.h"
-#include "wifi_manager.h"
+#include "network_manager.h"
 
 static const char TAG[] = "dns_server";
 static TaskHandle_t task_dns_server = NULL;

+ 11 - 9
components/wifi-manager/http_server_handlers.c

@@ -55,6 +55,8 @@ function to process requests, decode URLs, serve files, etc. etc.
 #include "platform_console.h"
 #include "accessors.h"
 #include "webapp/webpack.h"
+#include "network_wifi.h"
+#include "network_status.h"
  
 #define HTTP_STACK_SIZE	(5*1024)
 const char str_na[]="N/A";
@@ -437,7 +439,7 @@ esp_err_t ap_scan_handler(httpd_req_t *req){
     	// todo:  redirect to login page
     	// return ESP_OK;
     }
-	wifi_manager_scan_async();
+	network_manager_async_scan();
 	esp_err_t err = set_content_type_from_req(req);
 	if(err == ESP_OK){
 		httpd_resp_send(req, (const char *)empty, HTTPD_RESP_USE_STRLEN);
@@ -728,7 +730,7 @@ esp_err_t config_post_handler(httpd_req_t *req){
 			ESP_LOGW_LOC(TAG,   "Restarting system to process OTA for url %s",otaURL);
 		}
 
-		wifi_manager_reboot_ota(otaURL);
+		network_manager_reboot_ota(otaURL);
 		free(otaURL);
 	}
     return err;
@@ -789,8 +791,8 @@ esp_err_t connect_post_handler(httpd_req_t *req){
 		if(password){
 			strlcpy((char *)config->sta.password, password, sizeof(config->sta.password)+1);
 		}
-		ESP_LOGD_LOC(TAG,   "http_server_netconn_serve: wifi_manager_connect_async() call, with ssid: %s, password: %s", config->sta.ssid, config->sta.password);
-		wifi_manager_connect_async();
+		ESP_LOGD_LOC(TAG,   "http_server_netconn_serve: network_manager_async_scan() call, with ssid: %s, password: %s", config->sta.ssid, config->sta.password);
+		network_manager_async_scan();
 		httpd_resp_send(req, (const char *)success, strlen(success));
 	}
 	else {
@@ -814,7 +816,7 @@ esp_err_t connect_delete_handler(httpd_req_t *req){
 		return err;
 	}
 	httpd_resp_send(req, (const char *)success, strlen(success));
-	wifi_manager_disconnect_async();
+	network_manager_async_disconnect();
 
     return ESP_OK;
 }
@@ -831,7 +833,7 @@ esp_err_t reboot_ota_post_handler(httpd_req_t *req){
 	}
 
 	httpd_resp_send(req, (const char *)success, strlen(success));
-	wifi_manager_reboot(OTA);
+	network_manager_async_reboot(OTA);
     return ESP_OK;
 }
 esp_err_t reboot_post_handler(httpd_req_t *req){
@@ -846,7 +848,7 @@ esp_err_t reboot_post_handler(httpd_req_t *req){
 		return err;
 	}
 	httpd_resp_send(req, (const char *)success, strlen(success));
-	wifi_manager_reboot(RESTART);
+	network_manager_async_reboot(RESTART);
 	return ESP_OK;
 }
 esp_err_t recovery_post_handler(httpd_req_t *req){
@@ -861,7 +863,7 @@ esp_err_t recovery_post_handler(httpd_req_t *req){
 		return err;
 	}
 	httpd_resp_send(req, (const char *)success, strlen(success));
-	wifi_manager_reboot(RECOVERY);
+	network_manager_async_reboot(RECOVERY);
 	return ESP_OK;
 }
 
@@ -1162,7 +1164,7 @@ esp_err_t status_get_handler(httpd_req_t *req){
 		httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR , "Error retrieving status object");
 	}
 	// update status for next status call
-	wifi_manager_update_status();
+	network_manager_async_update_status();
 
 	return ESP_OK;
 }

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

@@ -38,7 +38,7 @@ function to process requests, decode URLs, serve files, etc. etc.
 #include <stdlib.h>
 #include <stdbool.h>
 #include "esp_http_server.h"
-#include "wifi_manager.h"
+#include "network_manager.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/event_groups.h"

+ 38 - 0
components/wifi-manager/network_driver_DM9051.c

@@ -0,0 +1,38 @@
+#include "esp_eth.h"
+#include "network_ethernet.h"
+
+static esp_eth_mac_t* mac_new(spi_device_handle_t spi_handle, eth_config_t* ethernet_config) {
+#ifdef CONFIG_ETH_SPI_ETHERNET_DM9051
+    eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
+    eth_dm9051_config_t eth_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
+    // we assume that isr has been installed already
+    eth_config.int_gpio_num = ethernet_config->intr;
+    return esp_eth_mac_new_dm9051(&eth_config, &mac_config);
+#else
+    return NULL;
+#endif
+}
+static esp_eth_phy_t* phy_new(eth_config_t* ethernet_config) {
+#ifdef CONFIG_ETH_SPI_ETHERNET_DM9051
+    eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
+    phy_config.phy_addr = 1;
+    phy_config.reset_gpio_num = ethernet_config->rst;
+    return esp_eth_phy_new_dm9051(&phy_config);
+#else
+    return NULL;
+#endif
+}
+static void init_config(eth_config_t* ethernet_config) {
+}
+
+static network_ethernet_driver_t DM9051 = {
+    .mac_new = mac_new,
+    .phy_new = phy_new,
+    .init_config = init_config,
+    .valid = true,
+};
+network_ethernet_driver_t* DM9051_Detect(char* Driver) {
+    if (!strcasestr(Driver, "DM9051"))
+        return NULL;
+    return &DM9051;
+}

+ 47 - 0
components/wifi-manager/network_driver_LAN8720.c

@@ -0,0 +1,47 @@
+#include "esp_eth.h"
+#include "network_ethernet.h"
+
+static esp_eth_mac_t* mac_new(spi_device_handle_t spi_handle, eth_config_t* ethernet_config) {
+#ifdef CONFIG_ETH_PHY_INTERFACE_RMII
+    eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
+    mac_config.smi_mdc_gpio_num = ethernet_config->mdc;
+    mac_config.smi_mdio_gpio_num = ethernet_config->mdio;
+    mac_config.sw_reset_timeout_ms = 400;
+    return esp_eth_mac_new_esp32(&mac_config);
+#else
+    return NULL;
+#endif
+}
+static esp_eth_phy_t* phy_new(eth_config_t* ethernet_config) {
+#ifdef CONFIG_ETH_PHY_INTERFACE_RMII    
+    eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
+    phy_config.phy_addr = 1;
+    phy_config.reset_gpio_num = ethernet_config->rst;
+    return esp_eth_phy_new_lan8720(&phy_config);
+#else
+    return NULL;
+#endif    
+}
+static void init_config(eth_config_t* ethernet_config) {
+#ifdef CONFIG_ETH_PHY_INTERFACE_RMII
+#else
+    return NULL;
+#endif
+}
+
+static network_ethernet_driver_t LAN8720 = {
+
+    .mac_new = mac_new,
+    .phy_new = phy_new,
+    .init_config = init_config,
+#ifdef CONFIG_ETH_PHY_INTERFACE_RMII
+    .valid = true,
+#else
+    .valid = false,
+#endif
+};
+network_ethernet_driver_t* LAN8720_Detect(char* Driver) {
+    if (!strcasestr(Driver, "LAN8720"))
+        return NULL;
+    return &LAN8720;
+}

+ 43 - 0
components/wifi-manager/network_driver_W5500.c

@@ -0,0 +1,43 @@
+#include "esp_eth.h"
+#include "network_ethernet.h"
+
+static esp_eth_mac_t* mac_new(spi_device_handle_t spi_handle, eth_config_t* ethernet_config) {
+#ifdef CONFIG_ETH_SPI_ETHERNET_W5500
+    eth_w5500_config_t eth_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
+    eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
+    // we assume that isr has been installed already
+    eth_config.int_gpio_num = ethernet_config->intr;
+    return esp_eth_mac_new_w5500(&eth_config, &mac_config);
+#else
+    return NULL;
+#endif
+}
+static esp_eth_phy_t* phy_new(eth_config_t* ethernet_config) {
+#ifdef CONFIG_ETH_SPI_ETHERNET_W5500
+    eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
+    phy_config.phy_addr = 1;
+    phy_config.reset_gpio_num = ethernet_config->rst;
+    return esp_eth_phy_new_w5500(&phy_config);
+#else
+    return NULL;
+#endif
+}
+
+static void init_config(eth_config_t* ethernet_config) {
+}
+
+static network_ethernet_driver_t W5500 = {
+    .mac_new = mac_new,
+    .phy_new = phy_new,
+    .init_config = init_config,
+#ifdef CONFIG_ETH_SPI_ETHERNET_W5500
+    .valid = true,
+#else
+    .valid = false,
+#endif
+};
+network_ethernet_driver_t* W5500_Detect(char* Driver, network_ethernet_driver_t* Device) {
+    if (!strcasestr(Driver, "W5500"))
+        return NULL;
+    return &W5500;
+}

+ 283 - 0
components/wifi-manager/network_ethernet.c

@@ -0,0 +1,283 @@
+#include "network_ethernet.h"
+#include "freertos/timers.h"
+#include "globdefs.h"
+#include "messaging.h"
+#include "network_status.h"
+#include "platform_config.h"
+#include "trace.h"
+#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
+#include "esp_log.h"
+
+//#include "dnserver.h"
+
+static char TAG[] = "network_ethernet";
+TimerHandle_t ETH_timer;
+esp_eth_handle_t eth_handle = NULL;
+esp_netif_t* eth_netif = NULL;
+EventGroupHandle_t ethernet_event_group;
+const int LINK_UP_BIT = BIT0;
+
+static const char* known_drivers[] = {"DM9051", "W5500", "LAN8720", NULL};
+static network_ethernet_driver_t* network_driver = NULL;
+extern network_ethernet_detect_func_t DM9051_Detect, W5500_Detect, LAN8720_Detect;
+static network_ethernet_detect_func_t* drivers[] = {DM9051_Detect, W5500_Detect, LAN8720_Detect, NULL};
+#define ETH_TIMEOUT_MS (30 * 1000)
+static void network_manager_ethernet_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
+
+/****************************************************************************************
+ *
+ */
+const char* network_ethernet_conf_get_driver_name(const 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;
+}
+/****************************************************************************************
+ *
+ */
+bool network_ethernet_is_valid_driver(const char* driver) {
+    return network_ethernet_conf_get_driver_name(driver) != NULL;
+}
+
+network_ethernet_driver_t* network_ethernet_driver_autodetect(const char* Driver) {
+    if (!Driver)
+        return NULL;
+
+    for (int i = 0; drivers[i]; i++) {
+        network_ethernet_driver_t* found_driver = drivers[i](Driver);
+        if (found_driver) {
+            ESP_LOGD(TAG, "Detected driver %s ", Driver);
+
+            network_driver = found_driver;
+            return found_driver;
+        }
+    }
+    return NULL;
+}
+
+static void eth_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
+esp_netif_t *network_ethernet_get_interface(){
+    return eth_netif;
+}
+
+bool network_ethernet_is_up() {
+    return (xEventGroupGetBits(ethernet_event_group) & LINK_UP_BIT)!=0;
+}
+bool network_ethernet_enabled() {
+    return eth_handle != NULL;
+}
+bool network_ethernet_wait_for_link(uint16_t max_wait_ms){
+    if(!network_ethernet_enabled()) return false;
+	bool link_up=(xEventGroupGetBits(ethernet_event_group) & LINK_UP_BIT)!=0;
+	if(!link_up){
+		ESP_LOGD(TAG,"Waiting for Ethernet link to be established...");
+	    link_up = (xEventGroupWaitBits(ethernet_event_group, LINK_UP_BIT,pdFALSE, pdTRUE, max_wait_ms / portTICK_PERIOD_MS)& LINK_UP_BIT)!=0;
+	    if(!link_up){
+	    	ESP_LOGW(TAG,"Ethernet Link timeout.");
+	    }
+	    else
+	    {
+	    	ESP_LOGI(TAG,"Ethernet Link Up!");
+	    }
+	}
+    return link_up;
+}
+
+static void ETH_Timeout(void* timer_id);
+void destroy_network_ethernet() {
+}
+static void set_host_name() {
+    ESP_LOGE(TAG, "TODO: Find a way to set the host name here!");
+    // esp_err_t err;
+    // ESP_LOGD(TAG, "Retrieving host name from nvs");
+    // char* host_name = (char*)config_alloc_get(NVS_TYPE_STR, "host_name");
+    // if (host_name == NULL) {
+    //     ESP_LOGE(TAG, "Could not retrieve host name from nvs");
+    // } else {
+    //     if (!network_ethernet_enabled()) {
+    //         ESP_LOGE(TAG, "Cannot set name on a disabled interface");
+    //     } else {
+    //         ESP_LOGD(TAG, "Setting host name to : %s", host_name);
+    //         if ((err = esp_netif_set_hostname(eth_handle, host_name)) != ESP_OK) {
+    //             ESP_LOGE(TAG, "Unable to set host name. Error: %s", esp_err_to_name(err));
+    //         }
+    //         ESP_LOGD(TAG, "Done setting host name to : %s", host_name);
+    //     }
+
+    //     FREE_AND_NULL(host_name);
+    // }
+}
+static void network_ethernet_print_config(const eth_config_t* eth_config) {
+    // #if defined(CONFIG_ETH_PHY_INTERFACE_RMII)
+    //     if(eth_config->)
+    //     ESP_LOGI(TAG,
+    //              "Model: %s, rst=%d, mdc=%d, mdio=%d, host=%d, cs=%d, mosi=%d, miso=%d, intr=%d, clk=%d, speed=%d, tx_en=%d, tx0=%d, tx1=%d, rx0=%d, rx1=%d, crs_dv=%d",
+    //              eth_config->model, eth_config->rst, eth_config->mdc, eth_config->mdio, eth_config->host, eth_config->cs,
+    //              eth_config->mosi, eth_config->miso, eth_config->intr, eth_config->clk, eth_config->speed,
+    //              eth_config->tx_en, eth_config->tx0, eth_config->tx1, eth_config->rx0, eth_config->rx1, eth_config->crs_dv);
+    // #else
+    //     ESP_LOGI(TAG, "Model: %s, rst=%d, mdc=%d, mdio=%d, host=%d, cs=%d, mosi=%d, miso=%d, intr=%d, clk=%d, speed=%d ",
+    //              eth_config->model, eth_config->rst, eth_config->mdc, eth_config->mdio, eth_config->host, eth_config->cs,
+    //              eth_config->mosi, eth_config->miso, eth_config->intr, eth_config->clk, eth_config->speed);
+    //         :
+    // #endif
+}
+
+void init_network_ethernet() {
+    esp_err_t err = ESP_OK;
+    esp_eth_mac_t* mac;
+    esp_eth_phy_t* phy;
+    eth_config_t eth;
+    config_eth_init(&eth);
+    ESP_LOGD(TAG, "Attempting to initialize Ethernet");
+    // quick check if we have a valid ethernet configuration
+    if (!eth.valid) {
+        ESP_LOGI(TAG, "No ethernet");
+        return;
+    }
+    network_driver = network_ethernet_driver_autodetect(eth.model);
+    if (!network_driver) {
+        messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Invalid ethernet Ethernet chip %s", eth.model);
+        return;
+    }
+    if (!network_driver->valid) {
+        messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Code not compiled for Ethernet chip %s", eth.model);
+        return;
+    }
+    network_driver->init_config(&eth);
+    network_ethernet_print_config(&eth);
+    esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
+    eth_netif = esp_netif_new(&cfg);
+    esp_eth_set_default_handlers(eth_netif);
+    esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL);
+    esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL);
+    ethernet_event_group = xEventGroupCreate();
+	xEventGroupClearBits(ethernet_event_group, LINK_UP_BIT);
+    spi_device_handle_t spi_handle = NULL;
+    if (network_driver->eth_config.spi) {
+        spi_host_device_t host = SPI3_HOST;
+
+        if (eth.host != -1) {
+            // don't use system's shared SPI
+            spi_bus_config_t buscfg = {
+                .miso_io_num = eth.miso,
+                .mosi_io_num = eth.mosi,
+                .sclk_io_num = eth.clk,
+                .quadwp_io_num = -1,
+                .quadhd_io_num = -1,
+            };
+
+            // can't use SPI0
+            if (eth.host == 1)
+                host = SPI2_HOST;
+            ESP_LOGI(TAG, "Initializing SPI bus on host %d with mosi %d and miso %d", host, eth.mosi, eth.miso);
+            err = spi_bus_initialize(host, &buscfg, 1);
+            if (err != ESP_OK) {
+                ESP_LOGE(TAG, "SPI bus init failed : %s", esp_err_to_name(err));
+            }
+
+        } else {
+            // when we use shared SPI, we assume it has been initialized
+            host = spi_system_host;
+        }
+        if (err == ESP_OK) {
+            spi_device_interface_config_t devcfg = {
+                .command_bits = 1,
+                .address_bits = 7,
+                .mode = 0,
+                .clock_speed_hz = eth.speed,
+                .spics_io_num = eth.cs,
+                .queue_size = 20};
+            ESP_LOGI(TAG, "Adding ethernet SPI on host %d with mosi %d and miso %d", host, eth.mosi, eth.miso);
+            err = spi_bus_add_device(host, &devcfg, &spi_handle);
+        }
+        if (err != ESP_OK) {
+            ESP_LOGE(TAG, "SPI host failed : %s", esp_err_to_name(err));
+        }
+    }
+    if (err == ESP_OK) {
+        ESP_LOGD(TAG, "Setting up ethernet driver");
+        mac = network_driver->mac_new(spi_handle, &eth);
+        phy = network_driver->phy_new(&eth);
+        esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
+        err = esp_eth_driver_install(&config, &eth_handle);
+    }
+    if (err == ESP_OK) {
+        ESP_LOGD(TAG, "Attaching ethernet to network interface");
+        err = esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle));
+    }
+    if (err == ESP_OK) {
+        ESP_LOGI(TAG, "Starting ethernet network");
+        err = esp_eth_start(eth_handle);
+    }
+    if (err != ESP_OK) {
+        messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Configuring Ethernet failed: %s", esp_err_to_name(err));
+        eth_handle = NULL;
+    }
+}
+
+void network_ethernet_start_timer() {
+    ETH_timer = xTimerCreate("ETH check", pdMS_TO_TICKS(ETH_TIMEOUT_MS), pdFALSE, NULL, ETH_Timeout);
+}
+
+/** Event handler for Ethernet events */
+static void eth_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
+    uint8_t mac_addr[6] = {0};
+    /* we can get the ethernet driver handle from event data */
+    if (event_base == ETH_EVENT) {
+        esp_eth_handle_t eth_handle = *(esp_eth_handle_t*)event_data;
+        switch (event_id) {
+            case ETHERNET_EVENT_CONNECTED:
+                xEventGroupSetBits(ethernet_event_group, LINK_UP_BIT);
+                esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
+                ESP_LOGI(TAG, "");
+                ESP_LOGI(TAG, "Ethernet Link Up, HW Addr %02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
+                ESP_LOGD(TAG, "Sending EVENT_ETH_LINK_UP message to network manager");
+                network_manager_async_link_up();
+                break;
+            case ETHERNET_EVENT_DISCONNECTED:
+                ESP_LOGI(TAG, "Ethernet Link Down");
+                xEventGroupClearBits(ethernet_event_group, LINK_UP_BIT);
+                ESP_LOGD(TAG, "Sending EVENT_ETH_LINK_DOWN message to network manager");
+                network_manager_async_link_down();
+                break;
+            case ETHERNET_EVENT_START:
+                ESP_LOGI(TAG, "Ethernet Started. Setting host name");
+                set_host_name();
+                break;
+            case ETHERNET_EVENT_STOP:
+                ESP_LOGI(TAG, "Ethernet Stopped");
+                break;
+            default:
+                break;
+        }
+    } else if (event_base == IP_EVENT && event_id == IP_EVENT_ETH_GOT_IP) {
+        network_manager_ethernet_ip_event_handler(arg, event_base, event_id, event_data);
+    }
+}
+
+static void ETH_Timeout(void* timer_id) {
+    network_manager_async_fail();
+}
+
+static void network_manager_ethernet_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
+    if (event_base != IP_EVENT)
+        return;
+    ip_event_got_ip_t* event = (ip_event_got_ip_t*)event_data;
+    ip_event_got_ip_t* s = event_data;
+    tcpip_adapter_if_t index = s->if_index;
+    esp_netif_ip_info_t* ip_info = &s->ip_info;
+
+    ESP_LOGI(TAG, "Got an IP address from Ethernet interface #%i. IP=" IPSTR ", Gateway=" IPSTR ", NetMask=" IPSTR ", %s",
+             index,
+             IP2STR(&ip_info->ip),
+             IP2STR(&ip_info->gw),
+             IP2STR(&ip_info->netmask),
+             s->ip_changed ? "Address was changed" : "Address unchanged");
+    ip_event_got_ip_t* parm = malloc(sizeof(ip_event_got_ip_t));
+    memcpy(parm, event_data, sizeof(ip_event_got_ip_t));
+    network_manager_async_got_ip(parm);
+}

+ 30 - 0
components/wifi-manager/network_ethernet.h

@@ -0,0 +1,30 @@
+#pragma once
+
+#include "network_manager.h"
+#include "accessors.h"
+#include <string.h>
+#ifdef __cplusplus
+extern "C" {
+
+#endif
+typedef struct {
+    bool valid;
+    eth_config_t eth_config;
+    esp_eth_mac_t* (*mac_new)(spi_device_handle_t spi_handle, eth_config_t * eth_config);
+    esp_eth_phy_t *(*phy_new)( eth_config_t* eth_config);
+    void (*init_config)(eth_config_t * eth_config);
+} network_ethernet_driver_t;
+typedef network_ethernet_driver_t* network_ethernet_detect_func_t(const char* Driver);
+
+void destroy_network_ethernet();
+void init_network_ethernet();
+bool network_ethernet_wait_for_link(uint16_t max_wait_ms);
+
+void network_ethernet_start_timer();
+bool network_ethernet_is_up();
+bool network_ethernet_enabled();
+esp_netif_t *network_ethernet_get_interface();
+#ifdef __cplusplus
+}
+
+#endif

+ 120 - 0
components/wifi-manager/network_manager.c

@@ -0,0 +1,120 @@
+/*
+Copyright (c) 2017-2019 Tony Pottier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+@file wifi_manager.c
+@author Tony Pottier
+@brief Defines all functions necessary for esp32 to connect to a wifi/scan wifis
+
+Contains the freeRTOS task and all necessary support
+
+@see https://idyl.io
+@see https://github.com/tonyp7/esp32-wifi-manager
+*/
+
+#include "network_manager.h"
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "network_ethernet.h"
+#include "network_status.h"
+#include "network_wifi.h"
+#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
+#include "esp_log.h"
+#include "platform_esp32.h"
+
+
+#include "esp_system.h"
+#include "freertos/FreeRTOS.h"
+
+#include "freertos/task.h"
+#include "esp_netif.h"
+
+#include "cJSON.h"
+#include "cmd_system.h"
+#include "esp_app_format.h"
+
+#include "esp_event.h"
+#include "esp_ota_ops.h"
+#include "esp_wifi.h"
+#include "esp_wifi_types.h"
+#include "lwip/api.h"
+#include "lwip/err.h"
+#include "lwip/ip4_addr.h"
+#include "lwip/netdb.h"
+#include "mdns.h"
+#include "messaging.h"
+#include "state_machine.h"
+
+#include "platform_config.h"
+#include "trace.h"
+
+#include "accessors.h"
+#include "globdefs.h"
+#include "http_server_handlers.h"
+
+
+
+#ifndef STR_OR_BLANK
+#define STR_OR_BLANK(p) p == NULL ? "" : p
+#endif
+
+//EventGroupHandle_t wifi_manager_event_group;
+void (**cb_ptr_arr)(void*) = NULL;
+
+/* @brief tag used for ESP serial console messages */
+//static const char TAG[] = "network_manager";
+
+/* @brief indicate that the ESP32 is currently connected. */
+const int WIFI_MANAGER_WIFI_CONNECTED_BIT = BIT0;
+const int WIFI_MANAGER_AP_STA_CONNECTED_BIT = BIT1;
+/* @brief Set automatically once the SoftAP is started */
+const int WIFI_MANAGER_AP_STARTED_BIT = BIT2;
+/* @brief When set, means a client requested to connect to an access point.*/
+const int WIFI_MANAGER_REQUEST_STA_CONNECT_BIT = BIT3;
+/* @brief This bit is set automatically as soon as a connection was lost */
+const int WIFI_MANAGER_STA_DISCONNECT_BIT = BIT4;
+/* @brief When set, means the wifi manager attempts to restore a previously saved connection at startup. */
+const int WIFI_MANAGER_REQUEST_RESTORE_STA_BIT = BIT5;
+/* @brief When set, means a client requested to disconnect from currently connected AP. */
+const int WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT = BIT6;
+/* @brief When set, means a scan is in progress */
+const int WIFI_MANAGER_SCAN_BIT = BIT7;
+/* @brief When set, means user requested for a disconnect */
+const int WIFI_MANAGER_REQUEST_DISCONNECT_BIT = BIT8;
+/* @brief When set, means user requested connecting to a new network and it failed */
+const int WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT = BIT9;
+
+/* @brief task handle for the main wifi_manager task */
+
+
+
+
+
+
+
+
+void wifi_manager_set_callback(message_code_t message_code, void (*func_ptr)(void*)) {
+    if (cb_ptr_arr && message_code < MESSAGE_CODE_COUNT) {
+        cb_ptr_arr[message_code] = func_ptr;
+    }
+}
+

+ 59 - 116
components/wifi-manager/wifi_manager.h → components/wifi-manager/network_manager.h

@@ -19,7 +19,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 
-@file wifi_manager.h
+@file network_manager.h
 @author Tony Pottier
 @brief Defines all functions necessary for esp32 to connect to a wifi/scan wifis
 
@@ -41,8 +41,10 @@ extern "C" {
 #include "esp_wifi_types.h"
 #include "squeezelite-ota.h"
 #include "cJSON.h"
-
-
+#include "esp_eth.h"
+#include "freertos/event_groups.h"
+#include "state_machine.h"
+#include "state_machine.h"
 /**
  * @brief Defines the maximum size of a SSID name. 32 is IEEE standard.
  * @warning limit is also hard coded in wifi_config_t. Never extend this value.
@@ -158,9 +160,6 @@ extern "C" {
  */
 #define JSON_ONE_APP_SIZE					99
 
-
-
-
 /**
  * @brief Defines the complete list of all messages that the wifi_manager can process.
  *
@@ -186,25 +185,51 @@ typedef enum message_code_t {
 	ORDER_START_DNS_HIJACK = 11,
 	EVENT_STA_DISCONNECTED = 12,
 	EVENT_SCAN_DONE = 13,
-	EVENT_STA_GOT_IP = 14,
+	EVENT_GOT_IP = 14,
 	ORDER_RESTART_OTA = 15,
 	ORDER_RESTART_RECOVERY = 16,
 	ORDER_RESTART_OTA_URL = 17,
 	ORDER_RESTART = 18,
 	ORDER_UPDATE_STATUS = 19,
 	EVENT_ETH_GOT_IP = 20,
-	MESSAGE_CODE_COUNT = 21 /* important for the callback array */
-
+	EVENT_ETH_TIMEOUT = 21,
+	EVENT_ETH_LINK_UP = 22,
+	EVENT_ETH_LINK_DOWN = 23,
+	MESSAGE_CODE_COUNT = 24 /* important for the callback array */
 }message_code_t;
 
-typedef enum reboot_type_t{
-	OTA,
-	RECOVERY,
-	RESTART,
-} reboot_type_t;
-void wifi_manager_reboot(reboot_type_t rtype);
-void wifi_manager_reboot_ota(char * url);
-void wifi_manager_update_status();
+
+
+/* @brief indicate that the ESP32 is currently connected. */
+extern const int WIFI_MANAGER_WIFI_CONNECTED_BIT;
+
+extern const int WIFI_MANAGER_AP_STA_CONNECTED_BIT;
+
+/* @brief Set automatically once the SoftAP is started */
+extern const int WIFI_MANAGER_AP_STARTED_BIT;
+
+/* @brief When set, means a client requested to connect to an access point.*/
+extern const int WIFI_MANAGER_REQUEST_STA_CONNECT_BIT;
+
+/* @brief This bit is set automatically as soon as a connection was lost */
+extern const int WIFI_MANAGER_STA_DISCONNECT_BIT ;
+
+/* @brief When set, means the wifi manager attempts to restore a previously saved connection at startup. */
+extern const int WIFI_MANAGER_REQUEST_RESTORE_STA_BIT ;
+
+/* @brief When set, means a client requested to disconnect from currently connected AP. */
+extern const int WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT ;
+
+/* @brief When set, means a scan is in progress */
+extern const int WIFI_MANAGER_SCAN_BIT ;
+
+/* @brief When set, means user requested for a disconnect */
+extern const int WIFI_MANAGER_REQUEST_DISCONNECT_BIT ;
+
+/* @brief When set, means user requested connecting to a new network and it failed */
+extern const int WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT ;
+
+void network_manager_reboot_ota(char * url);
 
 
 /**
@@ -218,6 +243,7 @@ typedef enum update_reason_code_t {
 	UPDATE_USER_DISCONNECT = 2,
 	UPDATE_LOST_CONNECTION = 3,
 	UPDATE_FAILED_ATTEMPT_AND_RESTORE = 4,
+	UPDATE_ETHERNET_CONNECTED = 5
 
 }update_reason_code_t;
 
@@ -226,6 +252,7 @@ typedef enum connection_request_made_by_code_t{
 	CONNECTION_REQUEST_USER = 1,
 	CONNECTION_REQUEST_AUTO_RECONNECT = 2,
 	CONNECTION_REQUEST_RESTORE_CONNECTION = 3,
+	CONNECTION_REQUEST_MAX_FAILED = 4,
 	CONNECTION_REQUEST_MAX = 0x7fffffff /*force the creation of this enum as a 32 bit int */
 }connection_request_made_by_code_t;
 
@@ -240,25 +267,24 @@ typedef enum connection_request_made_by_code_t{
 //};
 //extern struct wifi_settings_t wifi_settings;
 
-/**
- * @brief Structure used to store one message in the queue.
- */
-typedef struct{
-	message_code_t code;
-	void *param;
-} queue_message;
+// /**
+//  * @brief Structure used to store one message in the queue.
+//  */
+// typedef struct{
+// 	message_code_t code;
+// 	void *param;
+// } queue_message;
+
+
+
 
 
 
-/**
- * Allocate heap memory for the wifi manager and start the wifi_manager RTOS task
- */
-void wifi_manager_start();
 
 /**
  * Frees up all memory allocated by the wifi_manager and kill the task.
  */
-void wifi_manager_destroy();
+void network_manager_destroy();
 
 /**
  * Filters the AP scan list to unique SSIDs
@@ -268,27 +294,14 @@ void  filter_unique( wifi_ap_record_t * aplist, uint16_t * ap_num);
 /**
  * Main task for the wifi_manager
  */
-void wifi_manager( void * pvParameters );
+void network_manager( void * pvParameters );
 
 
 char* wifi_manager_alloc_get_ap_list_json();
-char* wifi_manager_alloc_get_ip_info_json();
 cJSON * wifi_manager_clear_ap_list_json(cJSON **old);
 
-/**
- * @brief saves the current STA wifi config to flash ram storage.
- */
-esp_err_t wifi_manager_save_sta_config();
 
 
-/**
- * @brief fetch a previously STA wifi config in the flash ram storage.
- * @return true if a previously saved config was found, false otherwise.
- */
-bool wifi_manager_fetch_wifi_sta_config();
-
-wifi_config_t* wifi_manager_get_wifi_sta_config();
-
 /**
  * @brief A standard wifi event handler as recommended by Espressif
  */
@@ -296,71 +309,13 @@ esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event);
 
 
 
-/**
- * @brief Registers handler for wifi and ip events
- */
-void wifi_manager_register_handlers();
-
-
-/**
- * @brief requests a connection to an access point that will be process in the main task thread.
- */
-void wifi_manager_connect_async();
-
-/**
- * @brief requests a wifi scan
- */
-void wifi_manager_scan_async();
-
-/**
- * @brief requests to disconnect and forget about the access point.
- */
-void wifi_manager_disconnect_async();
-
-/**
- * @brief Tries to get access to json buffer mutex.
- *
- * The HTTP server can try to access the json to serve clients while the wifi manager thread can try
- * to update it. These two tasks are synchronized through a mutex.
- *
- * The mutex is used by both the access point list json and the connection status json.\n
- * These two resources should technically have their own mutex but we lose some flexibility to save
- * on memory.
- *
- * This is a simple wrapper around freeRTOS function xSemaphoreTake.
- *
- * @param xTicksToWait The time in ticks to wait for the semaphore to become available.
- * @return true in success, false otherwise.
- */
-bool wifi_manager_lock_json_buffer(TickType_t xTicksToWait);
-
-/**
- * @brief Releases the json buffer mutex.
- */
-void wifi_manager_unlock_json_buffer();
-
-/**
- * @brief Generates the connection status json: ssid and IP addresses.
- * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful.
- */
-void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code);
 /**
  * @brief Clears the connection status json.
  * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful.
  */
 cJSON * wifi_manager_clear_ip_info_json(cJSON **old);
 cJSON * wifi_manager_get_new_json(cJSON **old);
-/**
- * @brief Generates the list of access points after a wifi scan.
- * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful.
- */
-void wifi_manager_generate_access_points_json(cJSON ** ap_list);
 
-/**
- * @brief Clear the list of access points.
- * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful.
- */
-void wifi_manager_clear_access_points_json();
 
 
 /**
@@ -369,19 +324,6 @@ void wifi_manager_clear_access_points_json();
 void wifi_manager_initialise_mdns();
 
 
-bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait);
-void wifi_manager_unlock_sta_ip_string();
-
-/**
- * @brief gets the string representation of the STA IP address, e.g.: "192.168.1.69"
- */
-char* wifi_manager_get_sta_ip_string();
-
-/**
- * @brief thread safe char representation of the STA IP update
- */
-void wifi_manager_safe_update_sta_ip_string(struct ip4_addr * ip4);
-
 
 /**
  * @brief Register a callback to a custom function when specific event message_code happens.
@@ -389,8 +331,9 @@ void wifi_manager_safe_update_sta_ip_string(struct ip4_addr * ip4);
 void wifi_manager_set_callback(message_code_t message_code, void (*func_ptr)(void*) );
 
 
-BaseType_t wifi_manager_send_message(message_code_t code, void *param);
-BaseType_t wifi_manager_send_message_to_front(message_code_t code, void *param);
+bool network_manager_is_flag_set(EventBits_t bit);
+void network_manager_set_flag(EventBits_t bit);
+void network_manager_clear_flag(EventBits_t bit);
 
 #ifdef __cplusplus
 }

+ 381 - 0
components/wifi-manager/network_status.c

@@ -0,0 +1,381 @@
+#include "network_status.h"
+#include <string.h>
+#include "bt_app_core.h"
+#include "esp_log.h"
+#include "globdefs.h"
+#include "lwip/inet.h"
+#include "monitor.h"
+#include "network_ethernet.h"
+#include "network_wifi.h"
+#include "platform_config.h"
+#include "platform_esp32.h"
+#include "tools.h"
+#include "trace.h"
+#ifndef CONFIG_SQUEEZELITE_ESP32_RELEASE_URL
+#pragma message "Defaulting release url"
+#define CONFIG_SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases"
+#endif
+static const char TAG[] = "network_status";
+SemaphoreHandle_t wifi_manager_json_mutex = NULL;
+SemaphoreHandle_t wifi_manager_sta_ip_mutex = NULL;
+char* release_url = NULL;
+char* wifi_manager_sta_ip = NULL;
+char* ip_info_json = NULL;
+cJSON* ip_info_cjson = NULL;
+static char lms_server_ip[IP4ADDR_STRLEN_MAX] = {0};
+static uint16_t lms_server_port = 0;
+static uint16_t lms_server_cport = 0;
+static void (*chained_notify)(in_addr_t, u16_t, u16_t);
+static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport);
+#define STA_IP_LEN sizeof(char) * IP4ADDR_STRLEN_MAX
+
+void init_network_status() {
+    chained_notify = server_notify;
+    server_notify = connect_notify;
+    ESP_LOGD(TAG, "init_network_status.  Creating mutexes");
+    wifi_manager_json_mutex = xSemaphoreCreateMutex();
+    wifi_manager_sta_ip_mutex = xSemaphoreCreateMutex();
+    ip_info_json = NULL;
+    ESP_LOGD(TAG, "init_network_status.  Creating status json structure");
+    ip_info_cjson = wifi_manager_clear_ip_info_json(&ip_info_cjson);
+    ESP_LOGD(TAG, "Getting release url ");
+    char* release_url = (char*)config_alloc_get_default(NVS_TYPE_STR, "release_url", QUOTE(CONFIG_SQUEEZELITE_ESP32_RELEASE_URL), 0);
+    if (release_url == NULL) {
+        ESP_LOGE(TAG, "Unable to retrieve the release url from nvs");
+    } else {
+        ESP_LOGD(TAG, "Found release url %s", release_url);
+    }
+    ESP_LOGD(TAG, "About to set the STA IP String to 0.0.0.0");
+    wifi_manager_sta_ip = (char*)malloc(STA_IP_LEN);
+    wifi_manager_safe_update_sta_ip_string(NULL);
+}
+void destroy_network_status() {
+    FREE_AND_NULL(release_url);
+    FREE_AND_NULL(ip_info_json);
+    FREE_AND_NULL(wifi_manager_sta_ip);
+    cJSON_Delete(ip_info_cjson);
+    vSemaphoreDelete(wifi_manager_json_mutex);
+    wifi_manager_json_mutex = NULL;
+    vSemaphoreDelete(wifi_manager_sta_ip_mutex);
+    wifi_manager_sta_ip_mutex = NULL;
+    ip_info_cjson = NULL;
+}
+cJSON* wifi_manager_get_new_json(cJSON** old) {
+    ESP_LOGV(TAG, "wifi_manager_get_new_json called");
+    cJSON* root = *old;
+    if (root != NULL) {
+        cJSON_Delete(root);
+        *old = NULL;
+    }
+    ESP_LOGV(TAG, "wifi_manager_get_new_json done");
+    return cJSON_CreateObject();
+}
+
+cJSON* wifi_manager_clear_ip_info_json(cJSON** old) {
+    ESP_LOGV(TAG, "wifi_manager_clear_ip_info_json called");
+    cJSON* root = wifi_manager_get_basic_info(old);
+    ESP_LOGV(TAG, "wifi_manager_clear_ip_info_json done");
+    return root;
+}
+void network_status_clear_ip() {
+    if (wifi_manager_lock_json_buffer(portMAX_DELAY)) {
+        ip_info_cjson = wifi_manager_clear_ip_info_json(&ip_info_cjson);
+        wifi_manager_unlock_json_buffer();
+    }
+}
+char* wifi_manager_alloc_get_ip_info_json() {
+    return cJSON_PrintUnformatted(ip_info_cjson);
+}
+
+void wifi_manager_unlock_json_buffer() {
+    ESP_LOGV(TAG, "Unlocking json buffer!");
+    xSemaphoreGive(wifi_manager_json_mutex);
+}
+
+bool wifi_manager_lock_json_buffer(TickType_t xTicksToWait) {
+    ESP_LOGV(TAG, "Locking json buffer");
+    if (wifi_manager_json_mutex) {
+        if (xSemaphoreTake(wifi_manager_json_mutex, xTicksToWait) == pdTRUE) {
+            ESP_LOGV(TAG, "Json buffer locked!");
+            return true;
+        } else {
+            ESP_LOGE(TAG, "Semaphore take failed. Unable to lock json buffer mutex");
+            return false;
+        }
+    } else {
+        ESP_LOGV(TAG, "Unable to lock json buffer mutex");
+        return false;
+    }
+}
+
+bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait) {
+    if (wifi_manager_sta_ip_mutex) {
+        if (xSemaphoreTake(wifi_manager_sta_ip_mutex, xTicksToWait) == pdTRUE) {
+            return true;
+        } else {
+            return false;
+        }
+    } else {
+        return false;
+    }
+}
+
+void wifi_manager_unlock_sta_ip_string() {
+    xSemaphoreGive(wifi_manager_sta_ip_mutex);
+}
+
+void wifi_manager_safe_update_sta_ip_string(esp_ip4_addr_t* ip4) {
+    if (wifi_manager_lock_sta_ip_string(portMAX_DELAY)) {
+        strcpy(wifi_manager_sta_ip, ip4 != NULL ? ip4addr_ntoa(ip4) : "0.0.0.0");
+        ESP_LOGD(TAG, "Set STA IP String to: %s", wifi_manager_sta_ip);
+        wifi_manager_unlock_sta_ip_string();
+    }
+}
+void wifi_manager_safe_reset_sta_ip_string() {
+    if (wifi_manager_lock_sta_ip_string(portMAX_DELAY)) {
+        strcpy(wifi_manager_sta_ip, "0.0.0.0");
+        ESP_LOGD(TAG, "Set STA IP String to: %s", wifi_manager_sta_ip);
+        wifi_manager_unlock_sta_ip_string();
+    }
+}
+char* wifi_manager_get_sta_ip_string() {
+    return wifi_manager_sta_ip;
+}
+void set_lms_server_details(in_addr_t ip, u16_t hport, u16_t cport) {
+    strncpy(lms_server_ip, inet_ntoa(ip), sizeof(lms_server_ip));
+    lms_server_ip[sizeof(lms_server_ip) - 1] = '\0';
+    ESP_LOGI(TAG, "LMS IP: %s, hport: %d, cport: %d", lms_server_ip, hport, cport);
+    lms_server_port = hport;
+    lms_server_cport = cport;
+}
+static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport) {
+    set_lms_server_details(ip, hport, cport);
+    if (chained_notify)
+        (*chained_notify)(ip, hport, cport);
+    network_manager_async_update_status();
+}
+void wifi_manager_update_basic_info() {
+    int32_t total_connected_time = 0;
+    int64_t last_connected = 0;
+    uint16_t num_disconnect = 0;
+    network_wifi_get_stats(&total_connected_time, &last_connected, &num_disconnect);
+    if (wifi_manager_lock_json_buffer(portMAX_DELAY)) {
+        monitor_gpio_t* mgpio = get_jack_insertion_gpio();
+
+        cJSON* voltage = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "Voltage");
+        if (voltage) {
+            cJSON_SetNumberValue(voltage, battery_value_svc());
+        }
+        cJSON* bt_status = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "bt_status");
+        if (bt_status) {
+            cJSON_SetNumberValue(bt_status, bt_app_source_get_a2d_state());
+        }
+        cJSON* bt_sub_status = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "bt_sub_status");
+        if (bt_sub_status) {
+            cJSON_SetNumberValue(bt_sub_status, bt_app_source_get_media_state());
+        }
+        cJSON* jack = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "Jack");
+        if (jack) {
+            jack->type = mgpio->gpio >= 0 && jack_inserted_svc() ? cJSON_True : cJSON_False;
+        }
+        cJSON* disconnect_count = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "disconnect_count");
+        if (disconnect_count) {
+            cJSON_SetNumberValue(disconnect_count, num_disconnect);
+        }
+        cJSON* avg_conn_time = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "avg_conn_time");
+        if (avg_conn_time) {
+            cJSON_SetNumberValue(avg_conn_time, num_disconnect > 0 ? (total_connected_time / num_disconnect) : 0);
+        }
+        if (lms_server_cport > 0) {
+            cJSON* value = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "lms_cport");
+            if (value) {
+                cJSON_SetNumberValue(value, lms_server_cport);
+            } else {
+                cJSON_AddNumberToObject(ip_info_cjson, "lms_cport", lms_server_cport);
+            }
+        }
+
+        if (lms_server_port > 0) {
+            cJSON* value = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "lms_port");
+            if (value) {
+                cJSON_SetNumberValue(value, lms_server_port);
+            } else {
+                cJSON_AddNumberToObject(ip_info_cjson, "lms_port", lms_server_port);
+            }
+        }
+
+        if (strlen(lms_server_ip) > 0) {
+            cJSON* value = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "lms_ip");
+            if (!value) {
+                // only create if it does not exist. Since we're creating a reference
+                // to a char buffer, updates to cJSON aren't needed
+                cJSON_AddItemToObject(ip_info_cjson, "lms_ip", cJSON_CreateStringReference(lms_server_ip));
+            }
+        }
+        if (network_ethernet_enabled()) {
+            cJSON* eth = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "eth_up");
+            if (eth) {
+                eth->type = network_ethernet_is_up() ? cJSON_True : cJSON_False;
+            }
+        }
+        wifi_manager_unlock_json_buffer();
+    }
+}
+cJSON* network_status_update_string(cJSON** root, const char* key, const char* value) {
+    if (*root == NULL) {
+        *root = cJSON_CreateObject();
+    }
+
+    if (!key || !value || strlen(key) == 0)
+        return *root;
+    cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
+    if (cjsonvalue && strcasecmp(cJSON_GetStringValue(cjsonvalue), value) != 0) {
+        ESP_LOGD(TAG, "Value %s changed from %s to %s", key, cJSON_GetStringValue(cjsonvalue), value);
+        cJSON_SetValuestring(cjsonvalue, value);
+    } else {
+        cJSON_AddItemToObject(*root, key, cJSON_CreateString(value));
+    }
+    return *root;
+}
+cJSON* network_status_update_number(cJSON** root, const char* key, int value) {
+    if (wifi_manager_lock_json_buffer(portMAX_DELAY)) {
+        if (*root == NULL) {
+            *root = cJSON_CreateObject();
+        }
+
+        if (key && value && strlen(key) != 0) {
+            cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
+            if (cjsonvalue) {
+                cJSON_SetNumberValue(cjsonvalue, value);
+            } else {
+                cJSON_AddNumberToObject(*root, key, value);
+            }
+        }
+        wifi_manager_unlock_json_buffer();
+    } else {
+        ESP_LOGW(TAG, "Unable to lock status json buffer. ");
+    }
+    return *root;
+}
+cJSON* network_status_update_float(cJSON** root, const char* key, float value) {
+    if (wifi_manager_lock_json_buffer(portMAX_DELAY)) {
+        if (*root == NULL) {
+            *root = cJSON_CreateObject();
+        }
+
+        if (key && strlen(key) != 0) {
+            cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
+            if (cjsonvalue) {
+                cJSON_SetNumberValue(cjsonvalue, value);
+            } else {
+                cJSON_AddNumberToObject(*root, key, value);
+            }
+        }
+        wifi_manager_unlock_json_buffer();
+    } else {
+        ESP_LOGW(TAG, "Unable to lock status json buffer. ");
+    }
+    return *root;
+}
+cJSON* network_status_update_bool(cJSON** root, const char* key, bool value) {
+    if (wifi_manager_lock_json_buffer(portMAX_DELAY)) {
+        if (*root == NULL) {
+            *root = cJSON_CreateObject();
+        }
+
+        if (key && strlen(key) != 0) {
+            cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
+            if (cjsonvalue) {
+                cjsonvalue->type = value ? cJSON_True : cJSON_False;
+            } else {
+                cJSON_AddBoolToObject(*root, key, value);
+            }
+        }
+        wifi_manager_unlock_json_buffer();
+    } else {
+        ESP_LOGW(TAG, "Unable to lock status json buffer. ");
+    }
+    return *root;
+}
+cJSON* wifi_manager_get_basic_info(cJSON** old) {
+    int32_t total_connected_time = 0;
+    int64_t last_connected = 0;
+    uint16_t num_disconnect = 0;
+    network_wifi_get_stats(&total_connected_time, &last_connected, &num_disconnect);
+
+    monitor_gpio_t* mgpio = get_jack_insertion_gpio();
+    const esp_app_desc_t* desc = esp_ota_get_app_description();
+    ESP_LOGV(TAG, "wifi_manager_get_basic_info called");
+    cJSON* root = network_status_update_string(&root, "project_name", desc->project_name);
+#ifdef CONFIG_FW_PLATFORM_NAME
+    root = network_status_update_string(&root, "platform_name", CONFIG_FW_PLATFORM_NAME);
+#endif
+    root = network_status_update_string(&root, "version", desc->version);
+    if (release_url != NULL)
+        root = network_status_update_string(&root, "release_url", release_url);
+    root = network_status_update_number(&root, "recovery", is_recovery_running ? 1 : 0);
+    root = network_status_update_bool(&root, "Jack", mgpio->gpio >= 0 && jack_inserted_svc());
+    root = network_status_update_float(&root, "Voltage", battery_value_svc());
+    root = network_status_update_number(&root, "disconnect_count", num_disconnect);
+    root = network_status_update_float(&root, "avg_conn_time", num_disconnect > 0 ? (total_connected_time / num_disconnect) : 0);
+    root = network_status_update_number(&root, "bt_status", bt_app_source_get_a2d_state());
+    root = network_status_update_number(&root, "bt_sub_status", bt_app_source_get_media_state());
+
+#if CONFIG_I2C_LOCKED
+    root = network_status_update_bool(&root, "is_i2c_locked", true);
+#else
+    root = network_status_update_bool(&root, "is_i2c_locked", false);
+#endif
+    if (network_ethernet_enabled()) {
+        root = network_status_update_bool(&root, "eth_up", network_ethernet_is_up());
+    }
+    ESP_LOGV(TAG, "wifi_manager_get_basic_info done");
+    return root;
+}
+
+void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code) {
+    ESP_LOGD(TAG, "wifi_manager_generate_ip_info_json called");
+
+    if (wifi_manager_lock_json_buffer(portMAX_DELAY)) {
+        /* generate the connection info with success */
+
+        ip_info_cjson = wifi_manager_get_basic_info(&ip_info_cjson);
+        wifi_manager_unlock_json_buffer();
+    } else {
+        ESP_LOGW(TAG, "Unable to lock status json buffer. ");
+    }
+    ip_info_cjson = network_status_update_number(&ip_info_cjson, "urc", update_reason_code);
+    if (update_reason_code == UPDATE_CONNECTION_OK || update_reason_code == UPDATE_ETHERNET_CONNECTED) {
+        /* rest of the information is copied after the ssid */
+        tcpip_adapter_ip_info_t ip_info;
+        esp_netif_get_ip_info(network_wifi_get_interface(), &ip_info);
+
+        network_status_update_string(&ip_info_cjson, "ip", ip4addr_ntoa((ip4_addr_t*)&ip_info.ip));
+        network_status_update_string(&ip_info_cjson, "netmask", ip4addr_ntoa((ip4_addr_t*)&ip_info.netmask));
+        network_status_update_string(&ip_info_cjson, "gw", ip4addr_ntoa((ip4_addr_t*)&ip_info.gw));
+        wifi_mode_t mode;
+        if (esp_wifi_get_mode(&mode) == ESP_OK && (mode == WIFI_MODE_STA || mode == WIFI_MODE_APSTA)) {
+            /* wifi is active, and associated to an AP */
+            wifi_ap_record_t ap;
+            esp_wifi_sta_get_ap_info(&ap);
+            network_status_update_string(&ip_info_cjson, "ssid", ((char*)ap.ssid));
+            network_status_update_number(&ip_info_cjson, "rssi", ap.rssi);
+        }
+        if (network_ethernet_is_up()) {
+            esp_netif_get_ip_info(network_ethernet_get_interface(), &ip_info);
+            cJSON* ethernet_ip = cJSON_CreateObject();
+            cJSON_AddItemToObject(ethernet_ip, "ip", cJSON_CreateString(ip4addr_ntoa((ip4_addr_t*)&ip_info.ip)));
+            cJSON_AddItemToObject(ethernet_ip, "netmask", cJSON_CreateString(ip4addr_ntoa((ip4_addr_t*)&ip_info.netmask)));
+            cJSON_AddItemToObject(ethernet_ip, "gw", cJSON_CreateString(ip4addr_ntoa((ip4_addr_t*)&ip_info.gw)));
+            cJSON_AddItemToObject(ip_info_cjson, "eth", ethernet_ip);
+        }
+    } else {
+        cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "ip");
+        cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "netmask");
+        cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "gw");
+        cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "rssi");
+        cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "ssid");
+        cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "eth");
+    }
+    ESP_LOGV(TAG, "wifi_manager_generate_ip_info_json done");
+}

+ 59 - 0
components/wifi-manager/network_status.h

@@ -0,0 +1,59 @@
+#pragma once
+#include "network_manager.h"
+#include "cJSON.h"
+#ifdef __cplusplus
+extern "C" {
+
+#endif
+char* wifi_manager_alloc_get_ip_info_json();
+/**
+ * @brief Tries to get access to json buffer mutex.
+ *
+ * The HTTP server can try to access the json to serve clients while the wifi manager thread can try
+ * to update it. These two tasks are synchronized through a mutex.
+ *
+ * The mutex is used by both the access point list json and the connection status json.\n
+ * These two resources should technically have their own mutex but we lose some flexibility to save
+ * on memory.
+ *
+ * This is a simple wrapper around freeRTOS function xSemaphoreTake.
+ *
+ * @param xTicksToWait The time in ticks to wait for the semaphore to become available.
+ * @return true in success, false otherwise.
+ */
+bool wifi_manager_lock_json_buffer(TickType_t xTicksToWait);
+
+/**
+ * @brief Releases the json buffer mutex.
+ */
+void wifi_manager_unlock_json_buffer();
+
+bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait);
+void wifi_manager_unlock_sta_ip_string();
+
+/**
+ * @brief gets the string representation of the STA IP address, e.g.: "192.168.1.69"
+ */
+char* wifi_manager_get_sta_ip_string();
+
+/**
+ * @brief thread safe char representation of the STA IP update
+ */
+void wifi_manager_safe_update_sta_ip_string(esp_ip4_addr_t * ip4);
+
+/**
+ * @brief Generates the connection status json: ssid and IP addresses.
+ * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful.
+ */
+void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code);
+
+void init_network_status();
+void destroy_network_status();
+cJSON* wifi_manager_get_basic_info(cJSON** old);
+
+void wifi_manager_update_basic_info();
+void network_status_clear_ip();
+void wifi_manager_safe_reset_sta_ip_string();
+#ifdef __cplusplus
+}
+#endif

+ 990 - 0
components/wifi-manager/network_wifi.c

@@ -0,0 +1,990 @@
+#include "network_wifi.h"
+#include <string.h>
+#include "cJSON.h"
+#include "dns_server.h"
+#include "esp_event.h"
+#include "esp_log.h"
+#include "esp_system.h"
+#include "esp_wifi.h"
+#include "esp_wifi_types.h"
+#include "globdefs.h"
+#include "lwip/sockets.h"
+#include "messaging.h"
+#include "network_status.h"
+#include "nvs.h"
+#include "nvs_flash.h"
+#include "platform_config.h"
+#include "platform_esp32.h"
+#include "tools.h"
+#include "trace.h"
+
+static void network_wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
+static void network_manager_wifi_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) ;
+static char* get_disconnect_code_desc(uint8_t reason);
+
+cJSON* accessp_cjson = NULL;
+wifi_config_t* wifi_manager_config_sta = NULL;
+static const char TAG[] = "network_wifi";
+const char wifi_manager_nvs_namespace[] = "config";
+
+uint16_t ap_num = MAX_AP_NUM;
+
+
+
+
+esp_netif_t *wifi_netif;
+
+wifi_ap_record_t* accessp_records = NULL;
+/* wifi scanner config */
+wifi_scan_config_t scan_config = {
+    .ssid = 0,
+    .bssid = 0,
+    .channel = 0,
+    .show_hidden = true};
+#ifndef STR_OR_BLANK
+#define STR_OR_BLANK(p) p == NULL ? "" : p
+#endif
+
+esp_netif_t *network_wifi_get_interface(){
+    return wifi_netif;
+}
+
+void init_network_wifi() {
+    ESP_LOGD(TAG, "WIFI Starting.");
+    accessp_cjson = NULL;
+    accessp_cjson = wifi_manager_clear_ap_list_json(&accessp_cjson);
+    wifi_manager_config_sta = (wifi_config_t*)malloc(sizeof(wifi_config_t));
+    memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t));
+    ESP_LOGD(TAG, "Init. ");
+    wifi_netif = esp_netif_create_default_wifi_sta();
+    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
+    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
+    ESP_LOGD(TAG, "Handlers");
+    //wifi_manager_register_handlers();
+    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
+                                                        ESP_EVENT_ANY_ID,
+                                                        &network_wifi_event_handler,
+                                                        NULL,
+                                                        NULL));
+    esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &network_manager_wifi_ip_event_handler, NULL);
+    ESP_LOGD(TAG, "Storage");
+    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
+    ESP_LOGD(TAG, "Set Mode");
+    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
+    ESP_LOGD(TAG, "Start");
+    ESP_ERROR_CHECK(esp_wifi_start());
+}
+void destroy_network_wifi() {
+    cJSON_Delete(accessp_cjson);
+    accessp_cjson = NULL;
+    FREE_AND_NULL(wifi_manager_config_sta);
+}
+bool network_wifi_sta_config_changed()  {
+    bool changed = true;
+    wifi_config_t wifi_manager_config_sta_existing;
+    if(wifi_manager_config_sta && wifi_manager_load_wifi_sta_config(&wifi_manager_config_sta_existing )){
+        changed = strcmp( (char *)wifi_manager_config_sta_existing.sta.ssid,(char *)wifi_manager_config_sta->sta.ssid ) !=0 ||
+                    strcmp((char *) wifi_manager_config_sta_existing.sta.password,(char *)wifi_manager_config_sta->sta.password ) !=0;
+    }
+    return changed;
+    
+}
+
+esp_err_t network_wifi_save_sta_config() {
+    nvs_handle handle;
+    esp_err_t esp_err;
+    ESP_LOGD(TAG, "Config Save");
+
+    if (wifi_manager_config_sta) {
+        esp_err = nvs_open(wifi_manager_nvs_namespace, NVS_READWRITE, &handle);
+        if (esp_err != ESP_OK) {
+            ESP_LOGE(TAG, "%s failure. Error %s", wifi_manager_nvs_namespace, esp_err_to_name(esp_err));
+            return esp_err;
+        }
+
+        esp_err = nvs_set_blob(handle, "ssid", wifi_manager_config_sta->sta.ssid, sizeof(wifi_manager_config_sta->sta.ssid));
+        if (esp_err != ESP_OK) {
+            ESP_LOGE(TAG, "ssid (%s). Error %s", wifi_manager_nvs_namespace, esp_err_to_name(esp_err));
+            return esp_err;
+        }
+
+        esp_err = nvs_set_blob(handle, "password", wifi_manager_config_sta->sta.password, sizeof(wifi_manager_config_sta->sta.password));
+        if (esp_err != ESP_OK) {
+            ESP_LOGE(TAG, "pass (%s). Error %s", wifi_manager_nvs_namespace, esp_err_to_name(esp_err));
+            return esp_err;
+        }
+
+        esp_err = nvs_commit(handle);
+        if (esp_err != ESP_OK) {
+            ESP_LOGE(TAG, "Commit error: %s", esp_err_to_name(esp_err));
+            messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Unable to save wifi credentials. %s", esp_err_to_name(esp_err));
+            return esp_err;
+        }
+        nvs_close(handle);
+
+        ESP_LOGD(TAG, "saved: ssid:%s password:%s", wifi_manager_config_sta->sta.ssid, wifi_manager_config_sta->sta.password);
+    }
+
+    return ESP_OK;
+}
+bool wifi_manager_load_wifi_sta_config(wifi_config_t* config ){
+    nvs_handle handle;
+    esp_err_t esp_err;
+
+    ESP_LOGD(TAG, "Fetching wifi sta config.");
+    esp_err = nvs_open(wifi_manager_nvs_namespace, NVS_READONLY, &handle);
+    if (esp_err == ESP_OK) {
+
+
+        /* ssid */
+        ESP_LOGD(TAG, "Fetching value for ssid.");
+        size_t sz = sizeof(config->sta.ssid);
+        uint8_t* buff = (uint8_t*)malloc(sizeof(uint8_t) * sz);
+        memset(buff, 0x00, sizeof(uint8_t) * sz);
+        esp_err = nvs_get_blob(handle, "ssid", buff, &sz);
+        if (esp_err != ESP_OK) {
+            ESP_LOGD(TAG, "No ssid found in nvs.");
+            FREE_AND_NULL(buff);
+            nvs_close(handle);
+            return false;
+        }
+        memcpy(config->sta.ssid, buff, sizeof(config->sta.ssid));
+        FREE_AND_NULL(buff);
+        ESP_LOGD(TAG, "wifi_manager_fetch_wifi_sta_config: ssid:%s ", config->sta.ssid);
+
+        /* password */
+        sz = sizeof(config->sta.password);
+        buff = (uint8_t*)malloc(sizeof(uint8_t) * sz);
+        memset(buff, 0x00, sizeof(uint8_t) * sz);
+        esp_err = nvs_get_blob(handle, "password", buff, &sz);
+        if (esp_err != ESP_OK) {
+            // Don't take this as an error. This could be an opened access point?
+            ESP_LOGW(TAG, "No wifi password found in nvs");
+        } else {
+            memcpy(config->sta.password, buff, sizeof(config->sta.password));
+            ESP_LOGD(TAG, "wifi_manager_fetch_wifi_sta_config: password:%s", config->sta.password);
+        }
+        FREE_AND_NULL(buff);
+        nvs_close(handle);
+        config->sta.scan_method = WIFI_ALL_CHANNEL_SCAN;
+        return config->sta.ssid[0] != '\0';
+    } else {
+        ESP_LOGW(TAG, "wifi manager has no previous configuration. %s", esp_err_to_name(esp_err));
+        return false;
+    }
+}
+
+bool wifi_manager_fetch_wifi_sta_config() {
+    if (wifi_manager_config_sta == NULL) {
+        ESP_LOGD(TAG, "Allocating memory for structure.");
+        wifi_manager_config_sta = (wifi_config_t*)malloc(sizeof(wifi_config_t));
+    }
+    memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t));
+    return wifi_manager_load_wifi_sta_config(wifi_manager_config_sta);
+}
+
+wifi_config_t* wifi_manager_get_wifi_sta_config() {
+    return wifi_manager_config_sta;
+}
+// void wifi_manager_register_handlers() {
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_WIFI_READY, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_SCAN_DONE, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_AUTHMODE_CHANGE, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_START, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_STOP, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_PROBEREQRECVED, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_SUCCESS, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_FAILED, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_TIMEOUT, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_PIN, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_STACONNECTED, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_STADISCONNECTED, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_START, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_STOP, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &network_wifi_event_handler, NULL));
+//     ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &network_wifi_event_handler, NULL));
+// }
+#define LOCAL_MAC_SIZE 20
+char* get_mac_string(uint8_t mac[6]) {
+    char* macStr = malloc(LOCAL_MAC_SIZE);
+    memset(macStr, 0x00, LOCAL_MAC_SIZE);
+    snprintf(macStr, LOCAL_MAC_SIZE, MACSTR, MAC2STR(mac));
+    return macStr;
+}
+static void network_wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
+    if (event_base != WIFI_EVENT)
+        return;
+    switch (event_id) {
+        case WIFI_EVENT_WIFI_READY:
+            ESP_LOGD(TAG, "WIFI_EVENT_WIFI_READY");
+            break;
+
+        case WIFI_EVENT_SCAN_DONE:
+            ESP_LOGD(TAG, "WIFI_EVENT_SCAN_DONE");
+            network_manager_async_scan_done();
+            break;
+
+        case WIFI_EVENT_STA_AUTHMODE_CHANGE:
+            ESP_LOGD(TAG, "WIFI_EVENT_STA_AUTHMODE_CHANGE");
+            break;
+
+        case WIFI_EVENT_AP_START:
+            ESP_LOGD(TAG, "WIFI_EVENT_AP_START");
+            break;
+
+        case WIFI_EVENT_AP_STOP:
+            ESP_LOGD(TAG, "WIFI_EVENT_AP_STOP");
+            break;
+
+        case WIFI_EVENT_AP_PROBEREQRECVED: {
+            //		        	wifi_event_ap_probe_req_rx_t
+            //		        	Argument structure for WIFI_EVENT_AP_PROBEREQRECVED event
+            //
+            //		        	Public Members
+            //
+            //		        	int rssi
+            //		        	Received probe request signal strength
+            //
+            //		        	uint8_t mac[6]
+            //		        	MAC address of the station which send probe request
+
+            wifi_event_ap_probe_req_rx_t* s = (wifi_event_ap_probe_req_rx_t*)event_data;
+            char* mac = get_mac_string(s->mac);
+            ESP_LOGD(TAG, "WIFI_EVENT_AP_PROBEREQRECVED. RSSI: %d, MAC: %s", s->rssi, STR_OR_BLANK(mac));
+            FREE_AND_NULL(mac);
+        } break;
+        case WIFI_EVENT_STA_WPS_ER_SUCCESS:
+            ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_SUCCESS");
+            break;
+        case WIFI_EVENT_STA_WPS_ER_FAILED:
+            ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_FAILED");
+            break;
+        case WIFI_EVENT_STA_WPS_ER_TIMEOUT:
+            ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_TIMEOUT");
+            break;
+        case WIFI_EVENT_STA_WPS_ER_PIN:
+            ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_PIN");
+            break;
+        case WIFI_EVENT_AP_STACONNECTED: {
+            wifi_event_ap_staconnected_t* stac = (wifi_event_ap_staconnected_t*)event_data;
+            char* mac = get_mac_string(stac->mac);
+            ESP_LOGD(TAG, "WIFI_EVENT_AP_STACONNECTED. aid: %d, mac: %s", stac->aid, STR_OR_BLANK(mac));
+            FREE_AND_NULL(mac);
+        } break;
+        case WIFI_EVENT_AP_STADISCONNECTED:
+            ESP_LOGD(TAG, "WIFI_EVENT_AP_STADISCONNECTED");
+            break;
+
+        case WIFI_EVENT_STA_START:
+            ESP_LOGD(TAG, "WIFI_EVENT_STA_START");
+            break;
+
+        case WIFI_EVENT_STA_STOP:
+            ESP_LOGD(TAG, "WIFI_EVENT_STA_STOP");
+            break;
+
+        case WIFI_EVENT_STA_CONNECTED: {
+            //		    		structwifi_event_sta_connected_t
+            //		    		Argument structure for WIFI_EVENT_STA_CONNECTED event
+            //
+            //		    		Public Members
+            //
+            //		    		uint8_t ssid[32]
+            //		    		SSID of connected AP
+            //
+            //		    		uint8_t ssid_len
+            //		    		SSID length of connected AP
+            //
+            //		    		uint8_t bssid[6]
+            //		    		BSSID of connected AP
+            //
+            //		    		uint8_t channel
+            //		    		channel of connected AP
+            //
+            //		    		wifi_auth_mode_tauthmode
+            //		    		authentication mode used by AP
+            //, get_mac_string(EVENT_HANDLER_ARG_FIELD(wifi_event_ap_probe_req_rx_t, mac)));
+
+            ESP_LOGD(TAG, "WIFI_EVENT_STA_CONNECTED. ");
+            wifi_event_sta_connected_t* s = (wifi_event_sta_connected_t*)event_data;
+            char* bssid = get_mac_string(s->bssid);
+            char* ssid = strdup((char*)s->ssid);
+            ESP_LOGD(TAG, "WIFI_EVENT_STA_CONNECTED. Channel: %d, Access point: %s, BSSID: %s ", s->channel, STR_OR_BLANK(ssid), (bssid));
+            FREE_AND_NULL(bssid);
+            FREE_AND_NULL(ssid);
+            network_manager_async_success();
+
+        } break;
+
+        case WIFI_EVENT_STA_DISCONNECTED: {
+            //		    		structwifi_event_sta_disconnected_t
+            //		    		Argument structure for WIFI_EVENT_STA_DISCONNECTED event
+            //
+            //		    		Public Members
+            //
+            //		    		uint8_t ssid[32]
+            //		    		SSID of disconnected AP
+            //
+            //		    		uint8_t ssid_len
+            //		    		SSID length of disconnected AP
+            //
+            //		    		uint8_t bssid[6]
+            //		    		BSSID of disconnected AP
+            //
+            //		    		uint8_t reason
+            //		    		reason of disconnection
+            wifi_event_sta_disconnected_t* s = (wifi_event_sta_disconnected_t*)event_data;
+            char* bssid = get_mac_string(s->bssid);
+            ESP_LOGD(TAG, "WIFI_EVENT_STA_DISCONNECTED. From BSSID: %s, reason code: %d (%s)", STR_OR_BLANK(bssid), s->reason, get_disconnect_code_desc(s->reason));
+            FREE_AND_NULL(bssid);
+
+                
+            /* if a DISCONNECT message is posted while a scan is in progress this scan will NEVER end, causing scan to never work again. For this reason SCAN_BIT is cleared too */
+            // todo: check for implementation of this: network_manager_clear_flag(WIFI_MANAGER_WIFI_CONNECTED_BIT | WIFI_MANAGER_SCAN_BIT);
+            wifi_event_sta_disconnected_t * disconnected_event = malloc(sizeof(wifi_event_sta_disconnected_t));
+            memcpy(disconnected_event, event_data, sizeof(wifi_event_sta_disconnected_t));
+            network_manager_async_lost_connection(disconnected_event);
+        } break;
+
+        default:
+            break;
+    }
+}
+
+
+cJSON* wifi_manager_get_new_array_json(cJSON** old) {
+    ESP_LOGV(TAG, "wifi_manager_get_new_array_json called");
+    cJSON* root = *old;
+    if (root != NULL) {
+        cJSON_Delete(root);
+        *old = NULL;
+    }
+    ESP_LOGV(TAG, "wifi_manager_get_new_array_json done");
+    return cJSON_CreateArray();
+}
+void wifi_manager_generate_access_points_json(cJSON** ap_list) {
+    *ap_list = wifi_manager_get_new_array_json(ap_list);
+
+    if (*ap_list == NULL)
+        return;
+    for (int i = 0; i < ap_num; i++) {
+        cJSON* ap = cJSON_CreateObject();
+        if (ap == NULL) {
+            ESP_LOGE(TAG, "Unable to allocate memory for access point entry #%d", i);
+            return;
+        }
+        cJSON* radio = cJSON_CreateObject();
+        if (radio == NULL) {
+            ESP_LOGE(TAG, "Unable to allocate memory for access point entry #%d", i);
+            cJSON_Delete(ap);
+            return;
+        }
+        wifi_ap_record_t ap_rec = accessp_records[i];
+        cJSON_AddNumberToObject(ap, "chan", ap_rec.primary);
+        cJSON_AddNumberToObject(ap, "rssi", ap_rec.rssi);
+        cJSON_AddNumberToObject(ap, "auth", ap_rec.authmode);
+        cJSON_AddItemToObject(ap, "ssid", cJSON_CreateString((char*)ap_rec.ssid));
+
+        char* bssid = get_mac_string(ap_rec.bssid);
+        cJSON_AddItemToObject(ap, "bssid", cJSON_CreateString(STR_OR_BLANK(bssid)));
+        FREE_AND_NULL(bssid);
+        cJSON_AddNumberToObject(radio, "b", ap_rec.phy_11b ? 1 : 0);
+        cJSON_AddNumberToObject(radio, "g", ap_rec.phy_11g ? 1 : 0);
+        cJSON_AddNumberToObject(radio, "n", ap_rec.phy_11n ? 1 : 0);
+        cJSON_AddNumberToObject(radio, "low_rate", ap_rec.phy_lr ? 1 : 0);
+        cJSON_AddItemToObject(ap, "radio", radio);
+        cJSON_AddItemToArray(*ap_list, ap);
+        char* ap_json = cJSON_PrintUnformatted(ap);
+        if (ap_json != NULL) {
+            ESP_LOGD(TAG, "New access point found: %s", ap_json);
+            free(ap_json);
+        }
+    }
+    char* ap_list_json = cJSON_PrintUnformatted(*ap_list);
+    if (ap_list_json != NULL) {
+        ESP_LOGV(TAG, "Full access point list: %s", ap_list_json);
+        free(ap_list_json);
+    }
+}
+void wifi_manager_set_ipv4val(const char* key, char* default_value, ip4_addr_t * target) {
+    char* value = config_alloc_get_default(NVS_TYPE_STR, key, default_value, 0);
+    if (value != NULL) {
+        ESP_LOGD(TAG, "%s: %s", key, value);
+        inet_pton(AF_INET, value, target); /* access point is on a static IP */
+    }
+    FREE_AND_NULL(value);
+}
+void wifi_manager_config_ap() {
+    tcpip_adapter_ip_info_t info;
+    esp_err_t err = ESP_OK;
+    char* value = NULL;
+    wifi_config_t ap_config = {
+        .ap = {
+            .ssid_len = 0,
+        },
+    };
+    ESP_LOGI(TAG, "Configuring Access Point.");
+    wifi_netif = esp_netif_create_default_wifi_ap();
+
+    /* In order to change the IP info structure, we have to first stop 
+     * the DHCP server on the new interface 
+    */
+    esp_netif_dhcps_stop(wifi_netif);
+
+    // tcpip_adapter_dhcps_get_status(TCPIP_ADAPTER_IF_AP, &dhcp_status);
+    // if (dhcp_status == TCPIP_ADAPTER_DHCP_STARTED) {
+    //     ESP_LOGD(TAG, "Stopping DHCP on interface so we can ");
+    //     if ((err = tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP)) != ESP_OK) /* stop AP DHCP server */
+    //     {
+    //         ESP_LOGW(TAG, "Stopping DHCP failed. Error %s", esp_err_to_name(err));
+    //     }
+    // }
+    /*
+    * Set access point mode IP adapter configuration
+    */
+
+    wifi_manager_set_ipv4val("ap_ip_address", DEFAULT_AP_IP, &info.ip);
+    wifi_manager_set_ipv4val("ap_ip_gateway", CONFIG_DEFAULT_AP_GATEWAY, &info.gw);
+    wifi_manager_set_ipv4val("ap_ip_netmask", CONFIG_DEFAULT_AP_NETMASK, &info.netmask);
+    ESP_LOGD(TAG, "Setting tcp_ip info for interface TCPIP_ADAPTER_IF_AP");
+    if ((err = esp_netif_set_ip_info(wifi_netif, &info)) != ESP_OK) {
+        ESP_LOGE(TAG, "Setting tcp_ip info for interface TCPIP_ADAPTER_IF_AP. Error %s", esp_err_to_name(err));
+        return;
+    }
+    /*
+		 * Set Access Point configuration
+		 */
+    value = config_alloc_get_default(NVS_TYPE_STR, "ap_ssid", CONFIG_DEFAULT_AP_SSID, 0);
+    if (value != NULL) {
+        strlcpy((char*)ap_config.ap.ssid, value, sizeof(ap_config.ap.ssid));
+        ESP_LOGI(TAG, "AP SSID: %s", (char*)ap_config.ap.ssid);
+    }
+    FREE_AND_NULL(value);
+
+    value = config_alloc_get_default(NVS_TYPE_STR, "ap_pwd", DEFAULT_AP_PASSWORD, 0);
+    if (value != NULL) {
+        strlcpy((char*)ap_config.ap.password, value, sizeof(ap_config.ap.password));
+        ESP_LOGI(TAG, "AP Password: %s", (char*)ap_config.ap.password);
+    }
+    FREE_AND_NULL(value);
+
+    value = config_alloc_get_default(NVS_TYPE_STR, "ap_channel", STR(CONFIG_DEFAULT_AP_CHANNEL), 0);
+    if (value != NULL) {
+        ESP_LOGD(TAG, "Channel: %s", value);
+        ap_config.ap.channel = atoi(value);
+    }
+    FREE_AND_NULL(value);
+
+    ap_config.ap.authmode = AP_AUTHMODE;
+    ap_config.ap.ssid_hidden = DEFAULT_AP_SSID_HIDDEN;
+    ap_config.ap.max_connection = DEFAULT_AP_MAX_CONNECTIONS;
+    ap_config.ap.beacon_interval = DEFAULT_AP_BEACON_INTERVAL;
+
+    ESP_LOGD(TAG, "Auth Mode: %d", ap_config.ap.authmode);
+    ESP_LOGD(TAG, "SSID Hidden: %d", ap_config.ap.ssid_hidden);
+    ESP_LOGD(TAG, "Max Connections: %d", ap_config.ap.max_connection);
+    ESP_LOGD(TAG, "Beacon interval: %d", ap_config.ap.beacon_interval);
+
+    const char* msg = "Setting wifi mode as WIFI_MODE_APSTA";
+    ESP_LOGD(TAG, "%s",msg);
+    if ((err = esp_wifi_set_mode(WIFI_MODE_APSTA)) != ESP_OK) {
+        ESP_LOGE(TAG, "%s. Error %s",msg, esp_err_to_name(err));
+        return;
+    }
+    msg = "Setting wifi AP configuration for WIFI_IF_AP";
+    ESP_LOGD(TAG, "%s", msg);
+    if ((err = esp_wifi_set_config(WIFI_IF_AP, &ap_config)) != ESP_OK) /* stop AP DHCP server */
+    {
+        ESP_LOGE(TAG, "%s . Error %s", msg, esp_err_to_name(err));
+        return;
+    }
+
+    msg = "Setting wifi bandwidth";
+    ESP_LOGD(TAG, "%s (%d)", msg, DEFAULT_AP_BANDWIDTH);
+    if ((err = esp_wifi_set_bandwidth(WIFI_IF_AP, DEFAULT_AP_BANDWIDTH)) != ESP_OK) /* stop AP DHCP server */
+    {
+        ESP_LOGE(TAG, "%s failed. Error %s", msg, esp_err_to_name(err));
+        return;
+    }
+
+    msg = "Setting wifi power save";
+    ESP_LOGD(TAG, "%s (%d)", msg, DEFAULT_STA_POWER_SAVE);
+
+    if ((err = esp_wifi_set_ps(DEFAULT_STA_POWER_SAVE)) != ESP_OK) /* stop AP DHCP server */
+    {
+        ESP_LOGE(TAG, "%s failed. Error %s", msg, esp_err_to_name(err));
+        return;
+    }
+    esp_netif_dhcps_start(wifi_netif);
+    ESP_LOGD(TAG, "Done configuring Soft Access Point");
+    dns_server_start();
+}
+
+void wifi_manager_filter_unique(wifi_ap_record_t* aplist, uint16_t* aps) {
+    int total_unique;
+    wifi_ap_record_t* first_free;
+    total_unique = *aps;
+
+    first_free = NULL;
+
+    for (int i = 0; i < *aps - 1; i++) {
+        wifi_ap_record_t* ap = &aplist[i];
+
+        /* skip the previously removed APs */
+        if (ap->ssid[0] == 0)
+            continue;
+
+        /* remove the identical SSID+authmodes */
+        for (int j = i + 1; j < *aps; j++) {
+            wifi_ap_record_t* ap1 = &aplist[j];
+            if ((strcmp((const char*)ap->ssid, (const char*)ap1->ssid) == 0) &&
+                (ap->authmode == ap1->authmode)) { /* same SSID, different auth mode is skipped */
+                /* save the rssi for the display */
+                if ((ap1->rssi) > (ap->rssi))
+                    ap->rssi = ap1->rssi;
+                /* clearing the record */
+                memset(ap1, 0, sizeof(wifi_ap_record_t));
+            }
+        }
+    }
+    /* reorder the list so APs follow each other in the list */
+    for (int i = 0; i < *aps; i++) {
+        wifi_ap_record_t* ap = &aplist[i];
+        /* skipping all that has no name */
+        if (ap->ssid[0] == 0) {
+            /* mark the first free slot */
+            if (first_free == NULL)
+                first_free = ap;
+            total_unique--;
+            continue;
+        }
+        if (first_free != NULL) {
+            memcpy(first_free, ap, sizeof(wifi_ap_record_t));
+            memset(ap, 0, sizeof(wifi_ap_record_t));
+            /* find the next free slot */
+            for (int j = 0; j < *aps; j++) {
+                if (aplist[j].ssid[0] == 0) {
+                    first_free = &aplist[j];
+                    break;
+                }
+            }
+        }
+    }
+    /* update the length of the list */
+    *aps = total_unique;
+}
+
+char* wifi_manager_alloc_get_ap_list_json() {
+    return cJSON_PrintUnformatted(accessp_cjson);
+}
+cJSON* wifi_manager_clear_ap_list_json(cJSON** old) {
+    ESP_LOGV(TAG, "wifi_manager_clear_ap_list_json called");
+    cJSON* root = wifi_manager_get_new_array_json(old);
+    ESP_LOGV(TAG, "wifi_manager_clear_ap_list_json done");
+    return root;
+}
+esp_err_t wifi_scan_done(queue_message* msg) {
+    esp_err_t err = ESP_OK;
+    /* As input param, it stores max AP number ap_records can hold. As output param, it receives the actual AP number this API returns.
+				 * As a consequence, ap_num MUST be reset to MAX_AP_NUM at every scan */
+    ESP_LOGD(TAG, "Getting AP list records");
+    if ((err = esp_wifi_scan_get_ap_num(&ap_num)) != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to retrieve scan results count. Error %s", esp_err_to_name(err));
+        return err;
+    }
+
+    if (ap_num > 0) {
+        accessp_records = (wifi_ap_record_t*)malloc(sizeof(wifi_ap_record_t) * ap_num);
+        if ((err = esp_wifi_scan_get_ap_records(&ap_num, accessp_records)) != ESP_OK) {
+            ESP_LOGE(TAG, "Failed to retrieve scan results list. Error %s", esp_err_to_name(err));
+            return err;
+        }
+        /* make sure the http server isn't trying to access the list while it gets refreshed */
+        ESP_LOGD(TAG, "Preparing to build ap JSON list");
+        if (wifi_manager_lock_json_buffer(pdMS_TO_TICKS(1000))) {
+            /* Will remove the duplicate SSIDs from the list and update ap_num */
+            wifi_manager_filter_unique(accessp_records, &ap_num);
+            wifi_manager_generate_access_points_json(&accessp_cjson);
+            wifi_manager_unlock_json_buffer();
+            ESP_LOGD(TAG, "Done building ap JSON list");
+
+        } else {
+            ESP_LOGE(TAG, "could not get access to json mutex in wifi_scan");
+            err = ESP_FAIL;
+        }
+        free(accessp_records);
+    } else {
+        //
+        ESP_LOGD(TAG, "No AP Found.  Emptying the list.");
+        accessp_cjson = wifi_manager_get_new_array_json(&accessp_cjson);
+    }
+    return err;
+}
+bool is_wifi_up(){
+    return wifi_netif!=NULL;
+}
+esp_err_t network_wifi_start_scan(queue_message* msg) {
+    esp_err_t err = ESP_OK;
+    ESP_LOGD(TAG, "MESSAGE: ORDER_START_WIFI_SCAN");
+    if(!is_wifi_up()) {
+        messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi not started. Cannot scan");
+        return ESP_FAIL;
+    }
+    /* if a scan is already in progress this message is simply ignored thanks to the WIFI_MANAGER_SCAN_BIT uxBit */
+    if (!network_manager_is_flag_set(WIFI_MANAGER_SCAN_BIT)) {
+        if ((err = esp_wifi_scan_start(&scan_config, false)) != ESP_OK) {
+            ESP_LOGW(TAG, "Unable to start scan; %s ", esp_err_to_name(err));
+            //						set_status_message(WARNING, "Wifi Connecting. Cannot start scan.");
+            messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Scanning failed: %s", esp_err_to_name(err));
+        } else {
+            network_manager_set_flag(WIFI_MANAGER_SCAN_BIT);
+        }
+    } else {
+        ESP_LOGW(TAG, "Scan already in progress!");
+    }
+
+    return err;
+}
+static void polling_STA(void* timer_id) {
+    network_manager_async_connect(wifi_manager_get_wifi_sta_config());
+}
+
+void set_host_name() {
+    esp_err_t err;
+    ESP_LOGD(TAG, "Retrieving host name from nvs");
+    char* host_name = (char*)config_alloc_get(NVS_TYPE_STR, "host_name");
+    if (host_name == NULL) {
+        ESP_LOGE(TAG, "Could not retrieve host name from nvs");
+    } else {
+        ESP_LOGD(TAG, "Setting host name to : %s", host_name);
+        if ((err = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, host_name)) != ESP_OK) {
+            ESP_LOGE(TAG, "Unable to set host name. Error: %s", esp_err_to_name(err));
+        }
+        //		if((err=tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_AP, host_name)) !=ESP_OK){
+        //			ESP_LOGE(TAG,  "Unable to set host name. Error: %s",esp_err_to_name(err));
+        //		}
+        free(host_name);
+    }
+}
+
+esp_err_t network_wifi_connect(wifi_config_t * cfg){
+    esp_err_t err = ESP_OK;
+    ESP_LOGD(TAG, "network_wifi_connect");
+    if(!is_wifi_up()) {
+        messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi not started. Cannot connect");
+        return ESP_FAIL;
+    }    
+    tcpip_adapter_dhcp_status_t status;
+    ESP_LOGD(TAG, "wifi_manager: Checking if DHCP client for STA interface is running");
+    ESP_ERROR_CHECK_WITHOUT_ABORT(tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &status));
+    if (status != TCPIP_ADAPTER_DHCP_STARTED) {
+        ESP_LOGD(TAG, "wifi_manager: Start DHCP client for STA interface");
+        ESP_ERROR_CHECK_WITHOUT_ABORT(tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA));
+    }
+    wifi_mode_t mode;
+    /* update config to latest and attempt connection */
+    esp_wifi_get_mode(&mode);
+    if (WIFI_MODE_APSTA != mode && WIFI_MODE_STA != mode) {
+        // the soft ap is not started, so let's set the WiFi mode to STA
+        ESP_LOGD(TAG, "MESSAGE: network_wifi_connect_existing - setting mode WIFI_MODE_STA");
+        if ((err = esp_wifi_set_mode(WIFI_MODE_STA)) != ESP_OK) {
+            ESP_LOGE(TAG, "Failed to set wifi mode to STA. Error %s", esp_err_to_name(err));
+            return err;
+        }
+    }
+       
+    if ((err = esp_wifi_set_config(WIFI_IF_STA, cfg)) != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to set STA configuration. Error %s", esp_err_to_name(err));
+        return err;
+    }
+
+    set_host_name();
+    ESP_LOGI(TAG, "Wifi Connecting...");
+    if ((err = esp_wifi_connect()) != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to initiate wifi connection. Error %s", esp_err_to_name(err));
+        return err;
+    }    
+    return err;
+}
+void network_wifi_clear_config(){
+    
+    /* erase configuration */
+    if (wifi_manager_config_sta) {
+        ESP_LOGI(TAG, "Erasing WiFi Configuration.");
+        memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t));
+        /* save NVS memory */
+        network_wifi_save_sta_config();
+    }
+
+}
+
+
+// esp_err_t network_wifi_disconnected(queue_message* msg) {
+//     esp_err_t err = ESP_OK;
+//     wifi_event_sta_disconnected_t disc_event;
+
+//     // ESP_LOGD(TAG, "MESSAGE: EVENT_STA_DISCONNECTED");
+//     // if (msg->param == NULL) {
+//     //     ESP_LOGE(TAG, "MESSAGE: EVENT_STA_DISCONNECTED - expected parameter not found!");
+//     // } else {
+//     //     memcpy(&disc_event, (wifi_event_sta_disconnected_t*)msg->param, sizeof(disc_event));
+//     //     free(msg->param);
+//     //     ESP_LOGD(TAG, "MESSAGE: EVENT_STA_DISCONNECTED with Reason code: %d (%s)", disc_event.reason, get_disconnect_code_desc(disc_event.reason));
+//     // }
+
+//     /* this even can be posted in numerous different conditions
+// 				 *
+// 				 * 1. SSID password is wrong
+// 				 * 2. Manual disconnection ordered
+// 				 * 3. Connection lost
+// 				 *
+// 				 * Having clear understand as to WHY the event was posted is key to having an efficient wifi manager
+// 				 *
+// 				 * With wifi_manager, we determine:
+// 				 *  If WIFI_MANAGER_REQUEST_STA_CONNECT_BIT is set, We consider it's a client that requested the connection.
+// 				 *    When SYSTEM_EVENT_STA_DISCONNECTED is posted, it's probably a password/something went wrong with the handshake.
+// 				 *
+// 				 *  If WIFI_MANAGER_REQUEST_STA_CONNECT_BIT is set, it's a disconnection that was ASKED by the client (clicking disconnect in the app)
+// 				 *    When SYSTEM_EVENT_STA_DISCONNECTED is posted, saved wifi is erased from the NVS memory.
+// 				 *
+// 				 *  If WIFI_MANAGER_REQUEST_STA_CONNECT_BIT and WIFI_MANAGER_REQUEST_STA_CONNECT_BIT are NOT set, it's a lost connection
+// 				 *
+// 				 *  In this version of the software, reason codes are not used. They are indicated here for potential future usage.
+// 				 *
+// 				 *  REASON CODE:
+// 				 *  1		UNSPECIFIED
+// 				 *  2		AUTH_EXPIRE					auth no longer valid, this smells like someone changed a password on the AP
+// 				 *  3		AUTH_LEAVE
+// 				 *  4		ASSOC_EXPIRE
+// 				 *  5		ASSOC_TOOMANY				too many devices already connected to the AP => AP fails to respond
+// 				 *  6		NOT_AUTHED
+// 				 *  7		NOT_ASSOCED
+// 				 *  8		ASSOC_LEAVE
+// 				 *  9		ASSOC_NOT_AUTHED
+// 				 *  10		DISASSOC_PWRCAP_BAD
+// 				 *  11		DISASSOC_SUPCHAN_BAD
+// 				 *	12		<n/a>
+// 				 *  13		IE_INVALID
+// 				 *  14		MIC_FAILURE
+// 				 *  15		4WAY_HANDSHAKE_TIMEOUT		wrong password! This was personnaly tested on my home wifi with a wrong password.
+// 				 *  16		GROUP_KEY_UPDATE_TIMEOUT
+// 				 *  17		IE_IN_4WAY_DIFFERS
+// 				 *  18		GROUP_CIPHER_INVALID
+// 				 *  19		PAIRWISE_CIPHER_INVALID
+// 				 *  20		AKMP_INVALID
+// 				 *  21		UNSUPP_RSN_IE_VERSION
+// 				 *  22		INVALID_RSN_IE_CAP
+// 				 *  23		802_1X_AUTH_FAILED			wrong password?
+// 				 *  24		CIPHER_SUITE_REJECTED
+// 				 *  200		BEACON_TIMEOUT
+// 				 *  201		NO_AP_FOUND
+// 				 *  202		AUTH_FAIL
+// 				 *  203		ASSOC_FAIL
+// 				 *  204		HANDSHAKE_TIMEOUT
+// 				 *
+// 				 * */
+
+//     /* reset saved sta IP */
+//     wifi_manager_safe_reset_sta_ip_string();
+
+//     if (network_manager_is_flag_set(WIFI_MANAGER_REQUEST_STA_CONNECT_BIT)) {
+//         network_manager_clear_flag(WIFI_MANAGER_REQUEST_STA_CONNECT_BIT);
+//         ESP_LOGW(TAG, "WiFi Disconnected while processing user connect request.  Wrong password?");
+//         /* there are no retries when it's a user requested connection by design. This avoids a user hanging too much
+// 					 * in case they typed a wrong password for instance. Here we simply clear the request bit and move on */
+            
+
+//         wifi_mode_t mode;
+//         esp_wifi_get_mode(&mode);
+//         if (WIFI_MODE_STA == mode) {
+//             network_manager_set_flag(WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT);
+//             // if wifi was STA, attempt to reload the previous network connection
+//             ESP_LOGW(TAG, "Attempting to restore previous network");
+//             wifi_manager_send_message(ORDER_LOAD_AND_RESTORE_STA, NULL);
+//         }
+//     } else if (network_manager_is_flag_set(WIFI_MANAGER_REQUEST_DISCONNECT_BIT)) {
+//         // ESP_LOGD(TAG, "WiFi disconnected by user");
+//         // /* user manually requested a disconnect so the lost connection is a normal event. Clear the flag and restart the AP */
+//         // network_manager_clear_flag(WIFI_MANAGER_REQUEST_DISCONNECT_BIT);
+//         // wifi_manager_generate_ip_info_json(UPDATE_USER_DISCONNECT,  wifi_netif,false);
+//         // /* erase configuration */
+//         // if (wifi_manager_config_sta) {
+//         //     ESP_LOGI(TAG, "Erasing WiFi Configuration.");
+//         //     memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t));
+//         //     /* save NVS memory */
+//         //     network_wifi_save_sta_config();
+//         // }
+//         // /* start SoftAP */
+//         // ESP_LOGD(TAG, "Disconnect processing complete. Ordering an AP start.");
+//         // wifi_manager_send_message(ORDER_START_AP, NULL);
+//     } else {
+//         /* lost connection ? */
+//         // ESP_LOGE(TAG, "WiFi Connection lost.");
+//         // messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "WiFi Connection lost");
+//         // wifi_manager_generate_ip_info_json(UPDATE_LOST_CONNECTION,  wifi_netif,false);
+
+//         // if (retries < WIFI_MANAGER_MAX_RETRY) {
+//         //     ESP_LOGD(TAG, "Issuing ORDER_CONNECT_STA to retry connection.");
+//         //     retries++;
+//         //     wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_AUTO_RECONNECT);
+//         // } else {
+//         //     /* In this scenario the connection was lost beyond repair: kick start the AP! */
+//         //     retries = 0;
+//         //     wifi_mode_t mode;
+//         //     ESP_LOGW(TAG, "All connect retry attempts failed.");
+
+//         //     /* put us in softAP mode first */
+//         //     esp_wifi_get_mode(&mode);
+//         //     /* if it was a restore attempt connection, we clear the bit */
+//         //     network_manager_clear_flag(WIFI_MANAGER_REQUEST_RESTORE_STA_BIT);
+
+//         //     if (WIFI_MODE_APSTA != mode) {
+//         //         STA_duration = STA_POLLING_MIN;
+//         //         wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_MAX_FAILED);
+//         //     } else if (STA_duration < STA_POLLING_MAX) {
+//         //         STA_duration *= 1.25;
+//         //     }
+
+//         //     xTimerChangePeriod(STA_timer, pdMS_TO_TICKS(STA_duration), portMAX_DELAY);
+//         //     xTimerStart(STA_timer, portMAX_DELAY);
+//         //     ESP_LOGD(TAG, "STA search slow polling of %d", STA_duration);
+//         // }
+//     }
+//     return err;
+// }
+
+
+char* get_disconnect_code_desc(uint8_t reason) {
+    switch (reason) {
+        case 1:
+            return "UNSPECIFIED";
+            break;
+        case 2:
+            return "AUTH_EXPIRE";
+            break;
+        case 3:
+            return "AUTH_LEAVE";
+            break;
+        case 4:
+            return "ASSOC_EXPIRE";
+            break;
+        case 5:
+            return "ASSOC_TOOMANY";
+            break;
+        case 6:
+            return "NOT_AUTHED";
+            break;
+        case 7:
+            return "NOT_ASSOCED";
+            break;
+        case 8:
+            return "ASSOC_LEAVE";
+            break;
+        case 9:
+            return "ASSOC_NOT_AUTHED";
+            break;
+        case 10:
+            return "DISASSOC_PWRCAP_BAD";
+            break;
+        case 11:
+            return "DISASSOC_SUPCHAN_BAD";
+            break;
+        case 12:
+            return "<n/a>";
+            break;
+        case 13:
+            return "IE_INVALID";
+            break;
+        case 14:
+            return "MIC_FAILURE";
+            break;
+        case 15:
+            return "4WAY_HANDSHAKE_TIMEOUT";
+            break;
+        case 16:
+            return "GROUP_KEY_UPDATE_TIMEOUT";
+            break;
+        case 17:
+            return "IE_IN_4WAY_DIFFERS";
+            break;
+        case 18:
+            return "GROUP_CIPHER_INVALID";
+            break;
+        case 19:
+            return "PAIRWISE_CIPHER_INVALID";
+            break;
+        case 20:
+            return "AKMP_INVALID";
+            break;
+        case 21:
+            return "UNSUPP_RSN_IE_VERSION";
+            break;
+        case 22:
+            return "INVALID_RSN_IE_CAP";
+            break;
+        case 23:
+            return "802_1X_AUTH_FAILED";
+            break;
+        case 24:
+            return "CIPHER_SUITE_REJECTED";
+            break;
+        case 200:
+            return "BEACON_TIMEOUT";
+            break;
+        case 201:
+            return "NO_AP_FOUND";
+            break;
+        case 202:
+            return "AUTH_FAIL";
+            break;
+        case 203:
+            return "ASSOC_FAIL";
+            break;
+        case 204:
+            return "HANDSHAKE_TIMEOUT";
+            break;
+        default:
+            return "UNKNOWN";
+            break;
+    }
+    return "";
+}
+
+
+static void network_manager_wifi_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
+    ip_event_got_ip_t* s = NULL;
+    tcpip_adapter_if_t index;
+    esp_netif_ip_info_t* ip_info = NULL;
+
+    if (event_base != IP_EVENT)
+        return;
+    switch (event_id) {
+        case IP_EVENT_ETH_GOT_IP:
+        case IP_EVENT_STA_GOT_IP:
+            s = (ip_event_got_ip_t*)event_data;
+            //tcpip_adapter_if_t index = s->if_index;
+            network_manager_async_got_ip();
+            ip_info = &s->ip_info;
+            index = s->if_index;
+
+            ESP_LOGI(TAG, "Got an IP address from interface #%i. IP=" IPSTR ", Gateway=" IPSTR ", NetMask=" IPSTR ", %s",
+                     index,
+                     IP2STR(&ip_info->ip),
+                     IP2STR(&ip_info->gw),
+                     IP2STR(&ip_info->netmask),
+                     s->ip_changed ? "Address was changed" : "Address unchanged");
+            
+            break;
+        case IP_EVENT_STA_LOST_IP:
+            ESP_LOGD(TAG, "IP_EVENT_STA_LOST_IP");
+            break;
+        case IP_EVENT_AP_STAIPASSIGNED:
+            ESP_LOGD(TAG, "IP_EVENT_AP_STAIPASSIGNED");
+            break;
+        case IP_EVENT_GOT_IP6:
+            ESP_LOGD(TAG, "IP_EVENT_GOT_IP6");
+            break;
+        default:
+            break;
+    }
+}

+ 61 - 0
components/wifi-manager/network_wifi.h

@@ -0,0 +1,61 @@
+#pragma once
+#include "network_manager.h"
+#ifdef __cplusplus
+extern "C" {
+
+#endif
+void init_network_wifi();
+void destroy_network_wifi(); 
+/**
+ * @brief saves the current STA wifi config to flash ram storage.
+ */
+esp_err_t network_wifi_save_sta_config();
+
+
+/**
+ * @brief fetch a previously STA wifi config in the flash ram storage.
+ * @return true if a previously saved config was found, false otherwise.
+ */
+bool wifi_manager_fetch_wifi_sta_config();
+
+wifi_config_t* wifi_manager_get_wifi_sta_config();
+
+/**
+ * @brief Registers handler for wifi and ip events
+ */
+void wifi_manager_register_handlers();
+
+/**
+ * @brief Generates the list of access points after a wifi scan.
+ * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful.
+ */
+void wifi_manager_generate_access_points_json(cJSON ** ap_list);
+
+/**
+ * @brief Clear the list of access points.
+ * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful.
+ */
+void wifi_manager_clear_access_points_json();
+
+
+void wifi_manager_config_ap();
+
+void wifi_manager_filter_unique( wifi_ap_record_t * aplist, uint16_t * aps);
+esp_err_t wifi_scan_done(queue_message *msg);
+esp_err_t network_wifi_start_scan(queue_message *msg);
+esp_err_t network_wifi_load_restore(queue_message *msg);
+esp_err_t network_wifi_order_connect(queue_message *msg);
+esp_err_t network_wifi_disconnected(queue_message *msg);
+esp_err_t network_wifi_start_ap(queue_message *msg);
+bool wifi_manager_load_wifi_sta_config(wifi_config_t* config );
+esp_err_t network_wifi_handle_event(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
+esp_err_t network_wifi_connect(wifi_config_t * cfg);
+bool is_wifi_up();
+void network_wifi_clear_config();
+esp_netif_t *network_wifi_get_interface();
+bool network_wifi_sta_config_changed();
+void network_wifi_get_stats( int32_t * ret_total_connected_time, int64_t * ret_last_connected, uint16_t * ret_num_disconnect);
+
+#ifdef __cplusplus
+}
+#endif

+ 793 - 0
components/wifi-manager/state_machine.cpp

@@ -0,0 +1,793 @@
+#include <state_machine.hpp>
+
+#include <cstdlib>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include "cmd_system.h"
+#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
+#include "esp_log.h"
+#include "esp_wifi_types.h"
+#include "http_server_handlers.h"
+#include "messaging.h"
+#include "network_ethernet.h"
+#include "network_status.h"
+#include "network_wifi.h"
+#include "state_machine.h"
+#include "trace.h"
+#include "dns_server.h"
+BaseType_t network_manager_task;
+/* objects used to manipulate the main queue of events */
+QueueHandle_t network_manager_queue;
+
+using namespace stateless;
+using namespace std::placeholders;
+static const char TAG[] = "network_manager";
+static TaskHandle_t task_network_manager = NULL;
+TimerHandle_t STA_timer = NULL;
+uint32_t STA_duration;
+
+static int32_t total_connected_time = 0;
+static int64_t last_connected = 0;
+static uint16_t num_disconnect = 0;
+void network_wifi_get_stats(int32_t* ret_total_connected_time, int64_t* ret_last_connected, uint16_t* ret_num_disconnect) {
+    *ret_total_connected_time = total_connected_time;
+    *ret_last_connected = last_connected;
+    *ret_num_disconnect = num_disconnect;
+}
+namespace {
+
+std::ostream& operator<<(std::ostream& os, const state_t s) {
+    //static const char* name[] = { "idle", "stopped", "started", "running" };
+    static const char* name[] = {
+
+        "initializing",
+        "global",
+        "eth_starting",
+        "eth_active",
+        "eth_active_linkup",
+        "eth_active_connected",
+        "eth_active_linkdown",
+        "wifi_up",
+        "wifi_initializing",
+        "network_manager_async",
+        "wifi_connecting_scanning",
+        "wifi_connecting",
+        "wifi_connected",
+        "wifi_disconnecting",
+        "wifi_user_disconnected",
+        "wifi_connected_waiting_for_ip",
+        "wifi_connected_scanning",
+        "wifi_lost_connection",
+        "wifi_ap_mode",
+        "wifi_ap_mode_scanning",
+        "wifi_ap_mode_scan_done",
+        "wifi_ap_mode_connecting",
+        "wifi_ap_mode_connected",
+        "system_rebooting"};
+    os << name[(int)s];
+    return os;
+}
+
+const char* trigger_to_string(trig_t trigger) {
+    switch (trigger) {
+        ENUM_TO_STRING(t_link_up);
+        ENUM_TO_STRING(t_link_down);
+        ENUM_TO_STRING(t_configure);
+        ENUM_TO_STRING(t_got_ip);
+        ENUM_TO_STRING(t_next);
+        ENUM_TO_STRING(t_start);
+        ENUM_TO_STRING(t_scan);
+        ENUM_TO_STRING(t_fail);
+        ENUM_TO_STRING(t_success);
+        ENUM_TO_STRING(t_scan_done);
+        ENUM_TO_STRING(t_connect);
+        ENUM_TO_STRING(t_reboot);
+        ENUM_TO_STRING(t_reboot_url);
+        ENUM_TO_STRING(t_lost_connection);
+        ENUM_TO_STRING(t_update_status);
+        ENUM_TO_STRING(t_disconnect);
+        default:
+
+            break;
+    }
+    return "Unknown trigger";
+}
+std::ostream& operator<<(std::ostream& os, const trig_t & t) {
+    //static const char* name[] = { "start", "stop", "set_speed", "halt" };
+    os << trigger_to_string(t);
+    return os;
+}
+
+}  // namespace
+
+// namespace stateless
+// {
+
+//   template<> void print_state<state>(std::ostream& os, const state& s)
+//   { os << s; }
+
+//   template<> void print_trigger<trigger_t_t(std::ostream& os, const trigger& t)
+//   { os << t; }
+
+// }
+
+// namespace
+// {
+
+// class network_manager
+// {
+// public:
+//   network_manager()
+//   : sm_(state_t::initializing)
+//   ,
+// {
+
+//}
+
+//   sm_.configure(state_t::idle)
+//     .permit(trig_t::t_start, state_t::started);
+
+//   sm_.configure(state_t::stopped)
+//     .on_entry([=](const TTransition&) { speed_ = 0; })
+//     .permit(trig_t::t_halt, state_t::idle);
+
+//   sm_.configure(state_t::started)
+//     .permit(trig_t::t_set_speed, state_t::running)
+//     .permit(trig_t::t_stop, state_t::stopped);
+
+//   sm_.configure(state_t::running)
+//     .on_entry_from(
+//       set_speed_trigger_,
+//       [=](const TTransition& t, int speed) { speed_ = speed; })
+//     .permit(trig_t::t_stop, state_t::stopped)
+//     .permit_reentry(trig_t::t_set_speed);
+
+//   void start(int speed)
+//   {
+//     sm_.fire(trig_t::t_start);
+//     set_speed(speed);
+//   }
+
+//   void stop()
+//   {
+//     sm_.fire(trig_t::t_stop);
+//     sm_.fire(trig_t::t_halt);
+//   }
+
+//   void set_speed(int speed)
+//   {
+//     sm_.fire(set_speed_trigger_, speed);
+//   }
+
+//   std::string print() const
+//   {
+//     std::ostringstream oss;
+//     print(oss);
+//     return oss.str();
+//   }
+
+//   void print(std::ostream& os) const
+//   {
+//     os << "Motor " << sm_ << " speed = " << speed_;
+//   }
+
+// private:
+
+//   //typedef std::shared_ptr<stateless::trigger_with_parameters<trigger_t, int>> TSetSpeedTrigger;
+
+//   wifi_config_t * wifi_config;
+//   TStateMachine sm_;
+//   ;
+//   ;
+// };
+
+// std::ostream& operator<<(std::ostream& os, const motor& m)
+// {
+//   m.print(os);
+//   return os;
+// }
+
+//}
+namespace {
+
+typedef state_machine<state_t, trig_t> TStateMachine;
+typedef TStateMachine::TTransition TTransition;
+typedef std::shared_ptr<stateless::trigger_with_parameters<trig_t, wifi_config_t*>> TConnectTrigger;
+typedef std::shared_ptr<stateless::trigger_with_parameters<trig_t, reboot_type_t>> TRebootTrigger;
+typedef std::shared_ptr<stateless::trigger_with_parameters<trig_t, char*>> TRebootOTATrigger;
+typedef std::shared_ptr<stateless::trigger_with_parameters<trig_t, wifi_event_sta_disconnected_t*>> TDisconnectTrigger;
+
+};  // namespace
+
+class NetworkManager {
+   public:
+    NetworkManager()
+        : sm_(state_t::instantiated),
+          connect_trigger_(sm_.set_trigger_parameters<wifi_config_t*>(trig_t::t_connect)),
+          reboot_trigger_(sm_.set_trigger_parameters<reboot_type_t>(trig_t::t_reboot)),
+          reboot_ota_(sm_.set_trigger_parameters<char*>(trig_t::t_reboot)),
+          disconnected_(sm_.set_trigger_parameters<wifi_event_sta_disconnected_t*>(trig_t::t_lost_connection)) {
+        sm_.configure(state_t::instantiated)
+            .permit(trig_t::t_start, state_t::initializing);
+        sm_.configure(state_t::global)
+            .permit(trig_t::t_reboot, state_t::system_rebooting)
+            .permit(trig_t::t_reboot_url, state_t::system_rebooting)
+            .permit_reentry(trig_t::t_update_status)
+            .on_entry_from(trig_t::t_update_status,
+                           [=](const TTransition& t) {
+                                wifi_manager_update_basic_info();
+                           });
+        sm_.configure(state_t::system_rebooting)
+            .on_entry_from(reboot_ota_, [=](const TTransition& t, char* url) {
+                if (url) {
+                    start_ota(url, NULL, 0);
+                    free(url);
+                }
+            })
+            .on_entry_from(reboot_trigger_, [=](const TTransition& t, reboot_type_t reboot_type) {
+                switch (reboot_type) {
+                    case reboot_type_t::OTA:
+                        ESP_LOGD(TAG, "Calling guided_restart_ota.");
+                        guided_restart_ota();
+                        break;
+                    case reboot_type_t::RECOVERY:
+                        ESP_LOGD(TAG, "Calling guided_factory.");
+                        guided_factory();
+                        break;
+                    case reboot_type_t::RESTART:
+                        ESP_LOGD(TAG, "Calling simple_restart.");
+                        simple_restart();
+                        break;
+
+                    default:
+                        break;
+                }
+            });
+
+        sm_.configure(state_t::initializing)
+            .on_entry([=](const TTransition& t) {
+                /* memory allocation */
+                ESP_LOGD(TAG, "network_manager_start.  Creating message queue");
+                network_manager_queue = xQueueCreate(3, sizeof(queue_message));
+                ESP_LOGD(TAG, "network_manager_start.  Allocating memory for callback functions registration");
+                // todo:  allow registration of event callbacks
+                ESP_LOGD(TAG, "Initializing tcp_ip adapter");
+                esp_netif_init();
+                ESP_LOGD(TAG, "Creating the default event loop");
+                ESP_ERROR_CHECK(esp_event_loop_create_default());
+                init_network_status();
+                ESP_LOGD(TAG, "Initializing network. done");
+
+                /* start wifi manager task */
+                ESP_LOGD(TAG, "Creating network manager task");
+                network_manager_task = xTaskCreate(&network_manager, "network_manager", 4096, NULL, WIFI_MANAGER_TASK_PRIORITY, &task_network_manager);
+                // send a message to start the connections
+            })
+            .permit(trig_t::t_start, state_t::eth_starting);
+        sm_.configure(state_t::eth_starting)
+            .on_entry([=](const TTransition& t) {
+                /* start http server */
+                http_server_start();
+                ESP_LOGD(TAG, "network_manager task started. Configuring Network Interface");
+                init_network_ethernet();
+            })
+            .permit(trig_t::t_fail, state_t::wifi_initializing)
+            .permit(trig_t::t_success, state_t::eth_active);
+
+        sm_.configure(state_t::eth_active)
+            .permit(trig_t::t_link_up, state_t::eth_active_linkup)
+            .permit(trig_t::t_got_ip, state_t::eth_active_connected)
+            .permit(trig_t::t_link_down, state_t::eth_active_linkdown)
+            .permit(trig_t::t_fail, state_t::wifi_initializing);
+
+        sm_.configure(state_t::eth_active_linkup)
+            .sub_state_of(state_t::eth_active)
+            .on_entry([=](const TTransition& t) {
+                // Anything we need to do on link becoming active?
+            });
+        sm_.configure(state_t::eth_active_linkdown)
+            .sub_state_of(state_t::eth_active)
+            .on_entry([=](const TTransition& t) {
+                // If not connected after a certain time, start
+                // wifi
+            });
+        sm_.configure(state_t::eth_active_connected)
+            .sub_state_of(state_t::eth_active)
+            .on_entry([=](const TTransition& t) {
+
+            })
+            .on_exit([=](const TTransition& t) {
+
+            });
+        sm_.configure(state_t::wifi_up)
+            .on_entry([=](const TTransition& t) {
+
+            })
+            .on_exit([=](const TTransition& t) {
+
+            });
+
+        sm_.configure(state_t::wifi_initializing)
+            .sub_state_of(state_t::wifi_up)
+            .on_entry([=](const TTransition& t) {
+                esp_err_t err = ESP_OK;
+                ESP_LOGD(TAG, "network_wifi_load_restore");
+                if (!is_wifi_up()) {
+                    messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi not started. Load Configuration");
+                    return ESP_FAIL;
+                }
+                if (wifi_manager_fetch_wifi_sta_config()) {
+                    ESP_LOGI(TAG, "Saved wifi found on startup. Will attempt to connect.");
+                    network_manager_async_connect(wifi_manager_get_wifi_sta_config());
+                } else {
+                    /* no wifi saved: start soft AP! This is what should happen during a first run */
+                    ESP_LOGD(TAG, "No saved wifi. Starting AP.");
+                    network_manager_async_configure();
+                }
+                return err;
+            })
+            .permit(trig_t::t_configure, state_t::wifi_ap_mode)
+            .permit(trig_t::t_connect, state_t::wifi_connecting_scanning);
+
+        sm_.configure(state_t::wifi_connecting_scanning)
+            .sub_state_of(state_t::wifi_up)
+            .on_entry_from(connect_trigger_, [=](const TTransition& t, wifi_config_t* wifi_config) {
+                if (network_wifi_connect(wifi_config) == ESP_OK) {
+                    network_manager_async_connect(wifi_config);
+                } else {
+                    network_manager_async_fail();
+                }
+
+                // STA_duration = STA_POLLING_MIN;
+                //     /* create timer for background STA connection */
+                //     if (!STA_timer) {
+                //         STA_timer = xTimerCreate("background STA", pdMS_TO_TICKS(STA_duration), pdFALSE, NULL, polling_STA);
+                //     }
+
+                // setup a timeout here.  On timeout,
+                // check reconnect_attempts and
+                // fire trig_t::t_scan if we have more attempts to try
+                // fire trig_t::t_fail  otherwise
+            })
+            .permit_reentry_if(trig_t::t_scan, [&]() {
+                return ++reconnect_attempt < 3;
+            })
+            .permit(trig_t::t_connect, state_t::wifi_connecting)
+            .permit(trig_t::t_fail, state_t::wifi_lost_connection);
+
+        sm_.configure(state_t::wifi_connecting)
+            .on_entry_from(connect_trigger_, [=](const TTransition& t, wifi_config_t* wifi_config) {
+                // setup a timeout here.  On timeout,
+                // check reconnect_attempts and
+                // fire trig_t::t_wifi_connecting_existing if we have more attempts to try
+                // fire trig_t::t_fail  otherwise
+            })
+            .permit(trig_t::t_success, state_t::wifi_connected_waiting_for_ip)
+            .permit(trig_t::t_got_ip, state_t::wifi_connected)
+            .permit(trig_t::t_lost_connection, state_t::wifi_ap_mode);
+        sm_.configure(state_t::wifi_connected_waiting_for_ip)
+            .permit(trig_t::t_got_ip, state_t::wifi_connected);
+
+        sm_.configure(state_t::wifi_ap_mode)
+            .on_entry([=](const TTransition& t) {
+                wifi_manager_config_ap();
+                ESP_LOGD(TAG, "AP Starting, requesting wifi scan.");
+                network_manager_async_scan();
+            })
+            .on_entry_from(disconnected_, [=](const TTransition& t, wifi_event_sta_disconnected_t* disconnected_event) {
+                if(disconnected_event){
+                    free(disconnected_event);
+                }
+            })
+            .permit(trig_t::t_scan, state_t::wifi_ap_mode_scanning);
+
+        sm_.configure(state_t::wifi_ap_mode_scanning)
+            .on_entry([=](const TTransition& t) {
+                // build a list of found AP
+            })
+            .permit(trig_t::t_scan_done, state_t::wifi_ap_mode_scan_done);
+
+        sm_.configure(state_t::wifi_ap_mode_scan_done)
+            .permit(trig_t::t_connect, state_t::wifi_ap_mode_connecting);
+        sm_.configure(state_t::wifi_ap_mode_connecting)
+            .on_entry_from(connect_trigger_, [=](const TTransition& t, wifi_config_t* wifi_config) {
+
+            })
+            .permit(trig_t::t_got_ip, state_t::wifi_ap_mode_connected)
+            .permit(trig_t::t_fail, state_t::wifi_ap_mode);
+
+        sm_.configure(state_t::wifi_ap_mode_connected)
+            .on_entry([=](const TTransition& t) {
+
+            })
+            .permit(trig_t::t_success, state_t::wifi_connected);
+
+        sm_.configure(state_t::wifi_connected)
+            .on_entry([&](const TTransition& t) {
+                last_connected = esp_timer_get_time();
+                /* bring down DNS hijack */
+                ESP_LOGD(TAG, "Stopping DNS.");
+                dns_server_stop();
+                if (network_wifi_sta_config_changed()) {
+                    network_wifi_save_sta_config();
+                }
+
+                /* stop AP mode */
+                esp_wifi_set_mode(WIFI_MODE_STA);
+            })
+            .permit_reentry(trig_t::t_scan_done)
+            .permit(trig_t::t_lost_connection, state_t::wifi_lost_connection)
+            .permit(trig_t::t_scan, state_t::wifi_connected_scanning)
+            .permit(trig_t::t_disconnect, state_t::wifi_disconnecting)
+            .permit(trig_t::t_connect, state_t::wifi_connecting);
+
+        sm_.configure(state_t::wifi_disconnecting)
+            .permit(trig_t::t_lost_connection, state_t::wifi_user_disconnected);
+        sm_.configure(state_t::wifi_user_disconnected)
+            .on_entry_from(disconnected_,
+                           [=](const TTransition& t, wifi_event_sta_disconnected_t* disconnected_event) {
+                               ESP_LOGD(TAG, "WiFi disconnected by user");
+                               network_wifi_clear_config();
+                               wifi_manager_generate_ip_info_json(UPDATE_USER_DISCONNECT);
+                               network_manager_async_configure();
+                               if (disconnected_event) {
+                                   free(disconnected_event);
+                               }
+                           })
+            .permit(trig_t::t_configure, state_t::wifi_ap_mode);
+        sm_.configure(state_t::wifi_lost_connection)
+            .on_entry_from(disconnected_,
+                           [=](const TTransition& t, wifi_event_sta_disconnected_t* disconnected_event) {
+                               ESP_LOGE(TAG, "WiFi Connection lost.");
+                               messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "WiFi Connection lost");
+                               wifi_manager_generate_ip_info_json(UPDATE_LOST_CONNECTION);
+                               if (last_connected > 0)
+                                   total_connected_time += ((esp_timer_get_time() - last_connected) / (1000 * 1000));
+                               last_connected = 0;
+                               num_disconnect++;
+                               ESP_LOGW(TAG, "Wifi disconnected. Number of disconnects: %d, Average time connected: %d", num_disconnect, num_disconnect > 0 ? (total_connected_time / num_disconnect) : 0);
+                               //network_manager_async_connect(wifi_manager_get_wifi_sta_config());
+                               if (retries < WIFI_MANAGER_MAX_RETRY) {
+                                   ESP_LOGD(TAG, "Issuing ORDER_CONNECT_STA to retry connection.");
+                                   retries++;
+                                   network_manager_async_connect(wifi_manager_get_wifi_sta_config());
+                                   free(disconnected_event);
+                               } else {
+                                   /* In this scenario the connection was lost beyond repair: kick start the AP! */
+                                   retries = 0;
+                                   wifi_mode_t mode;
+                                   ESP_LOGW(TAG, "All connect retry attempts failed.");
+
+                                   /* put us in softAP mode first */
+                                   esp_wifi_get_mode(&mode);
+                                   if (WIFI_MODE_APSTA != mode) {
+                                       STA_duration = STA_POLLING_MIN;
+                                       network_manager_async_lost_connection(disconnected_event);
+                                   } else if (STA_duration < STA_POLLING_MAX) {
+                                       STA_duration *= 1.25;
+                                       free(disconnected_event);
+                                   }
+                                   /* keep polling for existing connection */
+                                   xTimerChangePeriod(STA_timer, pdMS_TO_TICKS(STA_duration), portMAX_DELAY);
+                                   xTimerStart(STA_timer, portMAX_DELAY);
+                                   ESP_LOGD(TAG, "STA search slow polling of %d", STA_duration);
+                               }
+                           })
+            .on_entry([=](const TTransition& t) {
+                wifi_manager_safe_reset_sta_ip_string();
+            })
+            .permit(trig_t::t_connect, state_t::wifi_connecting)
+            .permit(trig_t::t_lost_connection, state_t::wifi_ap_mode);
+        // Register a callback for state transitions (the default does nothing).
+        sm_.on_transition([](const TTransition& t) {
+            std::cout << "transition from [" << t.source() << "] to ["
+                      << t.destination() << "] via trigger [" << t.trigger() << "]"
+                      << std::endl;
+        });
+
+        // Override the default behaviour of throwing when a trigger is unhandled.
+        sm_.on_unhandled_trigger([](const state_t s, const trig_t  t) {
+            std::cerr << "ignore unhandled trigger [" << t << "] in state [" << s
+                      << "]" << std::endl;
+        });
+    }
+
+   public:
+    bool
+    Allowed(trig_t  trigger) {
+        if (!sm_.can_fire(trigger)) {
+            ESP_LOGW(TAG, "Network manager might not be able to process trigger %s", trigger_to_string(trigger));
+            return false;
+        }
+        return true;
+    }
+    bool Fire(trig_t  trigger) {
+        try {
+            sm_.fire(trigger);
+            return true;
+        } catch (const std::exception& e) {
+            std::cerr << e.what() << '\n';
+        }
+        return false;
+    }
+    bool Event(queue_message& msg) {
+        trig_t  trigger = msg.trigger;
+        try {
+            if (trigger == trig_t::t_connect) {
+                sm_.fire(connect_trigger_, msg.wifi_config);
+            } else if (trigger == trig_t::t_reboot) {
+                sm_.fire(reboot_trigger_, msg.rtype);
+            } else if (trigger == trig_t::t_reboot_url) {
+                sm_.fire(reboot_ota_, msg.strval);
+            } else if (trigger == trig_t::t_lost_connection) {
+                sm_.fire(disconnected_, msg.disconnected_event);
+            } else {
+                sm_.fire(trigger);
+            }
+            return true;
+        } catch (const std::exception& e) {
+            std::cerr << e.what() << '\n';
+            return false;
+        }
+    }
+
+   private:
+    uint8_t reconnect_attempt = 0;
+    bool existing_connection = false;
+    uint8_t retries = 0;
+    TStateMachine sm_;
+    TConnectTrigger connect_trigger_;
+    TRebootTrigger reboot_trigger_;
+    TRebootOTATrigger reboot_ota_;
+    TDisconnectTrigger disconnected_;
+};
+
+NetworkManager nm;
+void network_manager_start() {
+    nm.Fire(trig_t::t_start);
+}
+
+bool network_manager_async(trig_t  trigger) {
+    queue_message msg;
+    msg.trigger = trigger;
+    if (nm.Allowed(trigger)) {
+        return xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
+    }
+    return false;
+}
+bool network_manager_async_fail() {
+    return network_manager_async(trig_t::t_fail);
+}
+bool network_manager_async_success() {
+    return network_manager_async(trig_t::t_success);
+}
+
+bool network_manager_async_link_up() {
+    return network_manager_async(trig_t::t_link_up);
+}
+bool network_manager_async_link_down() {
+    return network_manager_async(trig_t::t_link_down);
+}
+bool network_manager_async_configure() {
+    return network_manager_async(trig_t::t_configure);
+}
+bool network_manager_async_got_ip() {
+    return network_manager_async(trig_t::t_got_ip);
+}
+bool network_manager_async_next() {
+    return network_manager_async(trig_t::t_next);
+}
+bool network_manager_async_start() {
+    return network_manager_async(trig_t::t_start);
+}
+bool network_manager_async_scan() {
+    return network_manager_async(trig_t::t_scan);
+}
+
+bool network_manager_async_update_status() {
+    return network_manager_async(trig_t::t_update_status);
+}
+
+bool network_manager_async_disconnect() {
+    return network_manager_async(trig_t::t_disconnect);
+}
+
+bool network_manager_async_scan_done() {
+    return network_manager_async(trig_t::t_scan_done);
+}
+bool network_manager_async_connect(wifi_config_t* wifi_config) {
+    queue_message msg;
+    msg.trigger = trig_t::t_connect;
+    msg.wifi_config = wifi_config;
+    if (nm.Allowed(msg.trigger)) {
+        return xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
+    }
+    return false;
+}
+bool network_manager_async_lost_connection(wifi_event_sta_disconnected_t* disconnected_event) {
+    queue_message msg;
+    msg.trigger = trig_t::t_lost_connection;
+    msg.disconnected_event = disconnected_event;
+    if (nm.Allowed(msg.trigger)) {
+        return xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
+    }
+    return false;
+}
+bool network_manager_async_reboot(reboot_type_t rtype) {
+    queue_message msg;
+    msg.trigger = trig_t::t_reboot;
+    msg.rtype = rtype;
+    if (nm.Allowed(msg.trigger)) {
+        return xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
+    }
+    return false;
+}
+
+void network_manager_reboot_ota(char* url) {
+    queue_message msg;
+
+    if (url == NULL) {
+        msg.trigger = trig_t::t_reboot;
+        msg.rtype = reboot_type_t::OTA;
+    } else {
+        msg.trigger = trig_t::t_reboot_url;
+        msg.strval = strdup(url);
+    }
+    if (nm.Allowed(msg.trigger)) {
+        xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
+    }
+    return;
+}
+
+//     switch (msg.code) {
+//         case EVENT_SCAN_DONE:
+//             err = wifi_scan_done(&msg);
+//             /* callback */
+//             if (cb_ptr_arr[msg.code]) {
+//                 ESP_LOGD(TAG, "Invoking SCAN DONE callback");
+//                 (*cb_ptr_arr[msg.code])(NULL);
+//                 ESP_LOGD(TAG, "Done Invoking SCAN DONE callback");
+//             }
+//             break;
+//         case ORDER_START_WIFI_SCAN:
+//             err = network_wifi_start_scan(&msg);
+//             /* callback */
+//             if (cb_ptr_arr[msg.code])
+//                 (*cb_ptr_arr[msg.code])(NULL);
+//             break;
+
+//         case ORDER_LOAD_AND_RESTORE_STA:
+//             err = network_wifi_load_restore(&msg);
+//             /* callback */
+//             if (cb_ptr_arr[msg.code])
+//                 (*cb_ptr_arr[msg.code])(NULL);
+
+//             break;
+
+//         case ORDER_CONNECT_STA:
+//             err = network_wifi_order_connect(&msg);
+//             /* callback */
+//             if (cb_ptr_arr[msg.code])
+//                 (*cb_ptr_arr[msg.code])(NULL);
+
+//             break;
+
+//         case EVENT_STA_DISCONNECTED:
+//             err = network_wifi_disconnected(&msg);
+//             /* callback */
+//             if (cb_ptr_arr[msg.code])
+//                 (*cb_ptr_arr[msg.code])(NULL);
+//             break;
+
+//         case ORDER_START_AP:
+//             err = network_wifi_start_ap(&msg);
+//             /* callback */
+//             if (cb_ptr_arr[msg.code])
+//                 (*cb_ptr_arr[msg.code])(NULL);
+//             break;
+
+//         case EVENT_GOT_IP:
+//             ESP_LOGD(TAG, "MESSAGE: EVENT_GOT_IP");
+//             /* save IP as a string for the HTTP server host */
+//             //s->ip_info.ip.addr
+//             ip_event_got_ip_t* event = (ip_event_got_ip_t*)msg.param;
+//             wifi_manager_safe_update_sta_ip_string(&(event->ip_info.ip));
+//             wifi_manager_generate_ip_info_json(network_manager_is_flag_set(WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT)? UPDATE_FAILED_ATTEMPT_AND_RESTORE : UPDATE_CONNECTION_OK, event->esp_netif, event->ip_changed);
+//             free(msg.param);
+//             /* callback */
+//             if (cb_ptr_arr[msg.code])
+//                 (*cb_ptr_arr[msg.code])(NULL);
+//             break;
+//         case UPDATE_CONNECTION_OK:
+//             messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "UPDATE_CONNECTION_OK not implemented");
+//             break;
+//         case ORDER_DISCONNECT_STA:
+//             ESP_LOGD(TAG, "MESSAGE: ORDER_DISCONNECT_STA. Calling esp_wifi_disconnect()");
+
+//             /* precise this is coming from a user request */
+//             xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_DISCONNECT_BIT);
+
+//             /* order wifi discconect */
+//             ESP_ERROR_CHECK(esp_wifi_disconnect());
+
+//             /* callback */
+//             if (cb_ptr_arr[msg.code])
+//                 (*cb_ptr_arr[msg.code])(NULL);
+
+//             break;
+
+//         case ORDER_RESTART_OTA_URL:
+//             ESP_LOGD(TAG, "Calling start_ota.");
+//             start_ota(msg.param, NULL, 0);
+//             free(msg.param);
+//             break;
+
+//         case ORDER_RESTART_RECOVERY:
+
+//             break;
+//         case ORDER_RESTART:
+//             ESP_LOGD(TAG, "Calling simple_restart.");
+//             simple_restart();
+//             break;
+//         case ORDER_UPDATE_STATUS:
+//             ;
+//             break;
+//         case EVENT_ETH_TIMEOUT:
+//             ESP_LOGW(TAG, "Ethernet connection timeout.  Rebooting with WiFi Active");
+// 	network_manager_reboot(RESTART);
+//             break;
+// case EVENT_ETH_LINK_UP:
+//             /* callback */
+//             ESP_LOGD(TAG,"EVENT_ETH_LINK_UP message received");
+//             if (cb_ptr_arr[msg.code])
+//                 (*cb_ptr_arr[msg.code])(NULL);
+// break;
+// case EVENT_ETH_LINK_DOWN:
+//             /* callback */
+//             if (cb_ptr_arr[msg.code])
+//                 (*cb_ptr_arr[msg.code])(NULL);
+// break;
+//         default:
+//             break;
+
+//     } /* end of switch/case */
+
+// if (!network_ethernet_wait_for_link(500)) {
+//     if(network_ethernet_enabled()){
+//         ESP_LOGW(TAG, "Ethernet not connected. Starting Wifi");
+//     }
+//     init_network_wifi();
+//     wifi_manager_send_message(ORDER_LOAD_AND_RESTORE_STA, NULL);
+// }
+
+void network_manager(void* pvParameters) {
+    queue_message msg;
+    esp_err_t err = ESP_OK;
+    BaseType_t xStatus;
+    network_manager_async(trig_t::t_start);
+
+    /* main processing loop */
+    for (;;) {
+        xStatus = xQueueReceive(network_manager_queue, &msg, portMAX_DELAY);
+
+        if (xStatus == pdPASS) {
+            // pass the event to the sync processor
+            nm.Event(msg);
+        } /* end of if status=pdPASS */
+    }     /* end of for loop */
+
+    vTaskDelete(NULL);
+}
+
+void network_manager_destroy() {
+    vTaskDelete(task_network_manager);
+    task_network_manager = NULL;
+    /* heap buffers */
+    destroy_network_status();
+    destroy_network_wifi();
+    destroy_network_status();
+    /* RTOS objects */
+    vQueueDelete(network_manager_queue);
+    network_manager_queue = NULL;
+}

+ 108 - 0
components/wifi-manager/state_machine.h

@@ -0,0 +1,108 @@
+#pragma once
+#ifdef __cplusplus
+extern "C" {
+
+#endif
+
+#include "esp_wifi.h"
+#include "esp_wifi_types.h"
+
+
+#define STA_POLLING_MIN (15 * 1000)
+#define STA_POLLING_MAX (10 * 60 * 1000)
+
+//enum class state { idle, stopped, started, running };
+
+//enum class trigger { start, stop, set_speed, halt };
+typedef enum  {
+    t_link_up,
+    t_link_down,
+    t_configure,
+    t_got_ip,
+    t_disconnect,
+    t_next,
+    t_start,
+    t_scan,
+    t_fail,
+    t_success,
+    t_scan_done,
+    t_connect,
+    t_reboot,
+    t_reboot_url,
+    t_lost_connection,
+    t_update_status
+} trig_t;
+
+typedef enum  { 
+    instantiated,
+    initializing,
+    global,
+    eth_starting,
+    eth_active,
+    eth_active_linkup,
+    eth_active_connected,
+    eth_active_linkdown,
+    wifi_up,
+    wifi_initializing,
+    wifi_connecting_scanning,
+    wifi_connecting,
+    wifi_connected,
+    wifi_disconnecting,
+    wifi_user_disconnected,
+    wifi_connected_waiting_for_ip,
+    wifi_connected_scanning,
+    wifi_lost_connection,
+    wifi_ap_mode,
+    wifi_ap_mode_scanning,
+    wifi_ap_mode_scan_done,
+    wifi_ap_mode_connecting,
+    wifi_ap_mode_connected,
+    system_rebooting
+} state_t;
+typedef enum {
+	OTA,
+	RECOVERY,
+	RESTART,
+} reboot_type_t;
+typedef struct {
+    trig_t trigger;
+    union 
+    {
+        wifi_config_t* wifi_config;
+        reboot_type_t rtype;
+        char * strval;
+        wifi_event_sta_disconnected_t * disconnected_event;
+    } ;
+	
+    
+} queue_message;
+
+bool network_manager_event_simple(trig_t trigger);
+bool network_manager_event(trig_t trigger, void* param);
+bool network_t_connect_event(wifi_config_t* wifi_config);
+bool network_t_link_event(bool link_up);
+bool network_manager_async_event(trig_t trigger, void* param);
+bool network_manager_async(trig_t trigger);
+bool network_manager_async_fail();
+bool network_manager_async_success();
+bool network_manager_async_link_up();
+bool network_manager_async_link_down();
+bool network_manager_async_configure();
+bool network_manager_async_got_ip();
+bool network_manager_async_next();
+bool network_manager_async_start();
+bool network_manager_async_scan();
+bool network_manager_async_scan_done();
+bool network_manager_async_connect(wifi_config_t* wifi_config);
+bool network_manager_async_lost_connection(wifi_event_sta_disconnected_t * disconnected_event);
+bool network_manager_async_reboot(reboot_type_t rtype);
+void network_manager_reboot_ota(char* url);
+bool network_manager_async_disconnect();
+bool network_manager_async_update_status();
+/**
+ * Allocate heap memory for the wifi manager and start the wifi_manager RTOS task
+ */
+void network_manager_start();
+#ifdef __cplusplus
+}
+#endif

+ 0 - 1803
components/wifi-manager/wifi_manager.c

@@ -1,1803 +0,0 @@
-/*
-Copyright (c) 2017-2019 Tony Pottier
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-@file wifi_manager.c
-@author Tony Pottier
-@brief Defines all functions necessary for esp32 to connect to a wifi/scan wifis
-
-Contains the freeRTOS task and all necessary support
-
-@see https://idyl.io
-@see https://github.com/tonyp7/esp32-wifi-manager
-*/
-
-#include "wifi_manager.h"
-#include "platform_esp32.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
-
-#include "dns_server.h"
-#include "esp_system.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-#include "freertos/event_groups.h"
-#include <esp_event.h>
-#include "esp_event_loop.h"
-#include "tcpip_adapter.h"
-// IDF-V4++ #include "esp_netif.h"
-#include "esp_event.h"
-#include "esp_eth.h"
-#include "esp_wifi.h"
-#include "esp_wifi_types.h"
-#include "esp_log.h"
-#include "nvs.h"
-#include "nvs_flash.h"
-#include "mdns.h"
-#include "lwip/api.h"
-#include "lwip/err.h"
-#include "lwip/netdb.h"
-#include "lwip/ip4_addr.h"
-#include "esp_ota_ops.h"
-#include "esp_app_format.h"
-#include "cJSON.h"
-#include "platform_config.h"
-#include "trace.h"
-#include "cmd_system.h"
-#include "messaging.h"
-#include "bt_app_core.h"
-
-#include "http_server_handlers.h"
-#include "monitor.h"
-#include "accessors.h"
-#include "globdefs.h"
-
-
-#ifndef CONFIG_SQUEEZELITE_ESP32_RELEASE_URL
-#pragma message "Defaulting release url"
-#define CONFIG_SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases"
-#endif
-
-#define STR_OR_BLANK(p) p==NULL?"":p
-BaseType_t wifi_manager_task;
-
-/* objects used to manipulate the main queue of events */
-QueueHandle_t wifi_manager_queue;
-SemaphoreHandle_t wifi_manager_json_mutex = NULL;
-SemaphoreHandle_t wifi_manager_sta_ip_mutex = NULL;
-char *wifi_manager_sta_ip = NULL;
-#define STA_IP_LEN sizeof(char) * IP4ADDR_STRLEN_MAX
-uint16_t ap_num = MAX_AP_NUM;
-wifi_ap_record_t *accessp_records=NULL;
-cJSON * accessp_cjson=NULL;
-char *ip_info_json = NULL;
-char * release_url=NULL;
-cJSON * ip_info_cjson=NULL;
-wifi_config_t* wifi_manager_config_sta = NULL;
-static void	(*chained_notify)(in_addr_t, u16_t, u16_t);	
-static int32_t total_connected_time=0;
-static int64_t last_connected=0;
-static uint16_t num_disconnect=0;
-static char lms_server_ip[IP4ADDR_STRLEN_MAX]={0};
-static uint16_t lms_server_port=0;
-static uint16_t lms_server_cport=0;
-
-void (**cb_ptr_arr)(void*) = NULL;
-
-/* @brief tag used for ESP serial console messages */
-static const char TAG[] = "wifi_manager";
-
-/* @brief task handle for the main wifi_manager task */
-static TaskHandle_t task_wifi_manager = NULL;
-
-#define STA_POLLING_MIN	(15*1000)
-#define STA_POLLING_MAX	(10*60*1000)
-
-/**
- * The actual WiFi settings in use
- */
-//struct wifi_settings_t wifi_settings = {
-//	.sta_only = DEFAULT_STA_ONLY,
-//	.sta_power_save = DEFAULT_STA_POWER_SAVE,
-//	.sta_static_ip = 0
-//};
-
-
-/* wifi scanner config */
-wifi_scan_config_t scan_config = {
-	.ssid = 0,
-	.bssid = 0,
-	.channel = 0,
-	.show_hidden = true
-};
-
-
-const char wifi_manager_nvs_namespace[] = "config";
-
-EventGroupHandle_t wifi_manager_event_group;
-
-/* @brief indicate that the ESP32 is currently connected. */
-const int WIFI_MANAGER_WIFI_CONNECTED_BIT = BIT0;
-
-const int WIFI_MANAGER_AP_STA_CONNECTED_BIT = BIT1;
-
-/* @brief Set automatically once the SoftAP is started */
-const int WIFI_MANAGER_AP_STARTED_BIT = BIT2;
-
-/* @brief When set, means a client requested to connect to an access point.*/
-const int WIFI_MANAGER_REQUEST_STA_CONNECT_BIT = BIT3;
-
-/* @brief This bit is set automatically as soon as a connection was lost */
-const int WIFI_MANAGER_STA_DISCONNECT_BIT = BIT4;
-
-/* @brief When set, means the wifi manager attempts to restore a previously saved connection at startup. */
-const int WIFI_MANAGER_REQUEST_RESTORE_STA_BIT = BIT5;
-
-/* @brief When set, means a client requested to disconnect from currently connected AP. */
-const int WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT = BIT6;
-
-/* @brief When set, means a scan is in progress */
-const int WIFI_MANAGER_SCAN_BIT = BIT7;
-
-/* @brief When set, means user requested for a disconnect */
-const int WIFI_MANAGER_REQUEST_DISCONNECT_BIT = BIT8;
-
-/* @brief When set, means user requested connecting to a new network and it failed */
-const int WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT = BIT9;
-
-
-char * get_disconnect_code_desc(uint8_t reason){
-	switch (reason) {
-		case 1	: return "UNSPECIFIED"; break;
-		case 2	: return "AUTH_EXPIRE"; break;
-		case 3	: return "AUTH_LEAVE"; break;
-		case 4	: return "ASSOC_EXPIRE"; break;
-		case 5	: return "ASSOC_TOOMANY"; break;
-		case 6	: return "NOT_AUTHED"; break;
-		case 7	: return "NOT_ASSOCED"; break;
-		case 8	: return "ASSOC_LEAVE"; break;
-		case 9	: return "ASSOC_NOT_AUTHED"; break;
-		case 10	: return "DISASSOC_PWRCAP_BAD"; break;
-		case 11	: return "DISASSOC_SUPCHAN_BAD"; break;
-		case 12	: return "<n/a>"; break;
-		case 13	: return "IE_INVALID"; break;
-		case 14	: return "MIC_FAILURE"; break;
-		case 15	: return "4WAY_HANDSHAKE_TIMEOUT"; break;
-		case 16	: return "GROUP_KEY_UPDATE_TIMEOUT"; break;
-		case 17	: return "IE_IN_4WAY_DIFFERS"; break;
-		case 18	: return "GROUP_CIPHER_INVALID"; break;
-		case 19	: return "PAIRWISE_CIPHER_INVALID"; break;
-		case 20	: return "AKMP_INVALID"; break;
-		case 21	: return "UNSUPP_RSN_IE_VERSION"; break;
-		case 22	: return "INVALID_RSN_IE_CAP"; break;
-		case 23	: return "802_1X_AUTH_FAILED"; break;
-		case 24	: return "CIPHER_SUITE_REJECTED"; break;
-		case 200	: return "BEACON_TIMEOUT"; break;
-		case 201	: return "NO_AP_FOUND"; break;
-		case 202	: return "AUTH_FAIL"; break;
-		case 203	: return "ASSOC_FAIL"; break;
-		case 204	: return "HANDSHAKE_TIMEOUT"; break;
-		default: return "UNKNOWN"; break;
-	}
-	return "";
-}
-void wifi_manager_update_status(){
-	wifi_manager_send_message(ORDER_UPDATE_STATUS,NULL);
-}
-void set_host_name(){
-	esp_err_t err;
-	ESP_LOGD(TAG, "Retrieving host name from nvs");
-	char * host_name = (char * )config_alloc_get(NVS_TYPE_STR, "host_name");
-	if(host_name ==NULL){
-		ESP_LOGE(TAG,   "Could not retrieve host name from nvs");
-	}
-	else {
-		ESP_LOGD(TAG,  "Setting host name to : %s",host_name);
-		if((err=tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, host_name)) !=ESP_OK){
-			ESP_LOGE(TAG,  "Unable to set host name. Error: %s",esp_err_to_name(err));
-		}
-//		if((err=tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_AP, host_name)) !=ESP_OK){
-//			ESP_LOGE(TAG,  "Unable to set host name. Error: %s",esp_err_to_name(err));
-//		}
-		free(host_name);
-	}
-
-}
-
-bool isGroupBitSet(uint8_t bit){
-	EventBits_t uxBits= xEventGroupGetBits(wifi_manager_event_group);
-	return (uxBits & bit);
-}
-
-void wifi_manager_scan_async(){
-	wifi_manager_send_message(ORDER_START_WIFI_SCAN, NULL);
-}
-
-void wifi_manager_disconnect_async(){
-	wifi_manager_send_message(ORDER_DISCONNECT_STA, NULL);
-	//xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT); TODO: delete
-}
-
-void wifi_manager_reboot_ota(char * url){
-	if(url == NULL){
-		wifi_manager_send_message(ORDER_RESTART_OTA, NULL);
-	}
-	else {
-		wifi_manager_send_message(ORDER_RESTART_OTA_URL,strdup(url) );
-	}
-
-}
-
-void wifi_manager_reboot(reboot_type_t rtype){
-	switch (rtype) {
-	case OTA:
-		wifi_manager_send_message(ORDER_RESTART_OTA, NULL);
-		break;
-	case RECOVERY:
-		wifi_manager_send_message(ORDER_RESTART_RECOVERY, NULL);
-		break;
-	case RESTART:
-		wifi_manager_send_message(ORDER_RESTART, NULL);
-		break;
-		default:
-			ESP_LOGE(TAG,"Unknown reboot type %d", rtype);
-			break;
-	}
-	wifi_manager_send_message(ORDER_DISCONNECT_STA, NULL);
-	//xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT); TODO: delete
-}
-
-/** Event handler for Ethernet events */
-static void eth_event_handler(void *arg, esp_event_base_t event_base,
-                              int32_t event_id, void *event_data)
-{
-    uint8_t mac_addr[6] = {0};
-    /* we can get the ethernet driver handle from event data */
-    esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
-
-    switch (event_id) {
-    case ETHERNET_EVENT_CONNECTED:
-        esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
-        ESP_LOGI(TAG, "Ethernet Link Up");
-        ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x",
-                 mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
-        break;
-    case ETHERNET_EVENT_DISCONNECTED:
-        ESP_LOGI(TAG, "Ethernet Link Down");
-        break;
-    case ETHERNET_EVENT_START:
-        ESP_LOGI(TAG, "Ethernet Started");
-        break;
-    case ETHERNET_EVENT_STOP:
-        ESP_LOGI(TAG, "Ethernet Stopped");
-        break;
-    default:
-        break;
-    }
-}
-
-static void eth_init(void) {
-	esp_eth_mac_t *mac;
-	esp_eth_phy_t *phy;
-	esp_err_t err = ESP_OK;
-	eth_config_t const *eth = config_eth_get( );
-		
-	// quick check if we have a valid ethernet configuration
-	if ((eth->mdc == -1 && eth->mosi == -1) || !*eth->model) {
-		ESP_LOGI(TAG, "No ethernet");
-		return;
-	}	
-	
-    tcpip_adapter_set_default_eth_handlers();
-    esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL);
-
-    eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
-    eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
-    phy_config.phy_addr = 1;
-    phy_config.reset_gpio_num = eth->rst;
-
-	if (eth->rmii) {
-#ifdef CONFIG_ETH_USE_ESP32_EMAC		
-		mac_config.smi_mdc_gpio_num = eth->mdc;
-		mac_config.smi_mdio_gpio_num = eth->mdio;
-		mac = esp_eth_mac_new_esp32(&mac_config);
-		phy = esp_eth_phy_new_lan8720(&phy_config);
-		ESP_LOGI(TAG, "Adding ethernet RMII with mdc %d and mdio %d", eth->mdc, eth->mdio);
-#else
-		ESP_LOGE(TAG, "Ethernet RMII set but not included in compilation");
-		return;
-#endif
-	} else {
-#ifdef CONFIG_ETH_SPI_ETHERNET_DM9051		
-		spi_device_handle_t spi_handle = NULL;
-		spi_host_device_t host = SPI3_HOST;
-		
-		if (eth->host != -1) {
-			// don't use system's shared SPI
-			spi_bus_config_t buscfg = {
-				.miso_io_num = eth->miso,
-				.mosi_io_num = eth->mosi,
-				.sclk_io_num = eth->clk,
-				.quadwp_io_num = -1,
-				.quadhd_io_num = -1,
-			};
-			
-			// can't use SPI0
-			if (eth->host == 1) host = SPI2_HOST;
-			err |= spi_bus_initialize(host, &buscfg, 1);
-		} else {
-			// when we use shared SPI, we assume it has been initialized
-			host = spi_system_host;
-		}	
-		
-		spi_device_interface_config_t devcfg = {
-			.command_bits = 1,
-			.address_bits = 7,
-			.mode = 0,
-			.clock_speed_hz = eth->speed,
-			.spics_io_num = eth->cs,
-			.queue_size = 20
-		};
-		
-		err |= spi_bus_add_device(host, &devcfg, &spi_handle);
-		
-		// dm9051 ethernet driver is based on spi driver
-		eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
-		// we assume that isr has been installed already
-		dm9051_config.int_gpio_num = eth->intr;
-		mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
-		phy = esp_eth_phy_new_dm9051(&phy_config);
-		ESP_LOGI(TAG, "Adding ethernet SPI on host %d with mosi %d and miso %d", host, eth->mosi, eth->miso);
-#else
-		ESP_LOGE(TAG, "Ethernet SPI set but not included in compilation");
-		return;
-#endif
-	}	
-
-    esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
-    esp_eth_handle_t eth_handle = NULL;
-    err |= esp_eth_driver_install(&config, &eth_handle);
-    err |= esp_eth_start(eth_handle);	
-	
-	if (err != ESP_OK) {
-		ESP_LOGE(TAG, "Can't install Ethernet driver %d", err);
-	}
-}
-
-void wifi_manager_init_wifi(){
-	/* event handler and event group for the wifi driver */
-	ESP_LOGD(TAG,   "Initializing wifi.  Creating event group");
-	wifi_manager_event_group = xEventGroupCreate();
-	// Now Initialize the Wifi Stack
-	ESP_LOGD(TAG,   "Initializing wifi. Initializing tcp_ip adapter");
-    tcpip_adapter_init();
-    ESP_LOGD(TAG,   "Initializing wifi. Creating the default event loop");
-    ESP_ERROR_CHECK(esp_event_loop_create_default());
-    ESP_LOGD(TAG,   "Initializing wifi. Getting default wifi configuration");
-    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
-    ESP_LOGD(TAG,   "Initializing wifi. Initializing wifi. ");
-    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
-    ESP_LOGD(TAG,   "Initializing wifi. Calling register handlers");
-    wifi_manager_register_handlers();
-    ESP_LOGD(TAG,   "Initializing wifi. Setting WiFi storage as RAM");
-    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
-    ESP_LOGD(TAG,   "Initializing wifi. Setting WiFi mode to WIFI_MODE_NULL");
-    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_NULL) );
-    ESP_LOGD(TAG,   "Initializing wifi. Starting wifi");
-    ESP_ERROR_CHECK( esp_wifi_start() );
-	
-	eth_init();
-
-    taskYIELD();
-    ESP_LOGD(TAG,   "Initializing wifi. done");
-}
-
-void set_lms_server_details(in_addr_t ip, u16_t hport, u16_t cport){
-	strncpy(lms_server_ip,inet_ntoa(ip),sizeof(lms_server_ip));
-	lms_server_ip[sizeof(lms_server_ip)-1]='\0';
-	ESP_LOGI(TAG,"LMS IP: %s, hport: %d, cport: %d",lms_server_ip, hport, cport);
-	lms_server_port = hport;
-	lms_server_cport = cport;
-
-}
-
-static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport) {
-	set_lms_server_details(ip,hport,cport);
-	if (chained_notify) (*chained_notify)(ip, hport, cport);
-	wifi_manager_update_status();
-}
-
-static void polling_STA(void* timer_id) {
-	wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_AUTO_RECONNECT);
-}
-
-void wifi_manager_start(){
-
-
-	/* memory allocation */
-	ESP_LOGD(TAG,   "wifi_manager_start.  Creating message queue");
-	wifi_manager_queue = xQueueCreate( 3, sizeof( queue_message) );
-	ESP_LOGD(TAG,   "wifi_manager_start.  Creating mutexes");
-	wifi_manager_json_mutex = xSemaphoreCreateMutex();
-	wifi_manager_sta_ip_mutex = xSemaphoreCreateMutex();
-
-	ESP_LOGD(TAG,   "wifi_manager_start.  Creating access point json structure");
-
-	accessp_cjson = NULL;
-	accessp_cjson = wifi_manager_clear_ap_list_json(&accessp_cjson);
-	ip_info_json = NULL;
-	ESP_LOGD(TAG,   "wifi_manager_start.  Creating status jcon structure");
-	ip_info_cjson = wifi_manager_clear_ip_info_json(&ip_info_cjson);
-
-	ESP_LOGD(TAG,   "wifi_manager_start.  Allocating memory for wifi configuration structure");
-	wifi_manager_config_sta = (wifi_config_t*)malloc(sizeof(wifi_config_t));
-	memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t));
-//	memset(&wifi_settings, 0x00, sizeof(wifi_settings));
-
-	ESP_LOGD(TAG,   "wifi_manager_start.  Allocating memory for callback functions registration");
-	cb_ptr_arr = malloc(  sizeof(   sizeof( void (*)( void* ) )) * MESSAGE_CODE_COUNT);
-	for(int i=0; i<MESSAGE_CODE_COUNT; i++){
-		cb_ptr_arr[i] = NULL;
-	}
-
-	ESP_LOGD(TAG,   "About to set the STA IP String to 0.0.0.0");
-	wifi_manager_sta_ip = (char*)malloc(STA_IP_LEN);
-	wifi_manager_safe_update_sta_ip_string(NULL);
-
-	ESP_LOGD(TAG,   "Getting release url ");
-	char * release_url = (char * )config_alloc_get_default(NVS_TYPE_STR, "release_url", QUOTE(CONFIG_SQUEEZELITE_ESP32_RELEASE_URL), 0);
-	if(release_url == NULL){
-		ESP_LOGE(TAG,  "Unable to retrieve the release url from nvs");
-	}
-	else {
-		ESP_LOGD(TAG,   "Found release url %s", release_url);
-	}
-	chained_notify = server_notify;
-	server_notify = connect_notify;
-	ESP_LOGD(TAG,   "About to call init wifi");
-	wifi_manager_init_wifi();
-
-	/* start wifi manager task */
-	ESP_LOGD(TAG,   "Creating wifi manager task");
-	wifi_manager_task= xTaskCreate(&wifi_manager, "wifi_manager", 4096, NULL, WIFI_MANAGER_TASK_PRIORITY, &task_wifi_manager);
-}
-
-
-esp_err_t wifi_manager_save_sta_config(){
-	nvs_handle handle;
-	esp_err_t esp_err;
-	ESP_LOGD(TAG,   "About to save config to flash");
-
-	if(wifi_manager_config_sta){
-		esp_err = nvs_open(wifi_manager_nvs_namespace, NVS_READWRITE, &handle);
-		if (esp_err != ESP_OK) {
-			ESP_LOGE(TAG,  "Unable to open name namespace %s. Error %s", wifi_manager_nvs_namespace, esp_err_to_name(esp_err));
-			return esp_err;
-		}
-
-		esp_err = nvs_set_blob(handle, "ssid", wifi_manager_config_sta->sta.ssid, sizeof(wifi_manager_config_sta->sta.ssid));
-		if (esp_err != ESP_OK) {
-			ESP_LOGE(TAG,  "Unable to save ssid in name namespace %s. Error %s", wifi_manager_nvs_namespace, esp_err_to_name(esp_err));
-			return esp_err;
-		}
-
-		esp_err = nvs_set_blob(handle, "password", wifi_manager_config_sta->sta.password, sizeof(wifi_manager_config_sta->sta.password));
-		if (esp_err != ESP_OK) {
-			ESP_LOGE(TAG,  "Unable to save password in name namespace %s. Error %s", wifi_manager_nvs_namespace, esp_err_to_name(esp_err));
-			return esp_err;
-		}
-
-//		esp_err = nvs_set_blob(handle, "settings", &wifi_settings, sizeof(wifi_settings));
-//		if (esp_err != ESP_OK) {
-//			ESP_LOGE(TAG,  "Unable to save wifi_settings in name namespace %s. Error %s", wifi_manager_nvs_namespace, esp_err_to_name(esp_err));
-//			return esp_err;
-//		}
-
-		esp_err = nvs_commit(handle);
-		if (esp_err != ESP_OK) {
-			ESP_LOGE(TAG,  "Unable to commit changes. Error %s", esp_err_to_name(esp_err));
-			messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Unable to save wifi credentials. %s",esp_err_to_name(esp_err));
-			return esp_err;
-		}
-		nvs_close(handle);
-
-		ESP_LOGD(TAG,   "wifi_manager_wrote wifi_sta_config: ssid:%s password:%s",wifi_manager_config_sta->sta.ssid,wifi_manager_config_sta->sta.password);
-	}
-
-	return ESP_OK;
-}
-
-bool wifi_manager_fetch_wifi_sta_config(){
-	nvs_handle handle;
-	esp_err_t esp_err;
-
-	ESP_LOGD(TAG,  "Fetching wifi sta config.");
-	esp_err=nvs_open(wifi_manager_nvs_namespace, NVS_READONLY, &handle);
-	if(esp_err == ESP_OK){
-		if(wifi_manager_config_sta == NULL){
-			ESP_LOGD(TAG,  "Allocating memory for structure.");
-			wifi_manager_config_sta = (wifi_config_t*)malloc(sizeof(wifi_config_t));
-		}
-		memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t));
-
-		/* ssid */
-		ESP_LOGD(TAG,  "Fetching value for ssid.");
-		size_t sz = sizeof(wifi_manager_config_sta->sta.ssid);
-		uint8_t *buff = (uint8_t*)malloc(sizeof(uint8_t) * sz);
-		memset(buff,0x00,sizeof(uint8_t) * sz);
-		esp_err = nvs_get_blob(handle, "ssid", buff, &sz);
-		if(esp_err != ESP_OK){
-			ESP_LOGD(TAG,  "No ssid found in nvs.");
-			FREE_AND_NULL(buff);
-			nvs_close(handle);
-			return false;
-		}
-		memcpy(wifi_manager_config_sta->sta.ssid, buff, sizeof(wifi_manager_config_sta->sta.ssid));
-		FREE_AND_NULL(buff);
-		ESP_LOGD(TAG,   "wifi_manager_fetch_wifi_sta_config: ssid:%s ",wifi_manager_config_sta->sta.ssid);
-
-				/* password */
-		sz = sizeof(wifi_manager_config_sta->sta.password);
-		buff = (uint8_t*)malloc(sizeof(uint8_t) * sz);
-		memset(buff,0x00,sizeof(uint8_t) * sz);
-		esp_err = nvs_get_blob(handle, "password", buff, &sz);
-		if(esp_err != ESP_OK){
-			// Don't take this as an error. This could be an opened access point?
-			ESP_LOGW(TAG,  "No wifi password found in nvs");
-		}
-		else {
-			memcpy(wifi_manager_config_sta->sta.password, buff, sizeof(wifi_manager_config_sta->sta.password));
-			ESP_LOGD(TAG,   "wifi_manager_fetch_wifi_sta_config: password:%s",wifi_manager_config_sta->sta.password);
-		}
-		FREE_AND_NULL(buff);
-		nvs_close(handle);
-
-		return wifi_manager_config_sta->sta.ssid[0] != '\0';
-	}
-	else{
-		ESP_LOGW(TAG,  "wifi manager has no previous configuration. %s",esp_err_to_name(esp_err));
-		return false;
-	}
-
-}
-
-cJSON * wifi_manager_get_new_json(cJSON **old){
-	ESP_LOGV(TAG,  "wifi_manager_get_new_json called");
-	cJSON * root=*old;
-	if(root!=NULL){
-	    cJSON_Delete(root);
-	    *old=NULL;
-	}
-	ESP_LOGV(TAG,  "wifi_manager_get_new_json done");
-	 return cJSON_CreateObject();
-}
-cJSON * wifi_manager_get_new_array_json(cJSON **old){
-	ESP_LOGV(TAG,  "wifi_manager_get_new_array_json called");
-	cJSON * root=*old;
-	if(root!=NULL){
-	    cJSON_Delete(root);
-	    *old=NULL;
-	}
-	ESP_LOGV(TAG,  "wifi_manager_get_new_array_json done");
-	return cJSON_CreateArray();
-}
-void wifi_manager_update_basic_info(){
-	if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
-
-		monitor_gpio_t *mgpio= get_jack_insertion_gpio(); 
-		
-		cJSON * voltage = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "Voltage");
-		if(voltage){
-			cJSON_SetNumberValue(voltage,	battery_value_svc());
-		}
-		cJSON * bt_status = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "bt_status");
-		if(bt_status){
-			cJSON_SetNumberValue(bt_status,	bt_app_source_get_a2d_state());
-		}
-		cJSON * bt_sub_status = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "bt_sub_status");
-		if(bt_sub_status){
-			cJSON_SetNumberValue(bt_sub_status,	bt_app_source_get_media_state());
-		}
-		cJSON * jack = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "Jack");
-		if(jack){
-			jack->type=mgpio->gpio>=0 && jack_inserted_svc()?cJSON_True:cJSON_False;
-		}
-		cJSON * disconnect_count = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "disconnect_count");
-		if(disconnect_count){
-			cJSON_SetNumberValue(disconnect_count,	num_disconnect);
-		}
-		cJSON * avg_conn_time = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "avg_conn_time");
-		if(avg_conn_time){
-			cJSON_SetNumberValue(avg_conn_time,	num_disconnect>0?(total_connected_time/num_disconnect):0);
-		}	
-		if(lms_server_cport>0){
-			cJSON * value = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "lms_cport");
-			if(value){
-				cJSON_SetNumberValue(value,lms_server_cport);
-			}			
-			else {
-				cJSON_AddNumberToObject(ip_info_cjson,"lms_cport",lms_server_cport);
-			}
-		}
-
-		if(lms_server_port>0){
-			cJSON * value = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "lms_port");
-			if(value){
-				cJSON_SetNumberValue(value,lms_server_port);
-			}			
-			else {
-				cJSON_AddNumberToObject(ip_info_cjson,"lms_port",lms_server_port);
-			}
-		}
-
-
-		if(strlen(lms_server_ip) >0){
-			cJSON * value = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "lms_ip");
-			if(!value){
-				// only create if it does not exist. Since we're creating a reference 
-				// to a char buffer, updates to cJSON aren't needed
-				cJSON_AddItemToObject(ip_info_cjson, "lms_ip", cJSON_CreateStringReference(lms_server_ip));
-			}			
-		}		
-		wifi_manager_unlock_json_buffer();
-	}
-}
-cJSON * wifi_manager_get_basic_info(cJSON **old){
-	monitor_gpio_t *mgpio= get_jack_insertion_gpio(); 
-	const esp_app_desc_t* desc = esp_ota_get_app_description();
-	ESP_LOGV(TAG,  "wifi_manager_get_basic_info called");
-	cJSON *root = wifi_manager_get_new_json(old);
-	cJSON_AddItemToObject(root, "project_name", cJSON_CreateString(desc->project_name));
-	#ifdef CONFIG_FW_PLATFORM_NAME
-		cJSON_AddItemToObject(root, "platform_name", cJSON_CreateString(CONFIG_FW_PLATFORM_NAME));
-	#endif
-	cJSON_AddItemToObject(root, "version", cJSON_CreateString(desc->version));
-	if(release_url !=NULL) cJSON_AddItemToObject(root, "release_url", cJSON_CreateString(release_url));
-	cJSON_AddNumberToObject(root,"recovery",	is_recovery_running?1:0);
-	cJSON_AddBoolToObject(root, "Jack", mgpio->gpio>=0 && jack_inserted_svc() );
-	cJSON_AddNumberToObject(root,"Voltage",	battery_value_svc());
-	cJSON_AddNumberToObject(root,"disconnect_count", num_disconnect	);
-	cJSON_AddNumberToObject(root,"avg_conn_time", num_disconnect>0?(total_connected_time/num_disconnect):0	);
-	cJSON_AddNumberToObject(root,"bt_status", bt_app_source_get_a2d_state());
-	cJSON_AddNumberToObject(root,"bt_sub_status", bt_app_source_get_media_state());
-#if CONFIG_I2C_LOCKED
-	cJSON_AddTrueToObject(root, "is_i2c_locked");
-#else
-	cJSON_AddFalseToObject(root, "is_i2c_locked");
-#endif
-
-	ESP_LOGV(TAG,  "wifi_manager_get_basic_info done");
-	return root;
-}
-cJSON * wifi_manager_clear_ip_info_json(cJSON **old){
-	ESP_LOGV(TAG,  "wifi_manager_clear_ip_info_json called");
-	cJSON *root = wifi_manager_get_basic_info(old);
-	ESP_LOGV(TAG,  "wifi_manager_clear_ip_info_json done");
- 	 return root;
-}
-cJSON * wifi_manager_clear_ap_list_json(cJSON **old){
-	ESP_LOGV(TAG,  "wifi_manager_clear_ap_list_json called");
-	cJSON *root = wifi_manager_get_new_array_json(old);
-	ESP_LOGV(TAG,  "wifi_manager_clear_ap_list_json done");
- 	return root;
-}
-
-
-
-void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code){
-	ESP_LOGD(TAG,  "wifi_manager_generate_ip_info_json called");
-	wifi_config_t *config = wifi_manager_get_wifi_sta_config();
-	ip_info_cjson = wifi_manager_get_basic_info(&ip_info_cjson);
-
-	cJSON_AddNumberToObject(ip_info_cjson, "urc", update_reason_code);
-	if(config){
-		if(update_reason_code == UPDATE_CONNECTION_OK || update_reason_code == UPDATE_LOST_CONNECTION || update_reason_code == UPDATE_FAILED_ATTEMPT){
-			cJSON_AddItemToObject(ip_info_cjson, "ssid", cJSON_CreateString((char *)config->sta.ssid));
-		}
-		if(update_reason_code == UPDATE_CONNECTION_OK){
-			/* rest of the information is copied after the ssid */
-			tcpip_adapter_ip_info_t ip_info;
-			ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info));
-			cJSON_AddItemToObject(ip_info_cjson, "ip", cJSON_CreateString(ip4addr_ntoa((ip4_addr_t *)&ip_info.ip)));
-			cJSON_AddItemToObject(ip_info_cjson, "netmask", cJSON_CreateString(ip4addr_ntoa((ip4_addr_t *)&ip_info.netmask)));
-			cJSON_AddItemToObject(ip_info_cjson, "gw", cJSON_CreateString(ip4addr_ntoa((ip4_addr_t *)&ip_info.gw)));
-			wifi_ap_record_t ap;
-			esp_wifi_sta_get_ap_info(&ap);
-			cJSON_AddItemToObject(ip_info_cjson, "rssi", cJSON_CreateNumber(ap.rssi));
-		}
-	}
-
-	ESP_LOGV(TAG,  "wifi_manager_generate_ip_info_json done");
-}
-#define LOCAL_MAC_SIZE 20
-char * get_mac_string(uint8_t mac[6]){
-
-	char * macStr=malloc(LOCAL_MAC_SIZE);
-	memset(macStr, 0x00, LOCAL_MAC_SIZE);
-	snprintf(macStr, LOCAL_MAC_SIZE,MACSTR, MAC2STR(mac));
-	return macStr;
-
-}
-void wifi_manager_generate_access_points_json(cJSON ** ap_list){
-	*ap_list = wifi_manager_get_new_array_json(ap_list);
-
-	if(*ap_list==NULL) return;
-	for(int i=0; i<ap_num;i++){
-		cJSON * ap = cJSON_CreateObject();
-		if(ap == NULL) {
-			ESP_LOGE(TAG,  "Unable to allocate memory for access point entry #%d",i);
-			return;
-		}
-		cJSON * radio = cJSON_CreateObject();
-		if(radio == NULL) {
-			ESP_LOGE(TAG,  "Unable to allocate memory for access point entry #%d",i);
-			cJSON_Delete(ap);
-			return;
-		}
-		wifi_ap_record_t ap_rec = accessp_records[i];
-		cJSON_AddNumberToObject(ap, "chan", ap_rec.primary);
-		cJSON_AddNumberToObject(ap, "rssi", ap_rec.rssi);
-		cJSON_AddNumberToObject(ap, "auth", ap_rec.authmode);
-		cJSON_AddItemToObject(ap, "ssid", cJSON_CreateString((char *)ap_rec.ssid));
-
-		char * bssid = get_mac_string(ap_rec.bssid);
-		cJSON_AddItemToObject(ap, "bssid", cJSON_CreateString(STR_OR_BLANK(bssid)));
-		FREE_AND_NULL(bssid);
-		cJSON_AddNumberToObject(radio, "b", ap_rec.phy_11b?1:0);
-		cJSON_AddNumberToObject(radio, "g", ap_rec.phy_11g?1:0);
-		cJSON_AddNumberToObject(radio, "n", ap_rec.phy_11n?1:0);
-		cJSON_AddNumberToObject(radio, "low_rate", ap_rec.phy_lr?1:0);
-		cJSON_AddItemToObject(ap,"radio", radio);
-		cJSON_AddItemToArray(*ap_list, ap);
-		char * ap_json = cJSON_PrintUnformatted(ap);
-		if(ap_json!=NULL){
-			ESP_LOGD(TAG,  "New access point found: %s", ap_json);
-			free(ap_json);
-		}
-	}
-	char * ap_list_json = cJSON_PrintUnformatted(*ap_list);
-	if(ap_list_json!=NULL){
-		ESP_LOGV(TAG,  "Full access point list: %s", ap_list_json);
-		free(ap_list_json);
-	}
-
-}
-
-bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait){
-	if(wifi_manager_sta_ip_mutex){
-		if( xSemaphoreTake( wifi_manager_sta_ip_mutex, xTicksToWait ) == pdTRUE ) {
-			return true;
-		}
-		else{
-			return false;
-		}
-	}
-	else{
-		return false;
-	}
-
-}
-
-void wifi_manager_unlock_sta_ip_string(){
-	xSemaphoreGive( wifi_manager_sta_ip_mutex );
-}
-
-void wifi_manager_safe_update_sta_ip_string(struct ip4_addr * ip4){
-	if(wifi_manager_lock_sta_ip_string(portMAX_DELAY)){
-		strcpy(wifi_manager_sta_ip, ip4!=NULL?ip4addr_ntoa(ip4):"0.0.0.0");
-		ESP_LOGD(TAG,   "Set STA IP String to: %s", wifi_manager_sta_ip);
-		wifi_manager_unlock_sta_ip_string();
-	}
-}
-
-char* wifi_manager_get_sta_ip_string(){
-	return wifi_manager_sta_ip;
-}
-
-bool wifi_manager_lock_json_buffer(TickType_t xTicksToWait){
-	ESP_LOGV(TAG,  "Locking json buffer");
-	if(wifi_manager_json_mutex){
-		if( xSemaphoreTake( wifi_manager_json_mutex, xTicksToWait ) == pdTRUE ) {
-			ESP_LOGV(TAG,  "Json buffer locked!");
-			return true;
-		}
-		else{
-			ESP_LOGE(TAG,  "Semaphore take failed. Unable to lock json buffer mutex");
-			return false;
-		}
-	}
-	else{
-		ESP_LOGV(TAG,  "Unable to lock json buffer mutex");
-		return false;
-	}
-
-}
-
-void wifi_manager_unlock_json_buffer(){
-	ESP_LOGV(TAG,  "Unlocking json buffer!");
-	xSemaphoreGive( wifi_manager_json_mutex );
-}
-
-char* wifi_manager_alloc_get_ap_list_json(){
-	return cJSON_PrintUnformatted(accessp_cjson);
-}
-
-
-static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){
-
-    if(event_base== WIFI_EVENT){
-		switch(event_id) {
-			case WIFI_EVENT_WIFI_READY:
-				ESP_LOGD(TAG,   "WIFI_EVENT_WIFI_READY");
-				break;
-
-			case WIFI_EVENT_SCAN_DONE:
-				ESP_LOGD(TAG,   "WIFI_EVENT_SCAN_DONE");
-				xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_SCAN_BIT);
-				wifi_manager_send_message(EVENT_SCAN_DONE, NULL);
-				break;
-
-			case WIFI_EVENT_STA_AUTHMODE_CHANGE:
-				ESP_LOGD(TAG,   "WIFI_EVENT_STA_AUTHMODE_CHANGE");
-//		        	structwifi_event_sta_authmode_change_t
-//		        	Argument structure for WIFI_EVENT_STA_AUTHMODE_CHANGE event
-//
-//		        	Public Members
-//
-//		        	wifi_auth_mode_told_mode
-//		        	the old auth mode of AP
-//
-//		        	wifi_auth_mode_tnew_mode
-//		        	the new auth mode of AP
-				break;
-
-
-			case WIFI_EVENT_AP_START:
-				ESP_LOGD(TAG,   "WIFI_EVENT_AP_START");
-				xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_AP_STARTED_BIT);
-				break;
-
-			case WIFI_EVENT_AP_STOP:
-				ESP_LOGD(TAG,  "WIFI_EVENT_AP_STOP");
-				break;
-
-			case WIFI_EVENT_AP_PROBEREQRECVED:{
-//		        	wifi_event_ap_probe_req_rx_t
-//		        	Argument structure for WIFI_EVENT_AP_PROBEREQRECVED event
-//
-//		        	Public Members
-//
-//		        	int rssi
-//		        	Received probe request signal strength
-//
-//		        	uint8_t mac[6]
-//		        	MAC address of the station which send probe request
-
-				wifi_event_ap_probe_req_rx_t * s =(wifi_event_ap_probe_req_rx_t*)event_data;
-				char * mac = get_mac_string(s->mac);
-				ESP_LOGD(TAG,  "WIFI_EVENT_AP_PROBEREQRECVED. RSSI: %d, MAC: %s",s->rssi, STR_OR_BLANK(mac));
-				FREE_AND_NULL(mac);
-			}
-				break;
-			case WIFI_EVENT_STA_WPS_ER_SUCCESS:
-				ESP_LOGD(TAG,  "WIFI_EVENT_STA_WPS_ER_SUCCESS");
-				break;
-			case WIFI_EVENT_STA_WPS_ER_FAILED:
-				ESP_LOGD(TAG,  "WIFI_EVENT_STA_WPS_ER_FAILED");
-				break;
-			case WIFI_EVENT_STA_WPS_ER_TIMEOUT:
-				ESP_LOGD(TAG,  "WIFI_EVENT_STA_WPS_ER_TIMEOUT");
-				break;
-			case WIFI_EVENT_STA_WPS_ER_PIN:
-				ESP_LOGD(TAG,  "WIFI_EVENT_STA_WPS_ER_PIN");
-				break;
-			case WIFI_EVENT_AP_STACONNECTED:{ /* a user disconnected from the SoftAP */
-				wifi_event_ap_staconnected_t * stac = (wifi_event_ap_staconnected_t *)event_data;
-				char * mac = get_mac_string(stac->mac);
-				ESP_LOGD(TAG,   "WIFI_EVENT_AP_STACONNECTED. aid: %d, mac: %s",stac->aid,STR_OR_BLANK(mac));
-				FREE_AND_NULL(mac);
-				xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_AP_STA_CONNECTED_BIT);
-			}
-				break;
-			case WIFI_EVENT_AP_STADISCONNECTED:
-				ESP_LOGD(TAG,   "WIFI_EVENT_AP_STADISCONNECTED");
-				xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_AP_STA_CONNECTED_BIT);
-				break;
-
-			case WIFI_EVENT_STA_START:
-				ESP_LOGD(TAG,   "WIFI_EVENT_STA_START");
-				break;
-
-			case WIFI_EVENT_STA_STOP:
-				ESP_LOGD(TAG,   "WIFI_EVENT_STA_STOP");
-				break;
-
-			case WIFI_EVENT_STA_CONNECTED:{
-//		    		structwifi_event_sta_connected_t
-//		    		Argument structure for WIFI_EVENT_STA_CONNECTED event
-//
-//		    		Public Members
-//
-//		    		uint8_t ssid[32]
-//		    		SSID of connected AP
-//
-//		    		uint8_t ssid_len
-//		    		SSID length of connected AP
-//
-//		    		uint8_t bssid[6]
-//		    		BSSID of connected AP
-//
-//		    		uint8_t channel
-//		    		channel of connected AP
-//
-//		    		wifi_auth_mode_tauthmode
-//		    		authentication mode used by AP
-				//, get_mac_string(EVENT_HANDLER_ARG_FIELD(wifi_event_ap_probe_req_rx_t, mac)));
-
-				ESP_LOGD(TAG,   "WIFI_EVENT_STA_CONNECTED. ");
-				wifi_event_sta_connected_t * s =(wifi_event_sta_connected_t*)event_data;
-				char * bssid = get_mac_string(s->bssid);
-				char * ssid = strdup((char*)s->ssid);
-				ESP_LOGD(TAG,   "WIFI_EVENT_STA_CONNECTED. Channel: %d, Access point: %s, BSSID: %s ", s->channel, STR_OR_BLANK(ssid), (bssid));
-				FREE_AND_NULL(bssid);
-				FREE_AND_NULL(ssid);
-
-			}
-				break;
-
-			case WIFI_EVENT_STA_DISCONNECTED:{
-//		    		structwifi_event_sta_disconnected_t
-//		    		Argument structure for WIFI_EVENT_STA_DISCONNECTED event
-//
-//		    		Public Members
-//
-//		    		uint8_t ssid[32]
-//		    		SSID of disconnected AP
-//
-//		    		uint8_t ssid_len
-//		    		SSID length of disconnected AP
-//
-//		    		uint8_t bssid[6]
-//		    		BSSID of disconnected AP
-//
-//		    		uint8_t reason
-//		    		reason of disconnection
-				wifi_event_sta_disconnected_t * s =(wifi_event_sta_disconnected_t*)event_data;
-				char * bssid = get_mac_string(s->bssid);
-				ESP_LOGD(TAG,   "WIFI_EVENT_STA_DISCONNECTED. From BSSID: %s, reason code: %d (%s)", STR_OR_BLANK(bssid),s->reason, get_disconnect_code_desc(s->reason));
-				FREE_AND_NULL(bssid);
-				if(last_connected>0) total_connected_time+=((esp_timer_get_time()-last_connected)/(1000*1000));
-				last_connected = 0;
-				num_disconnect++;
-				ESP_LOGW(TAG,  "Wifi disconnected. Number of disconnects: %d, Average time connected: %d", num_disconnect, num_disconnect>0?(total_connected_time/num_disconnect):0);
-
-				/* if a DISCONNECT message is posted while a scan is in progress this scan will NEVER end, causing scan to never work again. For this reason SCAN_BIT is cleared too */
-				xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_WIFI_CONNECTED_BIT | WIFI_MANAGER_SCAN_BIT);
-
-
-				// We want to process this message asynchronously, so make sure we copy the event buffer
-				ESP_LOGD(TAG,  "Preparing to trigger event EVENT_STA_DISCONNECTED ");
-				void * parm=malloc(sizeof(wifi_event_sta_disconnected_t));
-				memcpy(parm,event_data,sizeof(wifi_event_sta_disconnected_t));
-				ESP_LOGD(TAG,  "Triggering EVENT_STA_DISCONNECTED ");
-				/* post disconnect event with reason code */
-				wifi_manager_send_message(EVENT_STA_DISCONNECTED, parm );
-			}
-				break;
-
-			default:
-				break;
-		}
-    }
-    else if(event_base== IP_EVENT){
-		switch (event_id) {
-			case IP_EVENT_STA_GOT_IP:{
-//		    		structip_event_got_ip_t
-//			    tcpip_adapter_if_t if_index;        /*!< Interface for which the event is received */
-//			    tcpip_adapter_ip6_info_t ip6_info;  /*!< IPv6 address of the interface */
-//		    	//	Event structure for IP_EVENT_STA_GOT_IP, IP_EVENT_ETH_GOT_IP events
-//
-//		    		Public Members
-//
-//		    		tcpip_adapter_if_tif_index
-//		    		Interface for which the event is received
-//
-//		    		tcpip_adapter_ip_info_t ip_info
-//		    		IP address, netmask, gatway IP address
-//
-//		    		bool ip_changed
-//		    		Whether the assigned IP has changed or not
-
-				ip_event_got_ip_t * s =(ip_event_got_ip_t*)event_data;
-				//tcpip_adapter_if_t index = s->if_index;
-				const tcpip_adapter_ip_info_t *ip_info = &s->ip_info;
-				ESP_LOGI(TAG,   "SYSTEM_EVENT_STA_GOT_IP. IP="IPSTR", Gateway="IPSTR", NetMask="IPSTR", %s",
-						IP2STR(&ip_info->ip),
-						IP2STR(&ip_info->gw),
-						IP2STR(&ip_info->netmask),
-								s->ip_changed?"Address was changed":"Address unchanged");
-				// todo: if ip address was changed, we probably need to restart, as all sockets
-				// will become abnormal
-				xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_WIFI_CONNECTED_BIT);
-				last_connected = esp_timer_get_time();
-
-				void * parm=malloc(sizeof(ip_event_got_ip_t));
-				memcpy(parm,event_data,sizeof(ip_event_got_ip_t));
-				wifi_manager_send_message(EVENT_STA_GOT_IP, parm );
-			}
-				break;
-			case IP_EVENT_STA_LOST_IP:
-				ESP_LOGD(TAG,   "IP_EVENT_STA_LOST_IP");
-				break;
-			case IP_EVENT_AP_STAIPASSIGNED:
-				ESP_LOGD(TAG,   "IP_EVENT_AP_STAIPASSIGNED");
-				break;
-			case IP_EVENT_GOT_IP6:
-				ESP_LOGD(TAG,   "IP_EVENT_GOT_IP6");
-				break;
-			case IP_EVENT_ETH_GOT_IP:
-				ESP_LOGD(TAG,   "IP_EVENT_ETH_GOT_IP");
-				wifi_manager_send_message(EVENT_ETH_GOT_IP, NULL);
-				break;
-			default:
-				break;
-		}
-	}
-
-}
-
-
-wifi_config_t* wifi_manager_get_wifi_sta_config(){
-	return wifi_manager_config_sta;
-}
-
-
-
-void wifi_manager_connect_async(){
-	/* in order to avoid a false positive on the front end app we need to quickly flush the ip json
-	 * There'se a risk the front end sees an IP or a password error when in fact
-	 * it's a remnant from a previous connection
-	 */
-	if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
-		ip_info_cjson= wifi_manager_clear_ip_info_json(&ip_info_cjson);
-		wifi_manager_unlock_json_buffer();
-	}
-	wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_USER);
-}
-
-
-char* wifi_manager_alloc_get_ip_info_json(){
-	return cJSON_PrintUnformatted(ip_info_cjson);
-}
-
-void wifi_manager_destroy(){
-	vTaskDelete(task_wifi_manager);
-	task_wifi_manager = NULL;
-	/* heap buffers */
-	free(ip_info_json);
-	free(release_url);
-	cJSON_Delete(ip_info_cjson);
-	cJSON_Delete(accessp_cjson);
-	ip_info_cjson=NULL;
-	accessp_cjson=NULL;
-	free(wifi_manager_sta_ip);
-	wifi_manager_sta_ip = NULL;
-	if(wifi_manager_config_sta){
-		free(wifi_manager_config_sta);
-		wifi_manager_config_sta = NULL;
-	}
-
-	/* RTOS objects */
-	vSemaphoreDelete(wifi_manager_json_mutex);
-	wifi_manager_json_mutex = NULL;
-	vSemaphoreDelete(wifi_manager_sta_ip_mutex);
-	wifi_manager_sta_ip_mutex = NULL;
-	vEventGroupDelete(wifi_manager_event_group);
-	wifi_manager_event_group = NULL;
-	vQueueDelete(wifi_manager_queue);
-	wifi_manager_queue = NULL;
-}
-
-void wifi_manager_filter_unique( wifi_ap_record_t * aplist, uint16_t * aps) {
-	int total_unique;
-	wifi_ap_record_t * first_free;
-	total_unique=*aps;
-
-	first_free=NULL;
-
-	for(int i=0; i<*aps-1;i++) {
-		wifi_ap_record_t * ap = &aplist[i];
-
-		/* skip the previously removed APs */
-		if (ap->ssid[0] == 0) continue;
-
-		/* remove the identical SSID+authmodes */
-		for(int j=i+1; j<*aps;j++) {
-			wifi_ap_record_t * ap1 = &aplist[j];
-			if ( (strcmp((const char *)ap->ssid, (const char *)ap1->ssid)==0) && 
-			     (ap->authmode == ap1->authmode) ) { /* same SSID, different auth mode is skipped */
-				/* save the rssi for the display */
-				if ((ap1->rssi) > (ap->rssi)) ap->rssi=ap1->rssi;
-				/* clearing the record */
-				memset(ap1,0, sizeof(wifi_ap_record_t));
-			}
-		}
-	}
-	/* reorder the list so APs follow each other in the list */
-	for(int i=0; i<*aps;i++) {
-		wifi_ap_record_t * ap = &aplist[i];
-		/* skipping all that has no name */
-		if (ap->ssid[0] == 0) {
-			/* mark the first free slot */
-			if (first_free==NULL) first_free=ap;
-			total_unique--;
-			continue;
-		}
-		if (first_free!=NULL) {
-			memcpy(first_free, ap, sizeof(wifi_ap_record_t));
-			memset(ap,0, sizeof(wifi_ap_record_t));
-			/* find the next free slot */
-			for(int j=0; j<*aps;j++) {
-				if (aplist[j].ssid[0]==0) {
-					first_free=&aplist[j];
-					break;
-				}
-			}
-		}
-	}
-	/* update the length of the list */
-	*aps = total_unique;
-}
-
-BaseType_t wifi_manager_send_message_to_front(message_code_t code, void *param){
-	queue_message msg;
-	msg.code = code;
-	msg.param = param;
-	return xQueueSendToFront( wifi_manager_queue, &msg, portMAX_DELAY);
-}
-
-BaseType_t wifi_manager_send_message(message_code_t code, void *param){
-	queue_message msg;
-	msg.code = code;
-	msg.param = param;
-	return xQueueSend( wifi_manager_queue, &msg, portMAX_DELAY);
-}
-
-void wifi_manager_set_callback(message_code_t message_code, void (*func_ptr)(void*) ){
-	if(cb_ptr_arr && message_code < MESSAGE_CODE_COUNT){
-		cb_ptr_arr[message_code] = func_ptr;
-	}
-}
-void wifi_manager_register_handlers(){
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_WIFI_READY, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_SCAN_DONE, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_AUTHMODE_CHANGE, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_START, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_STOP, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_PROBEREQRECVED, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_SUCCESS, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_FAILED, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_TIMEOUT, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_PIN, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_STACONNECTED, &event_handler, NULL ));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_STADISCONNECTED, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_START, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_STOP, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_LOST_IP, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_AP_STAIPASSIGNED, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &event_handler, NULL));
-	ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &event_handler, NULL));
-}
-
-void wifi_manager_config_ap(){
-	/* SoftAP - Wifi Access Point configuration setup */
-		tcpip_adapter_ip_info_t info;
-		esp_err_t err=ESP_OK;
-		memset(&info, 0x00, sizeof(info));
-		char * value = NULL;
-		wifi_config_t ap_config = {
-			.ap = {
-				.ssid_len = 0,
-			},
-		};
-		ESP_LOGI(TAG,  "Configuring Access Point.");
-
-		ESP_LOGD(TAG,"Stopping DHCP on interface ");
-		if((err= tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP))!=ESP_OK) 	/* stop AP DHCP server */
-		{
-			ESP_LOGW(TAG,  "Stopping DHCP failed. Error %s",esp_err_to_name(err));
-		}
-		/*
-		 * Set access point mode IP adapter configuration
-		 */
-		value = config_alloc_get_default(NVS_TYPE_STR, "ap_ip_address", DEFAULT_AP_IP, 0);
-		if(value!=NULL){
-			ESP_LOGD(TAG,  "IP Address: %s", value);
-			inet_pton(AF_INET,value, &info.ip); /* access point is on a static IP */
-		}
-		FREE_AND_NULL(value);
-		value = config_alloc_get_default(NVS_TYPE_STR, "ap_ip_gateway", CONFIG_DEFAULT_AP_GATEWAY, 0);
-		if(value!=NULL){
-			ESP_LOGD(TAG,  "Gateway: %s", value);
-			inet_pton(AF_INET,value, &info.gw); /* access point is on a static IP */
-		}
-		FREE_AND_NULL(value);
-		value = config_alloc_get_default(NVS_TYPE_STR, "ap_ip_netmask", CONFIG_DEFAULT_AP_NETMASK, 0);
-		if(value!=NULL){
-			ESP_LOGD(TAG,  "Netmask: %s", value);
-			inet_pton(AF_INET,value, &info.netmask); /* access point is on a static IP */
-		}
-		FREE_AND_NULL(value);
-
-		ESP_LOGD(TAG,  "Setting tcp_ip info for interface TCPIP_ADAPTER_IF_AP");
-		if((err=tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &info))!=ESP_OK){
-			ESP_LOGE(TAG,  "Setting tcp_ip info for interface TCPIP_ADAPTER_IF_AP. Error %s",esp_err_to_name(err));
-			return;
-		}
-		/*
-		 * Set Access Point configuration
-		 */
-		value = config_alloc_get_default(NVS_TYPE_STR, "ap_ssid", CONFIG_DEFAULT_AP_SSID, 0);
-		if(value!=NULL){
-			strlcpy((char *)ap_config.ap.ssid, value,sizeof(ap_config.ap.ssid) );
-			ESP_LOGI(TAG,  "AP SSID: %s", (char *)ap_config.ap.ssid);
-		}
-		FREE_AND_NULL(value);
-
-		value = config_alloc_get_default(NVS_TYPE_STR, "ap_pwd", DEFAULT_AP_PASSWORD, 0);
-		if(value!=NULL){
-			strlcpy((char *)ap_config.ap.password, value,sizeof(ap_config.ap.password) );
-			ESP_LOGI(TAG,  "AP Password: %s", (char *)ap_config.ap.password);
-		}
-		FREE_AND_NULL(value);
-
-		value = config_alloc_get_default(NVS_TYPE_STR, "ap_channel", STR(CONFIG_DEFAULT_AP_CHANNEL), 0);
-		if(value!=NULL){
-			ESP_LOGD(TAG,  "Channel: %s", value);
-			ap_config.ap.channel=atoi(value);
-		}
-		FREE_AND_NULL(value);
-
-		ap_config.ap.authmode = AP_AUTHMODE;
-		ap_config.ap.ssid_hidden = DEFAULT_AP_SSID_HIDDEN;
-		ap_config.ap.max_connection = DEFAULT_AP_MAX_CONNECTIONS;
-		ap_config.ap.beacon_interval = DEFAULT_AP_BEACON_INTERVAL;
-
-		ESP_LOGD(TAG,  "Auth Mode: %d", ap_config.ap.authmode);
-		ESP_LOGD(TAG,  "SSID Hidden: %d", ap_config.ap.ssid_hidden);
-		ESP_LOGD(TAG,  "Max Connections: %d", ap_config.ap.max_connection);
-		ESP_LOGD(TAG,  "Beacon interval: %d", ap_config.ap.beacon_interval);
-
-		ESP_LOGD(TAG,  "");
-		if((err= esp_wifi_set_mode(WIFI_MODE_APSTA))!=ESP_OK) 	/* stop AP DHCP server */
-		{
-			ESP_LOGE(TAG,  "Setting wifi mode as WIFI_MODE_APSTA failed. Error %s",esp_err_to_name(err));
-			return;
-		}
-
-
-
-		ESP_LOGD(TAG,  "Setting wifi AP configuration for WIFI_IF_AP");
-		if((err= esp_wifi_set_config(WIFI_IF_AP, &ap_config))!=ESP_OK) 	/* stop AP DHCP server */
-		{
-			ESP_LOGE(TAG,  "Setting wifi AP configuration for WIFI_IF_AP failed. Error %s",esp_err_to_name(err));
-			return;
-		}
-
-
-		ESP_LOGD(TAG,  "Setting wifi bandwidth (%d) for WIFI_IF_AP",DEFAULT_AP_BANDWIDTH);
-		if((err=esp_wifi_set_bandwidth(WIFI_IF_AP, DEFAULT_AP_BANDWIDTH))!=ESP_OK) 	/* stop AP DHCP server */
-		{
-			ESP_LOGE(TAG,  "Setting wifi bandwidth for WIFI_IF_AP failed. Error %s",esp_err_to_name(err));
-			return;
-		}
-
-		ESP_LOGD(TAG,  "Setting wifi power save (%d) for WIFI_IF_AP",DEFAULT_STA_POWER_SAVE);
-
-		if((err=esp_wifi_set_ps(DEFAULT_STA_POWER_SAVE))!=ESP_OK) 	/* stop AP DHCP server */
-		{
-			ESP_LOGE(TAG,  "Setting wifi power savefor WIFI_IF_AP failed. Error %s",esp_err_to_name(err));
-			return;
-		}
-
-		ESP_LOGD(TAG,  "Starting dhcps on interface TCPIP_ADAPTER_IF_AP");
-
-		if((err=tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP))!=ESP_OK) 	/* stop AP DHCP server */
-		{
-			ESP_LOGE(TAG, "Starting dhcp on TCPIP_ADAPTER_IF_AP failed. Error %s",esp_err_to_name(err));
-			return;
-		}
-
-		ESP_LOGD(TAG,  "Done configuring Soft Access Point");
-		dns_server_start();
-
-
-}
-
-void wifi_manager( void * pvParameters ){
-	queue_message msg;
-	BaseType_t xStatus;
-	EventBits_t uxBits;
-	uint8_t	retries = 0;
-	esp_err_t err=ESP_OK;
-	TimerHandle_t STA_timer;
-	uint32_t STA_duration = STA_POLLING_MIN;
-	
-	/* create timer for background STA connection */
-	STA_timer = xTimerCreate("background STA", pdMS_TO_TICKS(STA_duration), pdFALSE, NULL, polling_STA);		
-
-	/* start http server */
-	http_server_start();
-
-	/* enqueue first event: load previous config and start AP or STA mode */
-	wifi_manager_send_message(ORDER_LOAD_AND_RESTORE_STA, NULL);
-	/* main processing loop */
-	for(;;){
-		xStatus = xQueueReceive( wifi_manager_queue, &msg, portMAX_DELAY );
-
-		if( xStatus == pdPASS ){
-			switch(msg.code){
-
-			case EVENT_SCAN_DONE:
-				/* As input param, it stores max AP number ap_records can hold. As output param, it receives the actual AP number this API returns.
-				 * As a consequence, ap_num MUST be reset to MAX_AP_NUM at every scan */
-				ESP_LOGD(TAG,  "Getting AP list records");
-				if((err=esp_wifi_scan_get_ap_num(&ap_num))!=ESP_OK) {
-					ESP_LOGE(TAG,  "Failed to retrieve scan results count. Error %s",esp_err_to_name(err));
-					break;
-				}
-
-				if(ap_num>0){
-					accessp_records = (wifi_ap_record_t*)malloc(sizeof(wifi_ap_record_t) * ap_num);
-					if((err=esp_wifi_scan_get_ap_records(&ap_num, accessp_records))!=ESP_OK) {
-						ESP_LOGE(TAG,  "Failed to retrieve scan results list. Error %s",esp_err_to_name(err));
-						break;
-					}
-					/* make sure the http server isn't trying to access the list while it gets refreshed */
-					ESP_LOGD(TAG,  "Preparing to build ap JSON list");
-					if(wifi_manager_lock_json_buffer( pdMS_TO_TICKS(1000) )){
-						/* Will remove the duplicate SSIDs from the list and update ap_num */
-						wifi_manager_filter_unique(accessp_records, &ap_num);
-						wifi_manager_generate_access_points_json(&accessp_cjson);
-						wifi_manager_unlock_json_buffer();
-						ESP_LOGD(TAG,  "Done building ap JSON list");
-
-					}
-					else{
-						ESP_LOGE(TAG,   "could not get access to json mutex in wifi_scan");
-					}
-					free(accessp_records);
-				}
-				else{
-					//
-					ESP_LOGD(TAG,  "No AP Found.  Emptying the list.");
-					accessp_cjson = wifi_manager_get_new_array_json(&accessp_cjson);
-				}
-
-				/* callback */
-				if(cb_ptr_arr[msg.code]) {
-					ESP_LOGD(TAG,  "Invoking SCAN DONE callback");
-					(*cb_ptr_arr[msg.code])(NULL);
-					ESP_LOGD(TAG,  "Done Invoking SCAN DONE callback");
-				}
-				break;
-
-			case ORDER_START_WIFI_SCAN:
-				ESP_LOGD(TAG,   "MESSAGE: ORDER_START_WIFI_SCAN");
-
-				/* if a scan is already in progress this message is simply ignored thanks to the WIFI_MANAGER_SCAN_BIT uxBit */
-				if(! isGroupBitSet(WIFI_MANAGER_SCAN_BIT) ){
-					if(esp_wifi_scan_start(&scan_config, false)!=ESP_OK){
-						ESP_LOGW(TAG,  "Unable to start scan; wifi is trying to connect");
-//						set_status_message(WARNING, "Wifi Connecting. Cannot start scan.");
-						messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"Wifi connecting. Cannot start scan.");
-					}
-					else {
-						xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_SCAN_BIT);
-					}
-				}
-				else {
-					ESP_LOGW(TAG,  "Scan already in progress!");
-				}
-
-
-				/* callback */
-				if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
-
-				break;
-
-			case ORDER_LOAD_AND_RESTORE_STA:
-				ESP_LOGD(TAG,   "MESSAGE: ORDER_LOAD_AND_RESTORE_STA. About to fetch wifi STA configuration");
-				if(wifi_manager_fetch_wifi_sta_config()){
-					ESP_LOGI(TAG,   "Saved wifi found on startup. Will attempt to connect.");
-					wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_RESTORE_CONNECTION);
-				}
-				else{
-					/* no wifi saved: start soft AP! This is what should happen during a first run */
-					ESP_LOGD(TAG,   "No saved wifi found on startup. Starting access point.");
-					wifi_manager_send_message(ORDER_START_AP, NULL);
-				}
-
-				/* callback */
-				if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
-
-				break;
-
-			case ORDER_CONNECT_STA:
-				ESP_LOGD(TAG,   "MESSAGE: ORDER_CONNECT_STA - Begin");
-				break; // DOBREAK;
-
-				/* very important: precise that this connection attempt is specifically requested.
-				 * Param in that case is a boolean indicating if the request was made automatically
-				 * by the wifi_manager.
-				 * */
-				if((BaseType_t)msg.param == CONNECTION_REQUEST_USER) {
-					ESP_LOGD(TAG,   "MESSAGE: ORDER_CONNECT_STA - Connection request with no nvs connection saved yet");
-					xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT);
-					xEventGroupClearBits(wifi_manager_event_group,WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT);
-				}
-				else if((BaseType_t)msg.param == CONNECTION_REQUEST_RESTORE_CONNECTION) {
-					ESP_LOGD(TAG,   "MESSAGE: ORDER_CONNECT_STA - Connection request after restoring the AP configuration");
-					xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_RESTORE_STA_BIT);
-
-					/* STA - Wifi Station configuration setup */
-					//todo:  support static ip address
-//					if(wifi_settings.sta_static_ip) {
-//						// There's a static ip address configured, so
-//						ESP_LOGD(TAG,   "Assigning static ip to STA interface. IP: %s , GW: %s , Mask: %s",
-//										ip4addr_ntoa(&wifi_settings.sta_static_ip_config.ip),
-//										ip4addr_ntoa(&wifi_settings.sta_static_ip_config.gw),
-//										ip4addr_ntoa(&wifi_settings.sta_static_ip_config.netmask));
-//
-//						/* stop DHCP client*/
-//						ESP_ERROR_CHECK(tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA));
-//						/* assign a static IP to the STA network interface */
-//						ESP_ERROR_CHECK(tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &wifi_settings.sta_static_ip_config));
-//						}
-//					else {
-						/* start DHCP client if not started*/
-						tcpip_adapter_dhcp_status_t status;
-						ESP_LOGD(TAG,   "wifi_manager: Checking if DHCP client for STA interface is running");
-						ESP_ERROR_CHECK_WITHOUT_ABORT(tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &status));
-						if (status!=TCPIP_ADAPTER_DHCP_STARTED) {
-							ESP_LOGD(TAG,   "wifi_manager: Start DHCP client for STA interface");
-							ESP_ERROR_CHECK_WITHOUT_ABORT(tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA));
-						}
-					//}
-				}
-
-				uxBits = xEventGroupGetBits(wifi_manager_event_group);
-				if( uxBits & WIFI_MANAGER_WIFI_CONNECTED_BIT ){
-					ESP_LOGD(TAG,   "MESSAGE: ORDER_CONNECT_STA - Wifi connected bit set, ordering disconnect (WIFI_MANAGER_WIFI_CONNECTED_BIT)");
-					wifi_manager_send_message(ORDER_DISCONNECT_STA, NULL);
-					/* todo: reconnect */
-				}
-				else{
-					wifi_mode_t mode;
-					/* update config to latest and attempt connection */
-					esp_wifi_get_mode(&mode);
-					if( WIFI_MODE_APSTA != mode && WIFI_MODE_STA !=mode ){
-						// the soft ap is not started, so let's set the WiFi mode to STA
-						ESP_LOGD(TAG,   "MESSAGE: ORDER_CONNECT_STA - setting mode WIFI_MODE_STA");
-						if((err=esp_wifi_set_mode(WIFI_MODE_STA))!=ESP_OK) {
-							ESP_LOGE(TAG,  "Failed to set wifi mode to STA. Error %s",esp_err_to_name(err));
-							break;
-						}
-					}
-					ESP_LOGD(TAG,   "MESSAGE: ORDER_CONNECT_STA - setting config for WIFI_IF_STA");
-					wifi_config_t* cfg = wifi_manager_get_wifi_sta_config();
-				    char * scan_mode = config_alloc_get_default(NVS_TYPE_STR, "wifi_smode", "f", 0);
-				    if (scan_mode && strcasecmp(scan_mode,"a")==0) {
-				    	cfg->sta.scan_method=WIFI_ALL_CHANNEL_SCAN;
-				    }
-				    else {
-				    	cfg->sta.scan_method=WIFI_FAST_SCAN;
-				    }
-				    FREE_AND_NULL(scan_mode);
-					if((err=esp_wifi_set_config(WIFI_IF_STA, cfg))!=ESP_OK) {
-						ESP_LOGE(TAG,  "Failed to set STA configuration. Error %s",esp_err_to_name(err));
-						break;
-					}
-
-					set_host_name();
-					ESP_LOGI(TAG,  "Wifi Connecting...");
-					if((err=esp_wifi_connect())!=ESP_OK) {
-						ESP_LOGE(TAG,  "Failed to initiate wifi connection. Error %s",esp_err_to_name(err));
-						break;
-					}
-				}
-
-				/* callback */
-				if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
-
-				break;
-
-			case EVENT_STA_DISCONNECTED:{
-				wifi_event_sta_disconnected_t disc_event;
-
-				ESP_LOGD(TAG,   "MESSAGE: EVENT_STA_DISCONNECTED");
-				if(msg.param == NULL){
-					ESP_LOGE(TAG,  "MESSAGE: EVENT_STA_DISCONNECTED - expected parameter not found!");
-				}
-				else{
-					memcpy(&disc_event,(wifi_event_sta_disconnected_t*)msg.param,sizeof(disc_event));
-					free(msg.param);
-					ESP_LOGD(TAG,   "MESSAGE: EVENT_STA_DISCONNECTED with Reason code: %d (%s)", disc_event.reason, get_disconnect_code_desc(disc_event.reason));
-				}
-
-				/* this even can be posted in numerous different conditions
-				 *
-				 * 1. SSID password is wrong
-				 * 2. Manual disconnection ordered
-				 * 3. Connection lost
-				 *
-				 * Having clear understand as to WHY the event was posted is key to having an efficient wifi manager
-				 *
-				 * With wifi_manager, we determine:
-				 *  If WIFI_MANAGER_REQUEST_STA_CONNECT_BIT is set, We consider it's a client that requested the connection.
-				 *    When SYSTEM_EVENT_STA_DISCONNECTED is posted, it's probably a password/something went wrong with the handshake.
-				 *
-				 *  If WIFI_MANAGER_REQUEST_STA_CONNECT_BIT is set, it's a disconnection that was ASKED by the client (clicking disconnect in the app)
-				 *    When SYSTEM_EVENT_STA_DISCONNECTED is posted, saved wifi is erased from the NVS memory.
-				 *
-				 *  If WIFI_MANAGER_REQUEST_STA_CONNECT_BIT and WIFI_MANAGER_REQUEST_STA_CONNECT_BIT are NOT set, it's a lost connection
-				 *
-				 *  In this version of the software, reason codes are not used. They are indicated here for potential future usage.
-				 *
-				 *  REASON CODE:
-				 *  1		UNSPECIFIED
-				 *  2		AUTH_EXPIRE					auth no longer valid, this smells like someone changed a password on the AP
-				 *  3		AUTH_LEAVE
-				 *  4		ASSOC_EXPIRE
-				 *  5		ASSOC_TOOMANY				too many devices already connected to the AP => AP fails to respond
-				 *  6		NOT_AUTHED
-				 *  7		NOT_ASSOCED
-				 *  8		ASSOC_LEAVE
-				 *  9		ASSOC_NOT_AUTHED
-				 *  10		DISASSOC_PWRCAP_BAD
-				 *  11		DISASSOC_SUPCHAN_BAD
-				 *	12		<n/a>
-				 *  13		IE_INVALID
-				 *  14		MIC_FAILURE
-				 *  15		4WAY_HANDSHAKE_TIMEOUT		wrong password! This was personnaly tested on my home wifi with a wrong password.
-				 *  16		GROUP_KEY_UPDATE_TIMEOUT
-				 *  17		IE_IN_4WAY_DIFFERS
-				 *  18		GROUP_CIPHER_INVALID
-				 *  19		PAIRWISE_CIPHER_INVALID
-				 *  20		AKMP_INVALID
-				 *  21		UNSUPP_RSN_IE_VERSION
-				 *  22		INVALID_RSN_IE_CAP
-				 *  23		802_1X_AUTH_FAILED			wrong password?
-				 *  24		CIPHER_SUITE_REJECTED
-				 *  200		BEACON_TIMEOUT
-				 *  201		NO_AP_FOUND
-				 *  202		AUTH_FAIL
-				 *  203		ASSOC_FAIL
-				 *  204		HANDSHAKE_TIMEOUT
-				 *
-				 * */
-
-				/* reset saved sta IP */
-				wifi_manager_safe_update_sta_ip_string((struct ip4_addr * )0);
-
-				uxBits = xEventGroupGetBits(wifi_manager_event_group);
-				if( uxBits & WIFI_MANAGER_REQUEST_STA_CONNECT_BIT ){
-					xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT);
-					ESP_LOGW(TAG,   "WiFi Disconnected while processing user connect request.  Wrong password?");
-					/* there are no retries when it's a user requested connection by design. This avoids a user hanging too much
-					 * in case they typed a wrong password for instance. Here we simply clear the request bit and move on */
-					
-					if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
-						wifi_manager_generate_ip_info_json( UPDATE_FAILED_ATTEMPT );
-						wifi_manager_unlock_json_buffer();
-					}
-					wifi_mode_t mode;
-					esp_wifi_get_mode(&mode);
-					if( WIFI_MODE_STA ==mode ){
-						xEventGroupSetBits(wifi_manager_event_group,WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT);
-						// if wifi was STA, attempt to reload the previous network connection
-						ESP_LOGW(TAG,"Attempting to restore previous network"); 
-						wifi_manager_send_message(ORDER_LOAD_AND_RESTORE_STA, NULL);
-					}
-				}
-				else if (uxBits & WIFI_MANAGER_REQUEST_DISCONNECT_BIT){
-					ESP_LOGD(TAG,   "WiFi disconnected by user");
-					/* user manually requested a disconnect so the lost connection is a normal event. Clear the flag and restart the AP */
-					xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_DISCONNECT_BIT);
-					if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
-						wifi_manager_generate_ip_info_json( UPDATE_USER_DISCONNECT );
-						wifi_manager_unlock_json_buffer();
-					}
-					/* erase configuration */
-					if(wifi_manager_config_sta){
-						ESP_LOGI(TAG,   "Erasing WiFi Configuration.");
-						memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t));
-						/* save NVS memory */
-						wifi_manager_save_sta_config();
-					}
-					/* start SoftAP */
-					ESP_LOGD(TAG,   "Disconnect processing complete. Ordering an AP start.");
-					wifi_manager_send_message(ORDER_START_AP, NULL);
-				}
-				else{
-					/* lost connection ? */
-					ESP_LOGE(TAG,   "WiFi Connection lost.");
-					messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"WiFi Connection lost");
-
-					if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
-						wifi_manager_generate_ip_info_json( UPDATE_LOST_CONNECTION );
-						wifi_manager_unlock_json_buffer();
-					}
-
-					if(retries < WIFI_MANAGER_MAX_RETRY){
-						ESP_LOGD(TAG,   "Issuing ORDER_CONNECT_STA to retry connection.");
-						retries++;
-						wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_AUTO_RECONNECT);
-					}
-					else{
-						/* In this scenario the connection was lost beyond repair: kick start the AP! */
-						retries = 0;
-						wifi_mode_t mode;
-						ESP_LOGW(TAG,   "All connect retry attempts failed.");
-						
-						/* put us in softAP mode first */
-						esp_wifi_get_mode(&mode);
-						/* if it was a restore attempt connection, we clear the bit */
-						xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_RESTORE_STA_BIT);
-						
-						if(WIFI_MODE_APSTA != mode){
-							/* call directly config_ap because we don't want to scan so the message has no benefit */
-							ESP_LOGD(TAG,   "Starting AP directly.");
-							wifi_manager_config_ap();		
-							STA_duration = STA_POLLING_MIN;							
-							/* manual callback if needed */
-							if(cb_ptr_arr[ORDER_START_AP]) (*cb_ptr_arr[ORDER_START_AP])(NULL);
-						}
-						else if(STA_duration < STA_POLLING_MAX) {
-							STA_duration *= 1.25;
-						}	
-						
-						xTimerChangePeriod(STA_timer, pdMS_TO_TICKS(STA_duration), portMAX_DELAY);
-						xTimerStart(STA_timer, portMAX_DELAY);						
-						ESP_LOGD(TAG,   "STA search slow polling of %d", STA_duration);
-					}
-				}
-								
-				/* callback */
-				if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
-			}
-				break;
-
-			case ORDER_START_AP:
-				ESP_LOGD(TAG,   "MESSAGE: ORDER_START_AP");
-				wifi_manager_config_ap();
-				ESP_LOGD(TAG,  "AP Starting, requesting wifi scan.");
-				wifi_manager_scan_async();
-				/* callback */
-				if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
-				break;
-
-					
-			case EVENT_ETH_GOT_IP:
-				ESP_LOGD(TAG,   "MESSAGE: EVENT_ETH_GOT_IP");
-				/* callback */
-				if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
-				break;
-
-			case EVENT_STA_GOT_IP:
-				ESP_LOGD(TAG,   "MESSAGE: EVENT_STA_GOT_IP");
-
-				uxBits = xEventGroupGetBits(wifi_manager_event_group);
-
-				/* reset connection requests bits -- doesn't matter if it was set or not */
-				xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT);
-
-				/* save IP as a string for the HTTP server host */
-				//s->ip_info.ip.addr
-				ip_event_got_ip_t * event =(ip_event_got_ip_t*)msg.param;
-				wifi_manager_safe_update_sta_ip_string(&(event->ip_info.ip));
-				free(msg.param);
-
-				/* save wifi config in NVS if it wasn't a restored of a connection */
-				if(uxBits & WIFI_MANAGER_REQUEST_RESTORE_STA_BIT){
-					ESP_LOGD(TAG,  "Configuration came from nvs, no need to save.");
-					xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_RESTORE_STA_BIT);
-				}
-				else{
-					ESP_LOGD(TAG,  "Connection was initiated by user, storing config to nvs.");
-					wifi_manager_save_sta_config();
-				}
-
-				/* refresh JSON with the new IP */
-				if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
-					/* generate the connection info with success */
-					wifi_manager_generate_ip_info_json( uxBits & WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT?UPDATE_FAILED_ATTEMPT_AND_RESTORE:UPDATE_CONNECTION_OK );
-					wifi_manager_unlock_json_buffer();
-				}
-				else {
-					ESP_LOGW(TAG,  "Unable to lock status json buffer. ");
-				}
-
-				/* bring down DNS hijack */
-				ESP_LOGD(TAG,  "Stopping dns server.");
-				dns_server_stop();
-				
-				/* stop AP mode */
-				esp_wifi_set_mode(WIFI_MODE_STA);
-
-				/* callback */
-				if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
-				break;
-			case UPDATE_CONNECTION_OK:
-				/* refresh JSON */
-				if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
-					/* generate the connection info with success */
-					wifi_manager_generate_ip_info_json( UPDATE_CONNECTION_OK );
-					wifi_manager_unlock_json_buffer();
-				}
-				break;
-			case ORDER_DISCONNECT_STA:
-				ESP_LOGD(TAG,   "MESSAGE: ORDER_DISCONNECT_STA. Calling esp_wifi_disconnect()");
-
-				/* precise this is coming from a user request */
-				xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_DISCONNECT_BIT);
-
-				/* order wifi discconect */
-				ESP_ERROR_CHECK(esp_wifi_disconnect());
-
-				/* callback */
-				if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
-
-				break;
-			case  ORDER_RESTART_OTA:
-				ESP_LOGD(TAG,   "Calling guided_restart_ota.");
-				guided_restart_ota();
-				break;
-			case  ORDER_RESTART_OTA_URL:
-				ESP_LOGD(TAG,   "Calling start_ota.");
-				start_ota(msg.param, NULL, 0);
-				free(msg.param);
-				break;
-
-			case  ORDER_RESTART_RECOVERY:
-				ESP_LOGD(TAG,   "Calling guided_factory.");
-				guided_factory();
-				break;
-			case	ORDER_RESTART:
-				ESP_LOGD(TAG,   "Calling simple_restart.");
-				simple_restart();
-				break;
-			case ORDER_UPDATE_STATUS:
-				wifi_manager_update_basic_info();
-				break;
-			default:
-				break;
-
-			} /* end of switch/case */
-		} /* end of if status=pdPASS */
-	} /* end of for loop */
-
-	vTaskDelete( NULL );
-}

BIN
file-size.txt


BIN
file_size.txt


+ 17 - 67
main/Kconfig.projbuild

@@ -1,12 +1,12 @@
 menu "Squeezelite-ESP32"
 	menu "Logging"
 		config LOGGING_SLIMPROTO
-        	string "logging level for slimproto "
+        	string "logging level for slimproto"
         	default "info"
         	help
         		Set logging level info|debug|sdebug
 		config LOGGING_STREAM
-        	string "logging level for stream "
+        	string "logging level for stream"
         	default "info"
         	help
         		Set logging level info|debug|sdebug
@@ -101,103 +101,49 @@ menu "Squeezelite-ESP32"
 			default ""
 		config DAC_CONTROLSET
 			string
-			default "{ \"init\": [ {\"reg\":41, \"val\":128}, {\"reg\":18, \"val\":255} ], \"poweron\": [ {\"reg\":18, \"val\":64, \"mode\":\"or\"} ], \"poweroff\": [ {\"reg\":18, \"val\":191, \"mode\":\"and\"} ] }" if TWATCH2020
+			default '{ "init": [ {"reg":41, "val":128}, {"reg":18, "val":255} ], "poweron": [ {"reg":18, "val":64, "mode":"or"} ], "poweroff": [ {"reg":18, "val":191, "mode":"and" } ] }' if TWATCH2020
 			default ""		
 		# AGGREGATES - end				
 	endmenu
-
-	menu "Ethernet Options"
-		visible if BASIC_I2C_BT && (ETH_USE_ESP32_EMAC || ETH_USE_SPI_ETHERNET)
-		choice 
-			prompt "Ethernet Chipset"
-			default ETH_NODRIVER
-			config ETH_NODRIVER
-				bool "Defined in NVS"			   
-			config ETH_LAN8720
-				bool "Microchip LAN8720 (RMII)"
-			config ETH_DM9051
-				bool "Davicom 9051 (SPI)"				
-		endchoice	
-		config ETH_PHY_RST_IO
-			int "PHY Reset GPIO number" if !ETH_NODRIVER
-			default -1
-			help
-				Set the GPIO number used to reset PHY chip.
-				Set to -1 to disable PHY chip hardware reset.		
-		config ETH_MDC_IO
-			int "SMI MDC GPIO number" if ETH_LAN8720
-			default -1
-			help
-				Set the GPIO number used by SMI MDC.		
-		config ETH_MDIO_IO
-			int "SMI MDIO GPIO number" if ETH_LAN8720
-			default -1
-			help
-				Set the GPIO number used by SMI MDIO.		
-		config ETH_SPI_HOST
-			int "SPI host number (-1,1 or 2)" if ETH_DM9051
-			default -1
-			help
-				Set to -1 to use system's SPI config (see Various I/O)
-				Set to 2 or 3 to use a dedicated bus 
-		config ETH_SPI_INTR_IO
-			int "interrupt" if ETH_DM9051
-			default -1													
-		config ETH_SPI_CS_IO
-			int "Chip Select" if ETH_DM9051
-			default -1								
-		config ETH_SPI_CLK_IO
-			int "SPI clock" if ETH_SPI_HOST != -1 && ETH_DM9051
-			default -1
-		config ETH_SPI_MOSI_IO
-			int "Data Out" if ETH_SPI_HOST != -1 && ETH_DM9051
-			default -1				
-		config ETH_SPI_MISO_IO
-			int "Data In"  if ETH_SPI_HOST != -1 && ETH_DM9051
-			default -1
-		config ETH_SPI_SPEED
-			int "SPI speed (Hz)" if ETH_SPI_HOST != -1 && ETH_DM9051
-			default 20000000
-	endmenu
 	
 	menu "Audio settings"
 		menu "DAC settings" 
 			visible if BASIC_I2C_BT
 			menu "I2S settings"
 				config I2S_NUM         
-					int "I2S channel (0 or 1). "
+					int "I2S channel (0 or 1)."
 					default 0
 					help
 						I2S dma channel to use.  
 				config I2S_BCK_IO         
-					int "I2S Bit clock GPIO number. "
+					int "I2S Bit clock GPIO number."
 					default -1 
 					help
 						I2S Bit Clock gpio pin to use.  
 				config I2S_WS_IO         
-					int "I2S Word Select GPIO number. "
+					int "I2S Word Select GPIO number."
 					default -1 
 					help
 						I2S Word Select gpio pin to use.
 				config I2S_DO_IO         
-					int "I2S Data Output GPIO number. "
+					int "I2S Data Output GPIO number."
 					default -1
 					help
 						I2S data output gpio pin to use.
 				config I2S_DI_IO         
-					int "I2S Data Input GPIO number. "
+					int "I2S Data Input GPIO number."
 					default -1
 					help
 						I2S data input gpio pin to use (not used mostly, leave it to -1).					
 			endmenu
 			menu "I2C settings"	
 				config I2C_SDA
-					int "I2C SDA GPIO number for DAC control. "
+					int "I2C SDA GPIO number for DAC control."
 					default -1
 					help
 						I2C data gpio pin to use with DAC (not used mostly, leave it to -1).										
 				config I2C_SCL
-					int "I2C SCL GPIO number for DAC control. "
+					int "I2C SCL GPIO number for DAC control."
 					default -1
 					help
 						I2C clock gpio pin to use with DAC (not used mostly, leave it to -1).															
@@ -249,7 +195,7 @@ menu "Squeezelite-ESP32"
 		        help
 		            This is the name of the device that the Bluetooth speaker will see when it is connected to.
 		    config A2DP_CONTROL_DELAY_MS
-		        int "Control loop delay. "
+		        int "Control loop delay."
 		        default 500
 		        help
 		            Decreasing this will lead to a more responsive BT control, but might lead to noisy log files if debug is enabled.
@@ -289,7 +235,7 @@ menu "Squeezelite-ESP32"
 		config AIRPLAY_PORT
 			depends on AIRPLAY_SINK
 			string "AirPlay listening port"
-				default 5000
+				default "5000"
 		    help
 				AirPlay service listening port
 	endmenu	
@@ -401,5 +347,9 @@ menu "Squeezelite-ESP32"
 			help
 				Set the scaling factor for this 12 bits ADC
 	endmenu	
-	
+	config DEFAULT_COMMAND_LINE
+        string "Default command line to execute"
+        default "squeezelite -o I2S -b 500:2000 -d all=info -C 30"
+        help
+        This is the command to run when starting the device
 endmenu

+ 80 - 155
main/esp_app_main.c

@@ -30,7 +30,7 @@
 #include "lwip/netdb.h"
 #include "nvs_utilities.h"
 #include "trace.h"
-#include "wifi_manager.h"
+#include "network_manager.h"
 #include "squeezelite-ota.h"
 #include <math.h>
 #include "audio_controls.h"
@@ -256,164 +256,91 @@ const char * get_certificate(){
 }
 
 #define DEFAULT_NAME_WITH_MAC(var,defval) char var[strlen(defval)+sizeof(macStr)]; strcpy(var,defval); strcat(var,macStr)
-void register_default_nvs(){
-	uint8_t mac[6];
-	char macStr[LOCAL_MAC_SIZE+1];
-	char default_command_line[strlen(CONFIG_DEFAULT_COMMAND_LINE)+sizeof(macStr)];
-
-	esp_read_mac((uint8_t *)&mac, ESP_MAC_WIFI_STA);
-	snprintf(macStr, LOCAL_MAC_SIZE-1,"-%x%x%x", mac[3], mac[4], mac[5]);
-
-	DEFAULT_NAME_WITH_MAC(default_bt_name,CONFIG_BT_NAME);
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "bt_name", default_bt_name);
-	config_set_default(NVS_TYPE_STR, "bt_name", default_bt_name, 0);
-
-	DEFAULT_NAME_WITH_MAC(default_host_name,DEFAULT_HOST_NAME);
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "host_name", default_host_name);
-	config_set_default(NVS_TYPE_STR, "host_name", default_host_name, 0);
-
-	DEFAULT_NAME_WITH_MAC(default_airplay_name,CONFIG_AIRPLAY_NAME);
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "airplay_name",default_airplay_name);
-	config_set_default(NVS_TYPE_STR, "airplay_name",default_airplay_name , 0);
-
-	DEFAULT_NAME_WITH_MAC(default_ap_name,CONFIG_DEFAULT_AP_SSID);
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "ap_ssid", default_ap_name);
-	config_set_default(NVS_TYPE_STR, "ap_ssid",default_ap_name , 0);
-
-	strncpy(default_command_line, CONFIG_DEFAULT_COMMAND_LINE,sizeof(default_command_line)-1);
-	strncat(default_command_line, " -n ",sizeof(default_command_line)-1);
-	strncat(default_command_line, default_host_name,sizeof(default_command_line)-1);
-
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "autoexec", "1");
-	config_set_default(NVS_TYPE_STR,"autoexec","1", 0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "autoexec1",default_command_line);
-	config_set_default(NVS_TYPE_STR,"autoexec1",default_command_line,0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "a2dp_sink_name", CONFIG_A2DP_SINK_NAME);
-	config_set_default(NVS_TYPE_STR, "a2dp_sink_name", CONFIG_A2DP_SINK_NAME, 0);
+void register_default_string_val(const char * key, char * value){
+	char * existing =(char *)config_alloc_get(NVS_TYPE_STR,key );
+	ESP_LOGD(TAG,"Register default called with:  %s= %s",key,value );
+	if(!existing) {
+		ESP_LOGI(TAG,"Registering default value for key %s, value %s",key,value );
+		config_set_default(NVS_TYPE_STR, key,value, 0);
+	}
+	else {
+		ESP_LOGD(TAG,"Value found for %s: %s",key,existing );
+	}
+	FREE_AND_NULL(existing);
+}
 
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "a2dp_sink_name", STR(CONFIG_A2DP_SINK_NAME));
-	config_set_default(NVS_TYPE_STR, "a2dp_ctmt", STR(CONFIG_A2DP_CONNECT_TIMEOUT_MS), 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "a2dp_ctmt", STR(CONFIG_A2DP_CONNECT_TIMEOUT_MS));
-	config_set_default(NVS_TYPE_STR, "a2dp_ctrld", STR(CONFIG_A2DP_CONTROL_DELAY_MS), 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "release_url", CONFIG_SQUEEZELITE_ESP32_RELEASE_URL);
-	config_set_default(NVS_TYPE_STR, "release_url", CONFIG_SQUEEZELITE_ESP32_RELEASE_URL, 0);
+void register_default_with_mac(const char* key,  char* defval) {
+    uint8_t mac[6];
+    char macStr[LOCAL_MAC_SIZE + 1];
+    char* fullvalue = NULL;
+    esp_read_mac((uint8_t*)&mac, ESP_MAC_WIFI_STA);
+    snprintf(macStr, LOCAL_MAC_SIZE - 1, "-%x%x%x", mac[3], mac[4], mac[5]);
+	fullvalue = malloc(strlen(defval)+sizeof(macStr)+1);
+	if(fullvalue){
+		strcpy(fullvalue, defval);
+		strcat(fullvalue, macStr);
+		register_default_string_val(key,fullvalue);
+		FREE_AND_NULL(fullvalue);
+	}
+	else {
+		ESP_LOGE(TAG,"Memory allocation failed when registering default value for %s", key);
+	}
 	
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s","ap_ip_address",CONFIG_DEFAULT_AP_IP );
-	config_set_default(NVS_TYPE_STR, "ap_ip_address",CONFIG_DEFAULT_AP_IP , 0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "ap_ip_gateway",CONFIG_DEFAULT_AP_GATEWAY );
-	config_set_default(NVS_TYPE_STR, "ap_ip_gateway",CONFIG_DEFAULT_AP_GATEWAY , 0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s","ap_ip_netmask",CONFIG_DEFAULT_AP_NETMASK );
-	config_set_default(NVS_TYPE_STR, "ap_ip_netmask",CONFIG_DEFAULT_AP_NETMASK , 0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "ap_channel",STR(CONFIG_DEFAULT_AP_CHANNEL));
-	config_set_default(NVS_TYPE_STR, "ap_channel",STR(CONFIG_DEFAULT_AP_CHANNEL) , 0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "ap_pwd", CONFIG_DEFAULT_AP_PASSWORD);
-	config_set_default(NVS_TYPE_STR, "ap_pwd", CONFIG_DEFAULT_AP_PASSWORD, 0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "airplay_port", CONFIG_AIRPLAY_PORT);
-	config_set_default(NVS_TYPE_STR, "airplay_port", CONFIG_AIRPLAY_PORT, 0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "a2dp_dev_name", CONFIG_A2DP_DEV_NAME);
-	config_set_default(NVS_TYPE_STR, "a2dp_dev_name", CONFIG_A2DP_DEV_NAME, 0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "bypass_wm", "0");
-	config_set_default(NVS_TYPE_STR, "bypass_wm", "0", 0);
-
-	ESP_LOGD(TAG,"Registering default value for equalizer");
-	config_set_default(NVS_TYPE_STR, "equalizer", "", 0);
+}
 
-	ESP_LOGD(TAG,"Registering default Audio control board type %s, value ","actrls_config");
-	config_set_default(NVS_TYPE_STR, "actrls_config", "", 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s", "lms_ctrls_raw");
-	config_set_default(NVS_TYPE_STR, "lms_ctrls_raw", "n", 0);
-	
-	ESP_LOGD(TAG,"Registering default Audio control board type %s, value %s", "rotary_config", CONFIG_ROTARY_ENCODER);
-	config_set_default(NVS_TYPE_STR, "rotary_config", CONFIG_ROTARY_ENCODER, 0);
+void register_default_nvs(){
 
+	register_default_with_mac("bt_name", CONFIG_BT_NAME);
+	register_default_with_mac("host_name", DEFAULT_HOST_NAME);
+	register_default_with_mac("airplay_name", CONFIG_AIRPLAY_NAME);
+	register_default_with_mac("ap_ssid", CONFIG_DEFAULT_AP_SSID);
+	register_default_string_val("autoexec","1");
+	register_default_with_mac("autoexec1",CONFIG_DEFAULT_COMMAND_LINE " -n " DEFAULT_HOST_NAME);	
+	register_default_string_val("a2dp_sink_name", CONFIG_A2DP_SINK_NAME);
+	register_default_string_val("a2dp_ctmt", STR(CONFIG_A2DP_CONNECT_TIMEOUT_MS));
+	register_default_string_val("a2dp_ctrld", STR(CONFIG_A2DP_CONTROL_DELAY_MS));
+	register_default_string_val("release_url", CONFIG_SQUEEZELITE_ESP32_RELEASE_URL);
+	register_default_string_val("ap_ip_address",CONFIG_DEFAULT_AP_IP);
+	register_default_string_val("ap_ip_gateway",CONFIG_DEFAULT_AP_GATEWAY );
+	register_default_string_val("ap_ip_netmask",CONFIG_DEFAULT_AP_NETMASK);
+	register_default_string_val("ap_channel",STR(CONFIG_DEFAULT_AP_CHANNEL));
+	register_default_string_val("ap_pwd", CONFIG_DEFAULT_AP_PASSWORD);
+	register_default_string_val("airplay_port", CONFIG_AIRPLAY_PORT);
+	register_default_string_val("a2dp_dev_name", CONFIG_A2DP_DEV_NAME);
+	register_default_string_val("bypass_wm", "0");
+	register_default_string_val("equalizer", "");
+	register_default_string_val("actrls_config", "");	
+	register_default_string_val("lms_ctrls_raw", "n");	
+	register_default_string_val("rotary_config", CONFIG_ROTARY_ENCODER);
 	char number_buffer[101] = {};
 	snprintf(number_buffer,sizeof(number_buffer)-1,"%u",OTA_FLASH_ERASE_BLOCK);
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "ota_erase_blk", number_buffer);
-	config_set_default(NVS_TYPE_STR, "ota_erase_blk", number_buffer, 0);
-
+	register_default_string_val( "ota_erase_blk", number_buffer);
 	snprintf(number_buffer,sizeof(number_buffer)-1,"%u",OTA_STACK_SIZE);
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "ota_stack", number_buffer);
-	config_set_default(NVS_TYPE_STR, "ota_stack", number_buffer, 0);
-
+	register_default_string_val( "ota_stack", number_buffer);
 	snprintf(number_buffer,sizeof(number_buffer)-1,"%d",OTA_TASK_PRIOTITY);
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "ota_prio", number_buffer);
-	config_set_default(NVS_TYPE_STR, "ota_prio", number_buffer, 0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "enable_bt_sink", STR(CONFIG_BT_SINK));
-	config_set_default(NVS_TYPE_STR, "enable_bt_sink", STR(CONFIG_BT_SINK), 0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "bt_sink_pin", STR(CONFIG_BT_SINK_PIN));
-	config_set_default(NVS_TYPE_STR, "bt_sink_pin", STR(CONFIG_BT_SINK_PIN), 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "bt_sink_volume", "127");
-	config_set_default(NVS_TYPE_STR, "bt_sink_volume", "127", 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "enable_airplay", STR(CONFIG_AIRPLAY_SINK));
-	config_set_default(NVS_TYPE_STR, "enable_airplay", STR(CONFIG_AIRPLAY_SINK), 0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "display_config", CONFIG_DISPLAY_CONFIG);
-	config_set_default(NVS_TYPE_STR, "display_config", CONFIG_DISPLAY_CONFIG, 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "eth_config", CONFIG_ETH_CONFIG);
-	config_set_default(NVS_TYPE_STR, "eth_config", CONFIG_ETH_CONFIG, 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "i2c_config", CONFIG_I2C_CONFIG);
-	config_set_default(NVS_TYPE_STR, "i2c_config", CONFIG_I2C_CONFIG, 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "spi_config", CONFIG_SPI_CONFIG);
-	config_set_default(NVS_TYPE_STR, "spi_config", CONFIG_SPI_CONFIG, 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s, value %s", "set_GPIO", CONFIG_SET_GPIO);
-	config_set_default(NVS_TYPE_STR, "set_GPIO", CONFIG_SET_GPIO, 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s", "led_brightness");
-	config_set_default(NVS_TYPE_STR, "led_brightness", "", 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s", "spdif_config");
-	config_set_default(NVS_TYPE_STR, "spdif_config", "", 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s", "dac_config");
-	config_set_default(NVS_TYPE_STR, "dac_config", "", 0);
-	//todo: add dac_config for known targets
-	ESP_LOGD(TAG,"Registering default value for key %s", "dac_controlset");
-	config_set_default(NVS_TYPE_STR, "dac_controlset", "", 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s", "jack_mutes_amp");
-	config_set_default(NVS_TYPE_STR, "jack_mutes_amp", "n", 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s", "bat_config");
-	config_set_default(NVS_TYPE_STR, "bat_config", "", 0);
-			
-	ESP_LOGD(TAG,"Registering default value for key %s", "metadata_config");
-	config_set_default(NVS_TYPE_STR, "metadata_config", "", 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s", "telnet_enable");
-	config_set_default(NVS_TYPE_STR, "telnet_enable", "", 0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s", "telnet_buffer");
-	config_set_default(NVS_TYPE_STR, "telnet_buffer", "40000", 0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s", "telnet_block");
-	config_set_default(NVS_TYPE_STR, "telnet_block", "500", 0);
-	
-	ESP_LOGD(TAG,"Registering default value for key %s", "stats");
-	config_set_default(NVS_TYPE_STR, "stats", "n", 0);
-
-	ESP_LOGD(TAG,"Registering default value for key %s", "rel_api");
-	config_set_default(NVS_TYPE_STR, "rel_api", CONFIG_RELEASE_API, 0);
-
+	register_default_string_val( "ota_prio", number_buffer);
+	register_default_string_val( "enable_bt_sink", STR(CONFIG_BT_SINK));
+	register_default_string_val( "bt_sink_pin", STR(CONFIG_BT_SINK_PIN));
+	register_default_string_val( "bt_sink_volume", "127");
+	register_default_string_val( "enable_airplay", STR(CONFIG_AIRPLAY_SINK));
+	register_default_string_val( "display_config", CONFIG_DISPLAY_CONFIG);
+	register_default_string_val( "eth_config", CONFIG_ETH_CONFIG);
+	register_default_string_val( "i2c_config", CONFIG_I2C_CONFIG);
+	register_default_string_val( "spi_config", CONFIG_SPI_CONFIG);
+	register_default_string_val( "set_GPIO", CONFIG_SET_GPIO);
+	register_default_string_val( "led_brightness", "");
+	register_default_string_val( "spdif_config", "");
+	register_default_string_val( "dac_config", "");
+	register_default_string_val( "dac_controlset", "");
+	register_default_string_val( "jack_mutes_amp", "n");
+	register_default_string_val( "bat_config", "");
+	register_default_string_val( "metadata_config", "");
+	register_default_string_val( "telnet_enable", "");
+	register_default_string_val( "telnet_buffer", "40000");
+	register_default_string_val( "telnet_block", "500");
+	register_default_string_val( "stats", "n");
+	register_default_string_val( "rel_api", CONFIG_RELEASE_API);
+	register_default_string_val("wifi_smode", "A");
 	wait_for_commit();
 	ESP_LOGD(TAG,"Done setting default values in nvs.");
 }
@@ -507,13 +434,11 @@ void app_main()
 	led_blink_pushed(LED_GREEN, 250, 250);
 
 	if(bypass_wifi_manager){
-		ESP_LOGW(TAG,"*******************************************************************************************");
-		ESP_LOGW(TAG,"* wifi manager is disabled. Please use wifi commands to connect to your wifi access point.");
-		ESP_LOGW(TAG,"*******************************************************************************************");
+		ESP_LOGW(TAG,"wifi manager is disabled. Use command line for wifi control.");
 	}
 	else {
 		ESP_LOGI(TAG,"Starting Wifi Manager");
-		wifi_manager_start();
+		network_manager_start();
 		//wifi_manager_set_callback(EVENT_STA_GOT_IP, &cb_connection_got_ip);
 		wifi_manager_set_callback(EVENT_ETH_GOT_IP, &cb_connection_got_ip);
 		wifi_manager_set_callback(EVENT_STA_DISCONNECTED, &cb_connection_sta_disconnected);

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 567 - 241
sdkconfig


+ 3 - 3
sdkconfig.defaults

@@ -509,7 +509,7 @@ CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20
 CONFIG_ESP32_PHY_MAX_TX_POWER=20
 
 
-CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y
+CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y
 
 
 CONFIG_FATFS_CODEPAGE_437=y
@@ -781,8 +781,8 @@ CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
 
 CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y
 CONFIG_VFS_SUPPORT_TERMIOS=y
-CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1
-CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128
+CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1
+CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN=128
 
 CONFIG_WL_SECTOR_SIZE_512=y
 #CONFIG_WL_SECTOR_SIZE_4096 is not defined

+ 5 - 9
squeezelite.cmake

@@ -1,17 +1,13 @@
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 
 function(___register_flash partition_name sub_type)
-
     message(STATUS "Adding new build target (from build folder): ninja ${partition_name}-flash")
 	partition_table_get_partition_info(otaapp_offset "--partition-type app --partition-subtype ${sub_type}" "offset")
-	esptool_py_flash_project_args(${partition_name} ${otaapp_offset} ${build_dir}/${partition_name}.bin FLASH_IN_PROJECT )
-	esptool_py_custom_target(${partition_name}-flash ${partition_name} "${build_dir}/${partition_name}.bin")
-## IDF-V4.2+ 	idf_component_get_property(main_args esptool_py FLASH_ARGS)
-## IDF-V4.2+ 	idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS)
-## IDF-V4.2+    esptool_py_flash_target(${target_name}-flash "${main_args}" "${sub_args}")
-## IDF-V4.2+ 	esptool_py_flash_target_image(${target_name}-flash ${target_name} "${otaapp_offset}" "${build_dir}/${target_name}.bin")
-## IDF-V4.2+ 	esptool_py_flash_target_image(flash ${target_name} "${otaapp_offset}" "${build_dir}/${target_name}.bin")
-	
+	idf_component_get_property(main_args esptool_py FLASH_ARGS)
+	idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS)
+	esptool_py_flash_target(${partition_name}-flash "${main_args}" "${sub_args}")
+	esptool_py_flash_target_image(${partition_name}-flash ${partition_name} "${otaapp_offset}" "${build_dir}/${partition_name}.bin")
+	esptool_py_flash_target_image(flash ${partition_name} "${otaapp_offset}" "${build_dir}/${partition_name}.bin")
 endfunction()
 #
 # Removes the specified compile flag from the specified target.

+ 1 - 1
test/main/unit_tests.c

@@ -43,7 +43,7 @@
 #include "lwip/netdb.h"
 #include "nvs_utilities.h"
 #include "trace.h"
-#include "wifi_manager.h"
+#include "network_manager.h"
 #include "squeezelite-ota.h"
 #include <math.h>
 #include "audio_controls.h"

Vissa filer visades inte eftersom för många filer har ändrats