Просмотр исходного кода

cpp state machine for ethernet

Sebastien L 3 лет назад
Родитель
Сommit
81756a7649
43 измененных файлов с 4065 добавлено и 2552 удалено
  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 )
 set_property(TARGET recovery.elf PROPERTY RECOVERY_PREFIX app_recovery )
 include(squeezelite.cmake)
 include(squeezelite.cmake)
 set(PROJECT_VER $ENV{PROJECT_VER})
 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
 // 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.)
    This example code is in the Public Domain (or CC0 licensed, at your option.)
 
 
@@ -29,7 +29,7 @@
 #include "freertos/FreeRTOS.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/event_groups.h"
 #include "freertos/event_groups.h"
 #include "esp_wifi.h"
 #include "esp_wifi.h"
-#include "tcpip_adapter.h"
+#include "esp_netif.h"
 #include "esp_event.h"
 #include "esp_event.h"
 #include "led.h"
 #include "led.h"
 extern bool bypass_wifi_manager;
 extern bool bypass_wifi_manager;
@@ -98,7 +98,7 @@ static void initialise_wifi(void)
     if (initialized) {
     if (initialized) {
         return;
         return;
     }
     }
-    tcpip_adapter_init();
+    esp_netif_init();
     // Now moved to esp_app_main: wifi_event_group = xEventGroupCreate();
     // Now moved to esp_app_main: wifi_event_group = xEventGroupCreate();
     ESP_ERROR_CHECK(esp_event_loop_create_default());
     ESP_ERROR_CHECK(esp_event_loop_create_default());
     wifi_init_config_t cfg = WIFI_INIT_CONFIG_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 */
 	/* Disable buffering on stdin */
 	setvbuf(stdin, NULL, _IONBF, 0);
 	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
 	/* Configure UART. Note that REF_TICK is used so that the baud rate remains
 	 * correct while APB frequency is changing in light sleep mode.
 	 * correct while APB frequency is changing in light sleep mode.
 	 */
 	 */
 	const uart_config_t uart_config = { .baud_rate =
 	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,
 			.parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1,
 			.use_ref_tick = true };
 			.use_ref_tick = true };
 	ESP_ERROR_CHECK(uart_param_config(CONFIG_ESP_CONSOLE_UART_NUM, &uart_config));
 	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 "mdns.h"
 #include "nvs.h"
 #include "nvs.h"
-#include "tcpip_adapter.h"
-// IDF-V4++ #include "esp_netif.h"
+#include "esp_netif.h"
 #include "esp_log.h"
 #include "esp_log.h"
 #include "esp_console.h"
 #include "esp_console.h"
 #include "esp_pthread.h"
 #include "esp_pthread.h"

+ 1 - 1
components/raop/util.c

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

+ 81 - 28
components/services/accessors.c

@@ -15,7 +15,6 @@
 #include "accessors.h"
 #include "accessors.h"
 #include "globdefs.h"
 #include "globdefs.h"
 #include "display.h"
 #include "display.h"
-#include "display.h"
 #include "cJSON.h"
 #include "cJSON.h"
 #include "driver/gpio.h"
 #include "driver/gpio.h"
 #include "stdbool.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
  * Get i2s config structure from config string
  */
  */
 const i2s_platform_config_t * config_get_i2s_from_str(char * dac_config ){
 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);
 	set_i2s_pin(dac_config, &i2s_dac_pin.pin);
 	strcpy(i2s_dac_pin.model, "i2s");
 	strcpy(i2s_dac_pin.model, "i2s");
 	char * p=NULL;
 	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
  * Get eth config structure from config string
  */
  */
 const eth_config_t * config_get_eth_from_str(char * eth_config ){
 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;
 	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, "model")) != NULL) sscanf(p, "%*[^=]=%15[^,]", eth_pin.model);
 	if ((p = strcasestr(eth_config, "mdc")) != NULL) eth_pin.mdc = atoi(strchr(p, '=') + 1);
 	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, "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, "clk")) != NULL) eth_pin.clk = atoi(strchr(p, '=') + 1);
 	if ((p = strcasestr(eth_config, "host")) != NULL) eth_pin.host = 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;
 	return &eth_pin;
 }
 }
 
 
@@ -196,22 +198,37 @@ const i2s_platform_config_t * config_dac_get(){
  */
  */
 const eth_config_t * config_eth_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) 
 	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"
 										 ",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)
 										 ",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) 
 										 ",mosi=" STR(CONFIG_ETH_SPI_MOSI_IO) ",miso=" STR(CONFIG_ETH_SPI_MISO_IO) 
 										 ",intr=" STR(CONFIG_ETH_SPI_INTR_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;
 	static EXT_RAM_ATTR eth_config_t eth_config;
 	ESP_LOGD(TAG, "Ethernet config string %s", config);	
 	ESP_LOGD(TAG, "Ethernet config string %s", config);	
 	memcpy(&eth_config, config_get_eth_from_str(config), sizeof(eth_config));
 	memcpy(&eth_config, config_get_eth_from_str(config), sizeof(eth_config));
 	free(config);
 	free(config);
 	return &eth_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) {
 const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host) {
 	char *nvs_item, *p;
 	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);
 	nvs_item = config_alloc_get_str("spi_config", CONFIG_SPI_CONFIG, NULL);
 	if (nvs_item) {
 	if (nvs_item) {
 		if ((p = strcasestr(nvs_item, "data")) != NULL) spi.mosi_io_num = atoi(strchr(p, '=') + 1);
 		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;
 	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_I2C_GPIO(gpio_list);
 	gpio_list=get_DAC_GPIO(gpio_list);
 	gpio_list=get_DAC_GPIO(gpio_list);
 	gpio_list=get_psram_gpio_list(gpio_list);
 	gpio_list=get_psram_gpio_list(gpio_list);
+	gpio_list=get_eth_GPIO(gpio_list);
 	return gpio_list;
 	return gpio_list;
 }
 }

+ 4 - 1
components/services/accessors.h

@@ -31,8 +31,10 @@ typedef struct {
 } display_config_t;
 } display_config_t;
 
 
 typedef struct {
 typedef struct {
-	bool rmii;
 	char model[16];
 	char model[16];
+	bool valid;
+	bool rmii;
+	bool spi;
 	int rst;
 	int rst;
 	int mdc, mdio;
 	int mdc, mdio;
 	int host;
 	int host;
@@ -86,6 +88,7 @@ typedef struct {
 
 
 const display_config_t * 	config_display_get();
 const display_config_t * 	config_display_get();
 const eth_config_t * 		config_eth_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_display_set(const display_config_t * config);
 esp_err_t 					config_i2c_set(const i2c_config_t * config, int port);
 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);
 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;
 	TimerHandle_t timer;
 } buttons[MAX_BUTTONS];
 } buttons[MAX_BUTTONS];
 
 
-static EXT_RAM_ATTR struct {
+static struct {
 	int gpio, level;
 	int gpio, level;
 	struct button_s *button;
 	struct button_s *button;
 } polled_gpio[] = { {36, -1, NULL}, {39, -1, NULL}, {-1, -1, NULL} };
 } 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/i2s.h"
 #include "driver/rtc_io.h"
 #include "driver/rtc_io.h"
 #include "driver/dac.h"
 #include "driver/dac.h"
-#include <adc1_i2s_private.h>
+#include "adc1_private.h"
 
 
 #include "esp_intr_alloc.h"
 #include "esp_intr_alloc.h"
 #include "esp_err.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.
         //initialize the specific ADC channel.
         //in the current stage, we only support ADC1 and single channel mode.
         //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.
         //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.
     // configure I2S data port interface.
     i2s_reset_fifo(i2s_num);
     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.rx_pdm_en = 0;
         I2S[i2s_num]->pdm_conf.tx_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)) {
     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;
         I2S[i2s_num]->conf.sig_loopback = 1;
         if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) {
         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] != 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);
     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();
     _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);
     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->type = type;
 	message->msg_class = msg_class;
 	message->msg_class = msg_class;
 	message->sent_time = esp_timer_get_time() / 1000;
 	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){
 	while(cur){
 		messaging_post_to_queue(get_handle_ptr(cur),  message, msg_size);
 		messaging_post_to_queue(get_handle_ptr(cur),  message, msg_size);
 		cur = get_struct_ptr(cur->next);
 		cur = get_struct_ptr(cur->next);

+ 7 - 0
components/services/messaging.h

@@ -3,6 +3,10 @@
 #include "freertos/ringbuf.h"
 #include "freertos/ringbuf.h"
 #include "cJSON.h"
 #include "cJSON.h"
 #pragma once
 #pragma once
+#ifdef __cplusplus
+extern "C" {
+
+#endif
 typedef enum {
 typedef enum {
 	MESSAGING_INFO,
 	MESSAGING_INFO,
 	MESSAGING_WARNING,
 	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__)
 #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
 #endif
 
 
 #include "esp_err.h"
 #include "esp_err.h"
-#include "tcpip_adapter.h"
+#include "esp_netif.h"
 // IDF-V4++ #include "esp_netif.h"
 // IDF-V4++ #include "esp_netif.h"
 
 
 #ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET
 #ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET

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

@@ -20,8 +20,7 @@
 #include "cmd_system.h"
 #include "cmd_system.h"
 #include "esp_err.h"
 #include "esp_err.h"
 #include "squeezelite-ota.h"
 #include "squeezelite-ota.h"
-#include "tcpip_adapter.h"
-// IDF-V4++ #include "esp_netif.h"
+#include "esp_netif.h"
 #include "platform_config.h"
 #include "platform_config.h"
 #include <time.h>
 #include <time.h>
 #include <sys/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 );
 	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);
 	buf_handle = xRingbufferCreateStatic(log_buf_size, RINGBUF_TYPE_BYTEBUF, buffer_storage, buffer_struct);
 	if (buf_handle == NULL) {
 	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");
 		messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Failed to allocate memory for telnet buffer");
-
 		return;
 		return;
 	}
 	}
 
 

+ 4 - 1
components/tools/trace.h

@@ -21,7 +21,10 @@
 #ifndef STR_OR_ALT
 #ifndef STR_OR_ALT
 #define STR_OR_ALT(str,alt) (str?str:alt)
 #define STR_OR_ALT(str,alt) (str?str:alt)
 #endif
 #endif
-
+#define ENUM_TO_STRING(g) \
+    case g:     \
+        return STR(g);    \
+        break;
 extern const char unknown_string_placeholder[];
 extern const char unknown_string_placeholder[];
 extern const char * str_or_unknown(const char * str);
 extern const char * str_or_unknown(const char * str);
 extern const char * str_or_null(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
 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/
 						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 
 						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
 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 <byteswap.h>
 #include "squeezelite-ota.h"
 #include "squeezelite-ota.h"
-#include "wifi_manager.h"
+#include "network_manager.h"
 
 
 static const char TAG[] = "dns_server";
 static const char TAG[] = "dns_server";
 static TaskHandle_t task_dns_server = NULL;
 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 "platform_console.h"
 #include "accessors.h"
 #include "accessors.h"
 #include "webapp/webpack.h"
 #include "webapp/webpack.h"
+#include "network_wifi.h"
+#include "network_status.h"
  
  
 #define HTTP_STACK_SIZE	(5*1024)
 #define HTTP_STACK_SIZE	(5*1024)
 const char str_na[]="N/A";
 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
     	// todo:  redirect to login page
     	// return ESP_OK;
     	// return ESP_OK;
     }
     }
-	wifi_manager_scan_async();
+	network_manager_async_scan();
 	esp_err_t err = set_content_type_from_req(req);
 	esp_err_t err = set_content_type_from_req(req);
 	if(err == ESP_OK){
 	if(err == ESP_OK){
 		httpd_resp_send(req, (const char *)empty, HTTPD_RESP_USE_STRLEN);
 		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);
 			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);
 		free(otaURL);
 	}
 	}
     return err;
     return err;
@@ -789,8 +791,8 @@ esp_err_t connect_post_handler(httpd_req_t *req){
 		if(password){
 		if(password){
 			strlcpy((char *)config->sta.password, password, sizeof(config->sta.password)+1);
 			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));
 		httpd_resp_send(req, (const char *)success, strlen(success));
 	}
 	}
 	else {
 	else {
@@ -814,7 +816,7 @@ esp_err_t connect_delete_handler(httpd_req_t *req){
 		return err;
 		return err;
 	}
 	}
 	httpd_resp_send(req, (const char *)success, strlen(success));
 	httpd_resp_send(req, (const char *)success, strlen(success));
-	wifi_manager_disconnect_async();
+	network_manager_async_disconnect();
 
 
     return ESP_OK;
     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));
 	httpd_resp_send(req, (const char *)success, strlen(success));
-	wifi_manager_reboot(OTA);
+	network_manager_async_reboot(OTA);
     return ESP_OK;
     return ESP_OK;
 }
 }
 esp_err_t reboot_post_handler(httpd_req_t *req){
 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;
 		return err;
 	}
 	}
 	httpd_resp_send(req, (const char *)success, strlen(success));
 	httpd_resp_send(req, (const char *)success, strlen(success));
-	wifi_manager_reboot(RESTART);
+	network_manager_async_reboot(RESTART);
 	return ESP_OK;
 	return ESP_OK;
 }
 }
 esp_err_t recovery_post_handler(httpd_req_t *req){
 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;
 		return err;
 	}
 	}
 	httpd_resp_send(req, (const char *)success, strlen(success));
 	httpd_resp_send(req, (const char *)success, strlen(success));
-	wifi_manager_reboot(RECOVERY);
+	network_manager_async_reboot(RECOVERY);
 	return ESP_OK;
 	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");
 		httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR , "Error retrieving status object");
 	}
 	}
 	// update status for next status call
 	// update status for next status call
-	wifi_manager_update_status();
+	network_manager_async_update_status();
 
 
 	return ESP_OK;
 	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 <stdlib.h>
 #include <stdbool.h>
 #include <stdbool.h>
 #include "esp_http_server.h"
 #include "esp_http_server.h"
-#include "wifi_manager.h"
+#include "network_manager.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/task.h"
 #include "freertos/event_groups.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
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 SOFTWARE.
 
 
-@file wifi_manager.h
+@file network_manager.h
 @author Tony Pottier
 @author Tony Pottier
 @brief Defines all functions necessary for esp32 to connect to a wifi/scan wifis
 @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 "esp_wifi_types.h"
 #include "squeezelite-ota.h"
 #include "squeezelite-ota.h"
 #include "cJSON.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.
  * @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.
  * @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
 #define JSON_ONE_APP_SIZE					99
 
 
-
-
-
 /**
 /**
  * @brief Defines the complete list of all messages that the wifi_manager can process.
  * @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,
 	ORDER_START_DNS_HIJACK = 11,
 	EVENT_STA_DISCONNECTED = 12,
 	EVENT_STA_DISCONNECTED = 12,
 	EVENT_SCAN_DONE = 13,
 	EVENT_SCAN_DONE = 13,
-	EVENT_STA_GOT_IP = 14,
+	EVENT_GOT_IP = 14,
 	ORDER_RESTART_OTA = 15,
 	ORDER_RESTART_OTA = 15,
 	ORDER_RESTART_RECOVERY = 16,
 	ORDER_RESTART_RECOVERY = 16,
 	ORDER_RESTART_OTA_URL = 17,
 	ORDER_RESTART_OTA_URL = 17,
 	ORDER_RESTART = 18,
 	ORDER_RESTART = 18,
 	ORDER_UPDATE_STATUS = 19,
 	ORDER_UPDATE_STATUS = 19,
 	EVENT_ETH_GOT_IP = 20,
 	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;
 }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_USER_DISCONNECT = 2,
 	UPDATE_LOST_CONNECTION = 3,
 	UPDATE_LOST_CONNECTION = 3,
 	UPDATE_FAILED_ATTEMPT_AND_RESTORE = 4,
 	UPDATE_FAILED_ATTEMPT_AND_RESTORE = 4,
+	UPDATE_ETHERNET_CONNECTED = 5
 
 
 }update_reason_code_t;
 }update_reason_code_t;
 
 
@@ -226,6 +252,7 @@ typedef enum connection_request_made_by_code_t{
 	CONNECTION_REQUEST_USER = 1,
 	CONNECTION_REQUEST_USER = 1,
 	CONNECTION_REQUEST_AUTO_RECONNECT = 2,
 	CONNECTION_REQUEST_AUTO_RECONNECT = 2,
 	CONNECTION_REQUEST_RESTORE_CONNECTION = 3,
 	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_MAX = 0x7fffffff /*force the creation of this enum as a 32 bit int */
 }connection_request_made_by_code_t;
 }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;
 //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.
  * 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
  * 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
  * 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_ap_list_json();
-char* wifi_manager_alloc_get_ip_info_json();
 cJSON * wifi_manager_clear_ap_list_json(cJSON **old);
 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
  * @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.
  * @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.
  * @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_clear_ip_info_json(cJSON **old);
 cJSON * wifi_manager_get_new_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();
 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.
  * @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*) );
 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
 #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 );
-}



+ 17 - 67
main/Kconfig.projbuild

@@ -1,12 +1,12 @@
 menu "Squeezelite-ESP32"
 menu "Squeezelite-ESP32"
 	menu "Logging"
 	menu "Logging"
 		config LOGGING_SLIMPROTO
 		config LOGGING_SLIMPROTO
-        	string "logging level for slimproto "
+        	string "logging level for slimproto"
         	default "info"
         	default "info"
         	help
         	help
         		Set logging level info|debug|sdebug
         		Set logging level info|debug|sdebug
 		config LOGGING_STREAM
 		config LOGGING_STREAM
-        	string "logging level for stream "
+        	string "logging level for stream"
         	default "info"
         	default "info"
         	help
         	help
         		Set logging level info|debug|sdebug
         		Set logging level info|debug|sdebug
@@ -101,103 +101,49 @@ menu "Squeezelite-ESP32"
 			default ""
 			default ""
 		config DAC_CONTROLSET
 		config DAC_CONTROLSET
 			string
 			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 ""		
 			default ""		
 		# AGGREGATES - end				
 		# AGGREGATES - end				
 	endmenu
 	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 "Audio settings"
 		menu "DAC settings" 
 		menu "DAC settings" 
 			visible if BASIC_I2C_BT
 			visible if BASIC_I2C_BT
 			menu "I2S settings"
 			menu "I2S settings"
 				config I2S_NUM         
 				config I2S_NUM         
-					int "I2S channel (0 or 1). "
+					int "I2S channel (0 or 1)."
 					default 0
 					default 0
 					help
 					help
 						I2S dma channel to use.  
 						I2S dma channel to use.  
 				config I2S_BCK_IO         
 				config I2S_BCK_IO         
-					int "I2S Bit clock GPIO number. "
+					int "I2S Bit clock GPIO number."
 					default -1 
 					default -1 
 					help
 					help
 						I2S Bit Clock gpio pin to use.  
 						I2S Bit Clock gpio pin to use.  
 				config I2S_WS_IO         
 				config I2S_WS_IO         
-					int "I2S Word Select GPIO number. "
+					int "I2S Word Select GPIO number."
 					default -1 
 					default -1 
 					help
 					help
 						I2S Word Select gpio pin to use.
 						I2S Word Select gpio pin to use.
 				config I2S_DO_IO         
 				config I2S_DO_IO         
-					int "I2S Data Output GPIO number. "
+					int "I2S Data Output GPIO number."
 					default -1
 					default -1
 					help
 					help
 						I2S data output gpio pin to use.
 						I2S data output gpio pin to use.
 				config I2S_DI_IO         
 				config I2S_DI_IO         
-					int "I2S Data Input GPIO number. "
+					int "I2S Data Input GPIO number."
 					default -1
 					default -1
 					help
 					help
 						I2S data input gpio pin to use (not used mostly, leave it to -1).					
 						I2S data input gpio pin to use (not used mostly, leave it to -1).					
 			endmenu
 			endmenu
 			menu "I2C settings"	
 			menu "I2C settings"	
 				config I2C_SDA
 				config I2C_SDA
-					int "I2C SDA GPIO number for DAC control. "
+					int "I2C SDA GPIO number for DAC control."
 					default -1
 					default -1
 					help
 					help
 						I2C data gpio pin to use with DAC (not used mostly, leave it to -1).										
 						I2C data gpio pin to use with DAC (not used mostly, leave it to -1).										
 				config I2C_SCL
 				config I2C_SCL
-					int "I2C SCL GPIO number for DAC control. "
+					int "I2C SCL GPIO number for DAC control."
 					default -1
 					default -1
 					help
 					help
 						I2C clock gpio pin to use with DAC (not used mostly, leave it to -1).															
 						I2C clock gpio pin to use with DAC (not used mostly, leave it to -1).															
@@ -249,7 +195,7 @@ menu "Squeezelite-ESP32"
 		        help
 		        help
 		            This is the name of the device that the Bluetooth speaker will see when it is connected to.
 		            This is the name of the device that the Bluetooth speaker will see when it is connected to.
 		    config A2DP_CONTROL_DELAY_MS
 		    config A2DP_CONTROL_DELAY_MS
-		        int "Control loop delay. "
+		        int "Control loop delay."
 		        default 500
 		        default 500
 		        help
 		        help
 		            Decreasing this will lead to a more responsive BT control, but might lead to noisy log files if debug is enabled.
 		            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
 		config AIRPLAY_PORT
 			depends on AIRPLAY_SINK
 			depends on AIRPLAY_SINK
 			string "AirPlay listening port"
 			string "AirPlay listening port"
-				default 5000
+				default "5000"
 		    help
 		    help
 				AirPlay service listening port
 				AirPlay service listening port
 	endmenu	
 	endmenu	
@@ -401,5 +347,9 @@ menu "Squeezelite-ESP32"
 			help
 			help
 				Set the scaling factor for this 12 bits ADC
 				Set the scaling factor for this 12 bits ADC
 	endmenu	
 	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
 endmenu

+ 80 - 155
main/esp_app_main.c

@@ -30,7 +30,7 @@
 #include "lwip/netdb.h"
 #include "lwip/netdb.h"
 #include "nvs_utilities.h"
 #include "nvs_utilities.h"
 #include "trace.h"
 #include "trace.h"
-#include "wifi_manager.h"
+#include "network_manager.h"
 #include "squeezelite-ota.h"
 #include "squeezelite-ota.h"
 #include <math.h>
 #include <math.h>
 #include "audio_controls.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)
 #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] = {};
 	char number_buffer[101] = {};
 	snprintf(number_buffer,sizeof(number_buffer)-1,"%u",OTA_FLASH_ERASE_BLOCK);
 	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);
 	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);
 	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();
 	wait_for_commit();
 	ESP_LOGD(TAG,"Done setting default values in nvs.");
 	ESP_LOGD(TAG,"Done setting default values in nvs.");
 }
 }
@@ -507,13 +434,11 @@ void app_main()
 	led_blink_pushed(LED_GREEN, 250, 250);
 	led_blink_pushed(LED_GREEN, 250, 250);
 
 
 	if(bypass_wifi_manager){
 	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 {
 	else {
 		ESP_LOGI(TAG,"Starting Wifi Manager");
 		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_STA_GOT_IP, &cb_connection_got_ip);
 		wifi_manager_set_callback(EVENT_ETH_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);
 		wifi_manager_set_callback(EVENT_STA_DISCONNECTED, &cb_connection_sta_disconnected);

Разница между файлами не показана из-за своего большого размера
+ 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_PHY_MAX_TX_POWER=20
 
 
 
 
-CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y
+CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y
 
 
 
 
 CONFIG_FATFS_CODEPAGE_437=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_SUPPRESS_SELECT_DEBUG_OUTPUT=y
 CONFIG_VFS_SUPPORT_TERMIOS=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_512=y
 #CONFIG_WL_SECTOR_SIZE_4096 is not defined
 #CONFIG_WL_SECTOR_SIZE_4096 is not defined

+ 5 - 9
squeezelite.cmake

@@ -1,17 +1,13 @@
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 
 
 function(___register_flash partition_name sub_type)
 function(___register_flash partition_name sub_type)
-
     message(STATUS "Adding new build target (from build folder): ninja ${partition_name}-flash")
     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")
 	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()
 endfunction()
 #
 #
 # Removes the specified compile flag from the specified target.
 # 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 "lwip/netdb.h"
 #include "nvs_utilities.h"
 #include "nvs_utilities.h"
 #include "trace.h"
 #include "trace.h"
-#include "wifi_manager.h"
+#include "network_manager.h"
 #include "squeezelite-ota.h"
 #include "squeezelite-ota.h"
 #include <math.h>
 #include <math.h>
 #include "audio_controls.h"
 #include "audio_controls.h"

Некоторые файлы не были показаны из-за большого количества измененных файлов