Преглед на файлове

Esp32s3 test (#3734)

* Added ethernet functionality

* change smart leds to GPIO47 for now

* Make etherenet code specific for the esp32-s3 board
allexoK преди 8 месеца
родител
ревизия
149bbdc553

+ 7 - 0
code/components/allexok_lan/CMakeLists.txt

@@ -0,0 +1,7 @@
+FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
+
+idf_component_register(SRCS ${app_sources}
+                    INCLUDE_DIRS "."
+                    REQUIRES esp_eth nvs_flash wpa_supplicant jomjol_wlan jomjol_helper jomjol_mqtt esp_netif)
+
+

+ 210 - 0
code/components/allexok_lan/connect_lan.cpp

@@ -0,0 +1,210 @@
+#if defined(BOARD_ESP32_S3_ALEKSEI)
+#include "connect_lan.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <fstream>
+#include <vector>
+#include <sstream>
+#include <iostream>
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/event_groups.h"
+
+#include "driver/gpio.h"
+#include "esp_system.h"
+#include "esp_wifi.h"
+#include "esp_wnm.h"
+#include "esp_rrm.h"
+#include "esp_mbo.h"
+#include "esp_mac.h"
+#include "esp_netif.h"
+#include <netdb.h>
+#include "esp_log.h"
+#include "nvs_flash.h"
+
+#include "lwip/err.h"
+#include "lwip/sys.h"
+#ifdef ENABLE_MQTT
+    #include "interface_mqtt.h"
+#endif //ENABLE_MQTT
+
+#include "ClassLogFile.h"
+#include "read_lanini.h"
+#include "Helper.h"
+#include "statusled.h"
+
+#include "../../include/defines.h"
+
+#if (ESP_IDF_VERSION_MAJOR >= 5)
+#include "soc/periph_defs.h"
+#include "esp_private/periph_ctrl.h"
+#include "soc/gpio_sig_map.h"
+#include "soc/gpio_periph.h"
+#include "soc/io_mux_reg.h"
+#include "esp_rom_gpio.h"
+#define gpio_pad_select_gpio esp_rom_gpio_pad_select_gpio
+#define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c)
+#define gpio_matrix_out(a,b,c,d) esp_rom_gpio_connect_out_signal(a,b,c,d)
+#define ets_delay_us(a) esp_rom_delay_us(a)
+#endif
+
+#include "../esp-protocols/components/mdns/include/mdns.h" 
+
+#include <driver/spi_master.h>
+#include <esp_eth.h>
+#include <esp_netif.h>
+
+static const char *TAG = "LAN";
+
+extern bool WIFIConnected;
+static int LanReconnectCnt = 0;
+
+std::string* getLanIPAddress()
+{
+    return &wlan_config.ipaddress;
+}
+
+
+static void eth_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
+{
+    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) 
+	{
+        WIFIConnected = false;
+        LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Ethernet Started");
+    }
+	else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_DISCONNECTED) 
+	{
+        LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Ethernet Link Down");
+        // Optionally, try to reconnect or handle fallback LED:
+		StatusLED(WLAN_CONN, 1, false);
+        LanReconnectCnt++;
+		WIFIConnected = false;
+		}	
+	else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_CONNECTED) 
+	{
+		uint8_t mac_addr[6] = {0};
+		esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
+		
+		LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Ethernet Link Up");
+        esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
+        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]);
+
+	}	
+    else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_STOP) {
+        LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Ethernet Stopped");
+        WIFIConnected = false;
+		}
+}
+
+static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
+    int32_t event_id, void *event_data)
+{
+    WIFIConnected = true;
+	LanReconnectCnt = 0;
+	ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
+    wlan_config.ipaddress = std::string(ip4addr_ntoa((const ip4_addr*) &event->ip_info.ip));
+	LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Assigned IP: " + wlan_config.ipaddress);
+	#ifdef ENABLE_MQTT
+        if (getMQTTisEnabled()) {
+            vTaskDelay(5000 / portTICK_PERIOD_MS); 
+            MQTT_Init();    // Init when WIFI is getting connected    
+        }
+    #endif //ENABLE_MQTT   
+	// LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Assigned IP: " + WIFIConnected);
+	// LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Assigned IP: " + getWIFIisConnected());
+}
+
+
+esp_eth_handle_t eth_handle = NULL;
+esp_netif_t *eth_netif = NULL;
+
+int lan_init(void)
+{
+	esp_err_t retval = esp_netif_init();
+	if (retval != ESP_OK) {
+		LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_netif_init: Error: "  + std::to_string(retval));
+		return retval;
+	}
+    int retVal = esp_event_loop_create_default();
+    if (retVal != ESP_OK && retVal != ESP_ERR_INVALID_STATE) {
+        LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_event_loop_create_default, Error");
+        return retVal;
+    }
+
+    gpio_set_direction(ETH_ENABLE, GPIO_MODE_OUTPUT);
+    gpio_set_level(ETH_ENABLE, 1);
+
+    gpio_set_direction(ETH_INT, GPIO_MODE_INPUT);
+    gpio_set_pull_mode(ETH_INT, GPIO_PULLUP_ONLY);
+
+    esp_log_level_set("netif", ESP_LOG_DEBUG);
+    LogFile.WriteToFile(ESP_LOG_INFO, TAG, "SPI init");
+    // 1) SPI bus init
+    spi_bus_config_t buscfg = { 0 };
+    buscfg.mosi_io_num = ETH_MOSI;
+    buscfg.miso_io_num = ETH_MISO;
+    buscfg.sclk_io_num = ETH_CLK;
+
+    ESP_ERROR_CHECK(spi_bus_initialize(W5500_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
+
+    // 2) Prepare a `spi_device_interface_config_t` but DO NOT call spi_bus_add_device manually
+    spi_device_interface_config_t devcfg = {
+        .mode         = 0,  // SPI mode 0
+        .clock_speed_hz = 40 * 1000 * 1000, // 20MHz
+        .spics_io_num = ETH_CS,
+        .queue_size   = 30,
+        // the rest zero-initialized
+    };
+
+    eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(W5500_SPI_HOST, &devcfg);
+    w5500_config.int_gpio_num = ETH_INT;
+    // 4) Standard MAC/PHY config
+    eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
+    esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
+
+    eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
+    phy_config.phy_addr = 1; // typical W5500
+    esp_eth_phy_t *phy = esp_eth_phy_new_w5500(&phy_config);
+
+    esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy);
+
+    LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Driver install");
+
+    ESP_ERROR_CHECK(esp_eth_driver_install(&eth_config, &eth_handle));
+    LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Driver installed");
+
+    uint8_t base_mac_addr[6];
+    esp_err_t ret = esp_efuse_mac_get_default(base_mac_addr);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to get efuse base MAC, error=0x%x", ret);
+    }
+    uint8_t local_mac[6];
+    esp_derive_local_mac(local_mac, base_mac_addr);
+    ret = esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, local_mac);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to set W5500 MAC, error=0x%x", ret);
+    }
+
+    // 5) Attach netif + start
+    esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH();
+    eth_netif = esp_netif_new(&netif_cfg);
+
+        // Register event handlers
+    ESP_ERROR_CHECK(esp_event_handler_register(
+                        ETH_EVENT, ESP_EVENT_ANY_ID,
+                        &eth_event_handler, NULL));
+    ESP_ERROR_CHECK(esp_event_handler_register(
+                        IP_EVENT, IP_EVENT_ETH_GOT_IP,
+                        &got_ip_event_handler, NULL));
+
+    esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle));
+    esp_eth_start(eth_handle);
+    LogFile.WriteToFile(ESP_LOG_INFO, TAG, "W5500 Ethernet init done");
+
+    return ESP_OK;
+}
+
+#endif

+ 20 - 0
code/components/allexok_lan/connect_lan.h

@@ -0,0 +1,20 @@
+#if defined(BOARD_ESP32_S3_ALEKSEI)
+#pragma once
+
+#ifndef CONNECT_LAN_H
+#define CONNECT_LAN_H
+
+#include <string>
+// #include "connect_wlan.h"
+
+// int wifi_init_sta(void);
+std::string* getLanIPAddress();
+// int get_WIFI_RSSI();
+std::string* getLanHostname();
+
+bool getLanIsConnected();
+void LanDestroy();
+int lan_init();
+
+#endif //CONNECT_WLAN_H
+#endif

+ 248 - 0
code/components/allexok_lan/read_lanini.cpp

@@ -0,0 +1,248 @@
+#if defined(BOARD_ESP32_S3_ALEKSEI)
+
+#include "read_lanini.h"
+
+#include "Helper.h"
+
+#include "connect_lan.h"
+
+
+#include <fstream>
+#include <string>
+#include <vector>
+#include <sstream>
+#include <iostream>
+#include <string.h>
+#include "esp_log.h"
+#include "ClassLogFile.h"
+#include "../../include/defines.h"
+
+static const char *TAG = "LANINI";
+
+
+std::vector<string> ZerlegeZeileLAN(std::string input, std::string _delimiter = "")
+{
+	std::vector<string> Output;
+	std::string delimiter = " =,";
+    if (_delimiter.length() > 0){
+        delimiter = _delimiter;
+    }
+
+	input = trim(input, delimiter);
+	size_t pos = findDelimiterPos(input, delimiter);
+	std::string token;
+    if (pos != std::string::npos)           // splitted only up to first equal sign !!! Special case for LAN.ini
+    {
+		token = input.substr(0, pos);
+		token = trim(token, delimiter);
+		Output.push_back(token);
+		input.erase(0, pos + 1);
+		input = trim(input, delimiter);
+	}
+	Output.push_back(input);
+
+	return Output;
+}
+
+
+int LoadLanFromFile(std::string fn)
+{
+    std::string line = "";
+    std::string tmp = "";
+    std::vector<string> splitted;
+
+    fn = FormatFileName(fn);
+    FILE* pFile = fopen(fn.c_str(), "r");
+    if (pFile == NULL) {
+        LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Unable to open file (read). Device init aborted!"); 
+        return -1;
+    }
+
+    ESP_LOGD(TAG, "LoadLanFromFile: lan.ini opened");
+
+    char zw[256];
+    if (fgets(zw, sizeof(zw), pFile) == NULL) {
+        line = "";
+        LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "file opened, but empty or content not readable. Device init aborted!");
+        fclose(pFile);
+        return -1;
+    }
+    else {
+        line = std::string(zw);
+    }
+
+    while ((line.size() > 0) || !(feof(pFile)))
+    {
+        //ESP_LOGD(TAG, "line: %s", line.c_str());
+        if (line[0] != ';') {   // Skip lines which starts with ';'
+
+            splitted = ZerlegeZeileLAN(line, "=");
+            splitted[0] = trim(splitted[0], " ");
+
+            if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HOSTNAME")){
+                tmp = trim(splitted[1]);
+                if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
+                    tmp = tmp.substr(1, tmp.length()-2);
+                }
+                wlan_config.hostname = tmp;
+                LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Hostname: " + wlan_config.hostname);
+            }
+
+            else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "IP")){
+                tmp = splitted[1];
+                if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
+                    tmp = tmp.substr(1, tmp.length()-2);
+                }
+                wlan_config.ipaddress = tmp;
+                LogFile.WriteToFile(ESP_LOG_INFO, TAG, "IP-Address: " + wlan_config.ipaddress);
+            }
+
+            else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "GATEWAY")){
+                tmp = splitted[1];
+                if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
+                    tmp = tmp.substr(1, tmp.length()-2);
+                }
+                wlan_config.gateway = tmp;
+                LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Gateway: " + wlan_config.gateway);
+            }
+
+            else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "NETMASK")){
+                tmp = splitted[1];
+                if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
+                    tmp = tmp.substr(1, tmp.length()-2);
+                }
+                wlan_config.netmask = tmp;
+                LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Netmask: " + wlan_config.netmask);
+            }
+
+            else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "DNS")){
+                tmp = splitted[1];
+                if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
+                    tmp = tmp.substr(1, tmp.length()-2);
+                }
+                wlan_config.dns = tmp;
+                LogFile.WriteToFile(ESP_LOG_INFO, TAG, "DNS: " + wlan_config.dns);
+            }
+
+            else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HTTP_USERNAME")){
+                tmp = splitted[1];
+                if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
+                    tmp = tmp.substr(1, tmp.length()-2);
+                }
+                wlan_config.http_username = tmp;
+                LogFile.WriteToFile(ESP_LOG_INFO, TAG, "HTTP_USERNAME: " + wlan_config.http_username);
+            }
+
+            else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HTTP_PASSWORD")){
+                tmp = splitted[1];
+                if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
+                    tmp = tmp.substr(1, tmp.length()-2);
+                }
+                wlan_config.http_password = tmp;
+                #ifndef __HIDE_PASSWORD
+                LogFile.WriteToFile(ESP_LOG_INFO, TAG, "HTTP_PASSWORD: " + wlan_config.http_password);
+                #else
+                LogFile.WriteToFile(ESP_LOG_INFO, TAG, "HTTP_PASSWORD: XXXXXXXX");
+                #endif
+            }
+
+
+        }
+
+        /* read next line */
+        if (fgets(zw, sizeof(zw), pFile) == NULL) {
+            line = "";
+        }
+        else {
+            line = std::string(zw);
+        }
+    }
+    fclose(pFile);
+
+    return 0;
+}
+
+
+bool ChangeLanHostName(std::string fn, std::string _newhostname)
+{
+    if (_newhostname == wlan_config.hostname)
+        return false;
+
+    std::string line = "";
+    std::vector<string> splitted;
+    std::vector<string> neuesfile;
+    bool found = false;
+
+    FILE* pFile = NULL;
+
+    fn = FormatFileName(fn);
+    pFile = fopen(fn.c_str(), "r");
+    if (pFile == NULL) {
+        LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ChangeHostName: Unable to open file lan.ini (read)"); 
+        return false;
+    }
+
+    ESP_LOGD(TAG, "ChangeHostName: lan.ini opened");
+
+    char zw[256];
+    if (fgets(zw, sizeof(zw), pFile) == NULL) {
+        line = "";
+        LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ChangeHostName: File opened, but empty or content not readable");
+        return false;
+    }
+    else {
+        line = std::string(zw);
+    }
+
+    while ((line.size() > 0) || !(feof(pFile)))
+    {
+        //ESP_LOGD(TAG, "ChangeHostName: line: %s", line.c_str());
+        splitted = ZerlegeZeileLAN(line, "=");
+        splitted[0] = trim(splitted[0], " ");
+
+        if ((splitted.size() > 1) && ((toUpper(splitted[0]) == "HOSTNAME") || (toUpper(splitted[0]) == ";HOSTNAME"))){
+            line = "hostname = \"" + _newhostname + "\"\n";
+            found = true;
+        }
+
+        neuesfile.push_back(line);
+
+        if (fgets(zw, sizeof(zw), pFile) == NULL)
+        {
+            line = "";
+        }
+        else
+        {
+            line = std::string(zw);
+        }
+    }
+
+    if (!found)
+    {
+        line  = "\n;++++++++++++++++++++++++++++++++++\n";
+        line += "; Hostname: Name of device in network\n";
+        line += "; This parameter can be configured via WebUI configuration\n";
+        line += "; Default: \"watermeter\", if nothing is configured\n\n";
+        line = "hostname = \"" + _newhostname + "\"\n";
+        neuesfile.push_back(line);        
+    }
+    fclose(pFile);
+
+    pFile = fopen(fn.c_str(), "w+");
+    if (pFile == NULL) {
+        LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ChangeHostName: Unable to open file wlan.ini (write)"); 
+        return false;
+    }
+
+    for (int i = 0; i < neuesfile.size(); ++i)
+    {
+        //ESP_LOGD(TAG, "%s", neuesfile[i].c_str());
+        fputs(neuesfile[i].c_str(), pFile);
+    }
+    fclose(pFile);
+
+    ESP_LOGD(TAG, "ChangeLanHostName done");
+
+    return true;
+}
+#endif

+ 19 - 0
code/components/allexok_lan/read_lanini.h

@@ -0,0 +1,19 @@
+#if defined(BOARD_ESP32_S3_ALEKSEI)
+#pragma once
+
+#ifndef READ_LANINI_H
+#define READ_LANINI_H
+
+#include <string>
+#include "read_wlanini.h"
+
+
+extern struct wlan_config wlan_config;
+
+
+int LoadLanFromFile(std::string fn);
+bool ChangeLanHostName(std::string fn, std::string _newhostname);
+
+
+#endif //READ_WLANINI_H
+#endif

+ 5 - 1
code/components/jomjol_controlcamera/ClassControllCamera.cpp

@@ -244,6 +244,10 @@ bool CCamera::getCameraInitSuccessful(void)
 
 
 esp_err_t CCamera::setSensorDatenFromCCstatus(void)
 esp_err_t CCamera::setSensorDatenFromCCstatus(void)
 {
 {
+    #if defined(BOARD_ESP32_S3_ALEKSEI)    
+    esp_camera_deinit();
+    ESP_ERROR_CHECK( esp_camera_init(&camera_config) );
+    #endif
     sensor_t *s = esp_camera_sensor_get();
     sensor_t *s = esp_camera_sensor_get();
 
 
     if (s != NULL)
     if (s != NULL)
@@ -1011,7 +1015,7 @@ esp_err_t CCamera::CaptureToStream(httpd_req_t *req, bool FlashlightOn)
             vTaskDelay(xDelay);
             vTaskDelay(xDelay);
         }
         }
     }
     }
-
+    // httpd_resp_send_chunk(req, NULL, 0);      // 
     LEDOnOff(false);   // Status-LED off
     LEDOnOff(false);   // Status-LED off
     LightOnOff(false); // Flash-LED off
     LightOnOff(false); // Flash-LED off
 
 

+ 2 - 2
code/components/jomjol_helper/sdcard_check.cpp

@@ -112,8 +112,8 @@ bool SDCardCheckFolderFilePresence()
     }
     }
 
 
     /* check if file exists: wlan.ini */
     /* check if file exists: wlan.ini */
-    if (stat("/sdcard/wlan.ini", &sb) != 0) {
-        LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: File /wlan.ini not found");
+    if (stat("/sdcard/wlan.ini", &sb) != 0 and stat("/sdcard/lan.ini", &sb) != 0) {
+        LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Folder/file check: File /wlan.ini and /lan.ini not found");
         bRetval = false;
         bRetval = false;
     }
     }
 
 

+ 1 - 1
code/components/jomjol_wlan/connect_wlan.cpp

@@ -55,7 +55,7 @@
 static const char *TAG = "WIFI";
 static const char *TAG = "WIFI";
 
 
 static bool APWithBetterRSSI = false;
 static bool APWithBetterRSSI = false;
-static bool WIFIConnected = false;
+bool WIFIConnected = false;
 static int WIFIReconnectCnt = 0;
 static int WIFIReconnectCnt = 0;
 
 
 esp_netif_t *my_sta;
 esp_netif_t *my_sta;

+ 2 - 0
code/components/jomjol_wlan/connect_wlan.h

@@ -14,6 +14,8 @@ std::string* getHostname();
 bool getWIFIisConnected();
 bool getWIFIisConnected();
 void WIFIDestroy();
 void WIFIDestroy();
 
 
+extern bool WIFIConnected;
+
 #if (defined WLAN_USE_MESH_ROAMING && defined WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES)
 #if (defined WLAN_USE_MESH_ROAMING && defined WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES)
 void wifiRoamingQuery(void);
 void wifiRoamingQuery(void);
 #endif
 #endif

+ 15 - 6
code/include/defines.h

@@ -79,6 +79,8 @@
     //ClassFlowControll + Main + SoftAP
     //ClassFlowControll + Main + SoftAP
     #define WLAN_CONFIG_FILE "/sdcard/wlan.ini"
     #define WLAN_CONFIG_FILE "/sdcard/wlan.ini"
 
 
+    #define LAN_CONFIG_FILE "/sdcard/lan.ini"
+
 
 
     //main
     //main
     #define __SD_USE_ONE_LINE_MODE__
     #define __SD_USE_ONE_LINE_MODE__
@@ -93,8 +95,8 @@
          
          
     #define LOGFILE_LAST_PART_BYTES 80 * 1024 // 80 kBytes  // Size of partial log file to return 
     #define LOGFILE_LAST_PART_BYTES 80 * 1024 // 80 kBytes  // Size of partial log file to return 
 
 
-    #define SERVER_FILER_SCRATCH_BUFSIZE  4096 
-    #define SERVER_HELPER_SCRATCH_BUFSIZE  4096
+    #define SERVER_FILER_SCRATCH_BUFSIZE  1024 
+    #define SERVER_HELPER_SCRATCH_BUFSIZE  1024
     #define SERVER_OTA_SCRATCH_BUFSIZE  1024 
     #define SERVER_OTA_SCRATCH_BUFSIZE  1024 
 
 
 
 
@@ -171,7 +173,7 @@
     //#define WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES  // Client can send query to AP requesting to roam (if RSSI lower than RSSI threshold)
     //#define WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES  // Client can send query to AP requesting to roam (if RSSI lower than RSSI threshold)
 
 
     /* WIFI roaming only client triggered by scanning the channels after each round (only if RSSI < RSSIThreshold) and trigger a disconnect to switch AP */
     /* WIFI roaming only client triggered by scanning the channels after each round (only if RSSI < RSSIThreshold) and trigger a disconnect to switch AP */
-    #define WLAN_USE_ROAMING_BY_SCANNING
+    // #define WLAN_USE_ROAMING_BY_SCANNING
 
 
 
 
     //ClassFlowCNNGeneral
     //ClassFlowCNNGeneral
@@ -308,7 +310,7 @@
     #define FLASH_GPIO GPIO_NUM_4               // PIN for flashlight LED
     #define FLASH_GPIO GPIO_NUM_4               // PIN for flashlight LED
     #define USE_PWM_LEDFLASH                    // if __LEDGLOBAL is defined, a global variable is used for LED control, otherwise locally and each time a new
     #define USE_PWM_LEDFLASH                    // if __LEDGLOBAL is defined, a global variable is used for LED control, otherwise locally and each time a new
 
 
-#elif defined(BOARD_ESP32_S3_ALEKSEI) // Sonderversion für Aleksei mit ESP32s3 und Ethernet (PoE)
+    #elif defined(BOARD_ESP32_S3_ALEKSEI) // Sonderversion für Aleksei mit ESP32s3 und Ethernet (PoE)
     // HIGH=ENABLE
     // HIGH=ENABLE
     // ETH_EN activates power for the Ethernet
     // ETH_EN activates power for the Ethernet
     // PER_EN activates power for camera,leds,and SDcard, Battery measurement voltage divider
     // PER_EN activates power for camera,leds,and SDcard, Battery measurement voltage divider
@@ -316,6 +318,13 @@
     #define ETH_ENABLE GPIO_NUM_45
     #define ETH_ENABLE GPIO_NUM_45
     #define PER_ENABLE GPIO_NUM_46
     #define PER_ENABLE GPIO_NUM_46
 
 
+    // Ethernet (operated with SPI peripheral)
+    #define W5500_SPI_HOST     SPI2_HOST
+    #define ETH_MOSI GPIO_NUM_1
+    #define ETH_MISO GPIO_NUM_14
+    #define ETH_CLK GPIO_NUM_21
+    #define ETH_CS GPIO_NUM_39
+    #define ETH_INT GPIO_NUM_38
 	// SD card (operated with SDMMC peripheral)
 	// SD card (operated with SDMMC peripheral)
 	//-------------------------------------------------
 	//-------------------------------------------------
 	#define GPIO_SDCARD_CLK GPIO_NUM_40
 	#define GPIO_SDCARD_CLK GPIO_NUM_40
@@ -350,10 +359,10 @@
     #define CAM_PIN_PCLK     GPIO_NUM_13
     #define CAM_PIN_PCLK     GPIO_NUM_13
 
 
     //Statusled + ClassControllCamera
     //Statusled + ClassControllCamera
-    #define BLINK_GPIO GPIO_NUM_33              // PIN for red board LED
+    #define BLINK_GPIO GPIO_NUM_48              // PIN for red board LED
 	
 	
     //ClassControllCamera
     //ClassControllCamera
-    #define FLASH_GPIO GPIO_NUM_4               // PIN for flashlight LED
+    #define FLASH_GPIO GPIO_NUM_48               // PIN for flashlight LED
     #define USE_PWM_LEDFLASH                    // if __LEDGLOBAL is defined, a global variable is used for LED control, otherwise locally and each time a new
     #define USE_PWM_LEDFLASH                    // if __LEDGLOBAL is defined, a global variable is used for LED control, otherwise locally and each time a new
 
 
 
 

+ 44 - 16
code/main/main.cpp

@@ -25,6 +25,9 @@
 #include "connect_wlan.h"
 #include "connect_wlan.h"
 #include "read_wlanini.h"
 #include "read_wlanini.h"
 
 
+#include "connect_lan.h"
+#include "read_lanini.h"
+
 #include "server_main.h"
 #include "server_main.h"
 #include "MainFlowControl.h"
 #include "MainFlowControl.h"
 #include "server_file.h"
 #include "server_file.h"
@@ -463,26 +466,52 @@ extern "C" void app_main(void)
         ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
         ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
     #endif
     #endif
 
 
-    // Read WLAN parameter and start WIFI
-    // ********************************************
-    int iWLANStatus = LoadWlanFromFile(WLAN_CONFIG_FILE);
-    if (iWLANStatus == 0) {
-        LogFile.WriteToFile(ESP_LOG_INFO, TAG, "WLAN config loaded, init WIFI...");
-        if (wifi_init_sta() != ESP_OK) {
-            LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "WIFI init failed. Device init aborted!");
+    bool lanEnabled = false;
+    #if defined(BOARD_ESP32_S3_ALEKSEI)
+    int iLanStatus = LoadLanFromFile(LAN_CONFIG_FILE);
+    if (iLanStatus == 0) {
+        LogFile.WriteToFile(ESP_LOG_INFO, TAG, "LAN config loaded, init Lan...");
+        if (lan_init() != ESP_OK) {
+            LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "LAN init failed. Device init aborted!");
             StatusLED(WLAN_INIT, 3, true);
             StatusLED(WLAN_INIT, 3, true);
             return;
             return;
         }
         }
-
-        init_basic_auth();
+        else {
+            lanEnabled = true;
+            LogFile.WriteToFile(ESP_LOG_INFO, TAG, "LAN init completed successfully");
+        }
+    }
+    else if(iLanStatus == -1) {  // lan.ini not available, potentially empty or content not readable
+        LogFile.WriteToFile(ESP_LOG_WARN, TAG, "lan.ini not found, proceeding to wlan.ini");
     }
     }
-    else if (iWLANStatus == -1) {  // wlan.ini not available, potentially empty or content not readable
-        StatusLED(WLAN_INIT, 1, true);
-        return; // No way to continue without reading the wlan.ini
+    else {
+        LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Lan init failed. Unknown error!");
+        return; // No way to continue without reading the lan.ini
     }
     }
-    else if (iWLANStatus == -2) { // SSID or password not configured
-        StatusLED(WLAN_INIT, 2, true);
-        return; // No way to continue with empty SSID or password!
+    #endif
+    if(!lanEnabled){
+
+        // Read WLAN parameter and start WIFI
+        // ********************************************
+        int iWLANStatus = LoadWlanFromFile(WLAN_CONFIG_FILE);
+        if (iWLANStatus == 0) {
+            LogFile.WriteToFile(ESP_LOG_INFO, TAG, "WLAN config loaded, init WIFI...");
+            if (wifi_init_sta() != ESP_OK) {
+                LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "WIFI init failed. Device init aborted!");
+                StatusLED(WLAN_INIT, 3, true);
+                return;
+            }
+
+            init_basic_auth();
+        }
+        else if (iWLANStatus == -1) {  // wlan.ini not available, potentially empty or content not readable
+            StatusLED(WLAN_INIT, 1, true);
+            return; // No way to continue without reading the wlan.ini
+        }
+        else if (iWLANStatus == -2) { // SSID or password not configured
+            StatusLED(WLAN_INIT, 2, true);
+            return; // No way to continue with empty SSID or password!
+        }
     }
     }
 
 
     xDelay = 2000 / portTICK_PERIOD_MS;
     xDelay = 2000 / portTICK_PERIOD_MS;
@@ -495,7 +524,6 @@ extern "C" void app_main(void)
     {
     {
         LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Manual Time Sync failed during startup" );
         LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Manual Time Sync failed during startup" );
     }
     }
-
     // Set log level for wifi component to WARN level (default: INFO; only relevant for serial console)
     // Set log level for wifi component to WARN level (default: INFO; only relevant for serial console)
     // ********************************************
     // ********************************************
     esp_log_level_set("wifi", ESP_LOG_WARN);
     esp_log_level_set("wifi", ESP_LOG_WARN);

+ 111 - 62
code/main/softAP.cpp

@@ -41,6 +41,7 @@
 
 
 bool isConfigINI = false;
 bool isConfigINI = false;
 bool isWlanINI = false;
 bool isWlanINI = false;
+bool isLanINI = false;
 
 
 static const char *TAG = "WIFI AP";
 static const char *TAG = "WIFI AP";
 
 
@@ -99,12 +100,13 @@ void wifi_init_softAP(void)
 void SendHTTPResponse(httpd_req_t *req)
 void SendHTTPResponse(httpd_req_t *req)
 {
 {
     std::string message = "<h1>AI-on-the-edge - BASIC SETUP</h1><p>This is an access point with a minimal server to setup the minimum required files and information on the device and the SD-card. ";
     std::string message = "<h1>AI-on-the-edge - BASIC SETUP</h1><p>This is an access point with a minimal server to setup the minimum required files and information on the device and the SD-card. ";
-    message += "This mode is always started if one of the following files is missing: /wlan.ini or the /config/config.ini.<p>";
-    message += "The setup is done in 3 steps: 1. upload full inital configuration (sd-card content), 2. store WLAN access information, 3. reboot (and connect to WLANs)<p><p>";
+    message += "This mode is always started if neither /wlan.ini nor /lan.ini is preset or the /config/config.ini. is missing<p>";
+    message += "The setup is done in 3 steps: 1. upload full inital configuration (sd-card content), 2. store WLAN/LAN access information, 3. reboot (and connect to WLANs/LANs)<p><p>";
     message += "Please follow the below instructions.<p>";
     message += "Please follow the below instructions.<p>";
     httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
     httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
 
 
     isWlanINI = FileExists(WLAN_CONFIG_FILE);
     isWlanINI = FileExists(WLAN_CONFIG_FILE);
+    isLanINI = FileExists(LAN_CONFIG_FILE);
 
 
     if (!isConfigINI)
     if (!isConfigINI)
     {
     {
@@ -129,33 +131,53 @@ void SendHTTPResponse(httpd_req_t *req)
         httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
         httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
         return;
         return;
     }
     }
-    if (!isWlanINI)
+    if (!isWlanINI && !isLanINI)
     {
     {
-        message = "<h3>2. WLAN access credentials</h3><p>";
+        message  = "<h3>2. WLAN access credentials</h3><p>";
+        message += "Interface: <select id=\"iface\" onchange=\"toggle()\">";
+        message +=              "<option value=\"wifi\" selected>Wi-Fi</option>";
+        message +=              "<option value=\"eth\">Ethernet</option></select><p>";
+        
+        /* Wi-Fi-only fields wrapped in a <div id="wifi"> for easy hide/show */
+        message += "<div id=\"wifi\">";
         message += "<table>";
         message += "<table>";
-        message += "<tr><td>WLAN-SSID</td><td><input type=\"text\" name=\"ssid\" id=\"ssid\"></td><td>SSID of the WLAN</td></tr>";
-        message += "<tr><td>WLAN-Password</td><td><input type=\"text\" name=\"password\" id=\"password\"></td><td>ATTENTION: the password will not be encrypted during the sending.</td><tr>";
-        message += "</table><p>";
-        message += "<h4>ATTENTION:<h4>Be sure about the WLAN settings. They cannot be reset afterwards. If ssid or password is wrong, you need to take out the sd-card and manually change them in \"wlan.ini\"!<p>";
-        httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
-
-//        message = "</tr><tr><td> Hostname</td><td><input type=\"text\" name=\"hostname\" id=\"hostname\"></td><td></td>";
-//        message += "</tr><tr><td>Fixed IP</td><td><input type=\"text\" name=\"ip\" id=\"ip\"></td><td>Leave emtpy if set by router (DHCP)</td></tr>";
-//        message += "<tr><td>Gateway</td><td><input type=\"text\" name=\"gateway\" id=\"gateway\"></td><td>Leave emtpy if set by router (DHCP)</td></tr>";
-//        message += "<tr><td>Netmask</td><td><input type=\"text\" name=\"netmask\" id=\"netmask\"></td><td>Leave emtpy if set by router (DHCP)</td>";
-//        message += "</tr><tr><td>DNS</td><td><input type=\"text\" name=\"dns\" id=\"dns\"></td><td>Leave emtpy if set by router (DHCP)</td></tr>";
-//        message += "<tr><td>RSSI Threshold</td><td><input type=\"number\" name=\"name\" id=\"threshold\" min=\"-100\"  max=\"0\" step=\"1\" value = \"0\"></td><td>WLAN Mesh Parameter: Threshold for RSSI value to check for start switching access point in a mesh system (if actual RSSI is lower). Possible values: -100 to 0, 0 = disabled - Value will be transfered to wlan.ini at next startup)</td></tr>";
-//        httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
-
-
-        message = "<button class=\"button\" type=\"button\" onclick=\"wr()\">Write wlan.ini</button>";
-        message += "<script language=\"JavaScript\">async function wr(){";
-        message += "api = \"/config?\"+\"ssid=\"+document.getElementById(\"ssid\").value+\"&pwd=\"+document.getElementById(\"password\").value;";
-//        message += "api = \"/config?\"+\"ssid=\"+document.getElementById(\"ssid\").value+\"&pwd=\"+document.getElementById(\"password\").value+\"&hn=\"+document.getElementById(\"hostname\").value+\"&ip=\"+document.getElementById(\"ip\").value+\"&gw=\"+document.getElementById(\"gateway\").value+\"&nm=\"+document.getElementById(\"netmask\").value+\"&dns=\"+document.getElementById(\"dns\").value+\"&rssithreshold=\"+document.getElementById(\"threshold\").value;";
-        message += "fetch(api);await new Promise(resolve => setTimeout(resolve, 1000));location.reload();}</script>";
-        httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
-        return;
-    }
+        message += "<tr><td>WLAN-SSID</td><td><input id=\"ssid\"></td><td>SSID of the WLAN</td></tr>";
+        message += "<tr><td>WLAN-Password</td><td><input id=\"password\"></td><td><b>ATTENTION:</b> sent unencrypted</td></tr>";
+        message += "</table></div><p>";
+        
+        message += "<h4>ATTENTION:</h4>Be sure about the WLAN/LAN settings. They cannot be reset afterwards. "
+                   "If SSID or password are wrong you must edit <i>wlan.ini</i> on the SD-card!<p>";
+        
+        httpd_resp_send_chunk(req, message.c_str(), message.length());
+        
+        /* ---- Button + JS ---------------------------------------------------- */
+        message.clear();
+        message  = "<button class=\"button\" id=\"saveBtn\" onclick=\"wr()\">Write wlan.ini</button>";
+        message += R"JS(
+        <script>
+        function toggle(){
+            const wifiSelected = (iface.value === 'wifi');
+            wifi.style.display = wifiSelected ? 'block' : 'none';
+            /* change button label */
+            saveBtn.textContent = wifiSelected ? 'Write wlan.ini' : 'Write lan.ini';
+        }
+        async function wr(){
+          let url = '/config?type=' + iface.value;
+          if(iface.value==='wifi'){
+            url += '&ssid=' + encodeURIComponent(ssid.value) +
+                   '&pwd='  + encodeURIComponent(password.value);
+          }
+          await fetch(url);
+          await new Promise(r=>setTimeout(r,500));
+          location.reload();
+        }
+        </script>)JS";
+        
+        httpd_resp_send_chunk(req, message.c_str(), message.length());
+        /* finish response */
+        httpd_resp_send_chunk(req, nullptr, 0);
+        return; // done
+        }
 
 
     message = "<h3>3. Reboot</h3><p>";
     message = "<h3>3. Reboot</h3><p>";
     message += "After triggering the reboot, the zip-files gets extracted and written to the sd-card.<br>The ESP32 will restart two times and then connect to your access point. Please find the IP in your router settings and access it with the new ip-address.<p>";
     message += "After triggering the reboot, the zip-files gets extracted and written to the sd-card.<br>The ESP32 will restart two times and then connect to your access point. Please find the IP in your router settings and access it with the new ip-address.<p>";
@@ -207,6 +229,8 @@ esp_err_t config_ini_handler(httpd_req_t *req)
     std::string dns = "";
     std::string dns = "";
     std::string rssithreshold = ""; //rssi threshold for WIFI roaming
     std::string rssithreshold = ""; //rssi threshold for WIFI roaming
     std::string text = "";
     std::string text = "";
+    std::string type = "";
+
 
 
 
 
     if (httpd_req_get_url_query_str(req, _query, 400) == ESP_OK)
     if (httpd_req_get_url_query_str(req, _query, 400) == ESP_OK)
@@ -266,27 +290,49 @@ esp_err_t config_ini_handler(httpd_req_t *req)
             ESP_LOGD(TAG, "rssithreshold is found: %s", _valuechar);
             ESP_LOGD(TAG, "rssithreshold is found: %s", _valuechar);
             rssithreshold = UrlDecode(std::string(_valuechar));
             rssithreshold = UrlDecode(std::string(_valuechar));
         }
         }
+
+        if (httpd_query_key_value(_query, "type", _valuechar, 100) == ESP_OK)
+        {
+            ESP_LOGD(TAG, "type is found: %s", _valuechar);
+            type = UrlDecode(std::string(_valuechar));
+        }
     }
     }
 
 
-    FILE* configfilehandle = fopen(WLAN_CONFIG_FILE, "w");
+    FILE* configfilehandle = nullptr;
+    if(type == "wifi"){  
+        configfilehandle = fopen(WLAN_CONFIG_FILE, "w");
 
 
-    text  = ";++++++++++++++++++++++++++++++++++\n";
-    text += "; AI on the edge - WLAN configuration\n";
-    text += "; ssid: Name of WLAN network (mandatory), e.g. \"WLAN-SSID\"\n";
-    text += "; password: Password of WLAN network (mandatory), e.g. \"PASSWORD\"\n\n";
-    fputs(text.c_str(), configfilehandle);
-    
-    if (ssid.length())
-        ssid = "ssid = \"" + ssid + "\"\n";
-    else
+        text  = ";++++++++++++++++++++++++++++++++++\n";
+        text += "; AI on the edge - WLAN configuration\n";
+        text += "; ssid: Name of WLAN network (mandatory), e.g. \"WLAN-SSID\"\n";
+        text += "; password: Password of WLAN network (mandatory), e.g. \"PASSWORD\"\n\n";
+        fputs(text.c_str(), configfilehandle);
+        
+        if (ssid.length())
+            ssid = "ssid = \"" + ssid + "\"\n";
+        else
+            ssid = "ssid = \"\"\n";
+        fputs(ssid.c_str(), configfilehandle);
+
+        if (pwd.length())
+            pwd = "password = \"" + pwd + "\"\n";
+        else
+            pwd = "password = \"\"\n";
+        fputs(pwd.c_str(), configfilehandle);
+    }
+    else{
+        configfilehandle = fopen(LAN_CONFIG_FILE, "w");
+
+        text  = ";++++++++++++++++++++++++++++++++++\n";
+        text += "; AI on the edge - WLAN configuration\n";
+        text += "; ssid: Name of WLAN network (mandatory), e.g. \"WLAN-SSID\"\n";
+        text += "; password: Password of WLAN network (mandatory), e.g. \"PASSWORD\"\n\n";
+        fputs(text.c_str(), configfilehandle);
         ssid = "ssid = \"\"\n";
         ssid = "ssid = \"\"\n";
-    fputs(ssid.c_str(), configfilehandle);
-
-    if (pwd.length())
-        pwd = "password = \"" + pwd + "\"\n";
-    else
+        fputs(ssid.c_str(), configfilehandle);
         pwd = "password = \"\"\n";
         pwd = "password = \"\"\n";
-    fputs(pwd.c_str(), configfilehandle);
+        fputs(pwd.c_str(), configfilehandle);
+    }
 
 
     text  = "\n;++++++++++++++++++++++++++++++++++\n";
     text  = "\n;++++++++++++++++++++++++++++++++++\n";
     text += "; Hostname: Name of device in network\n";
     text += "; Hostname: Name of device in network\n";
@@ -333,22 +379,24 @@ esp_err_t config_ini_handler(httpd_req_t *req)
         dns = ";dns = \"xxx.xxx.xxx.xxx\"\n";
         dns = ";dns = \"xxx.xxx.xxx.xxx\"\n";
     fputs(dns.c_str(), configfilehandle);
     fputs(dns.c_str(), configfilehandle);
 
 
-    text  = "\n;++++++++++++++++++++++++++++++++++\n";
-    text += "; WIFI Roaming:\n";
-    text += "; Network assisted roaming protocol is activated by default\n";
-    text += "; AP / mesh system needs to support roaming protocol 802.11k/v\n";
-    text += ";\n";
-    text += "; Optional feature (usually not neccessary):\n";
-    text += "; RSSI Threshold for client requested roaming query (RSSI < RSSIThreshold)\n";
-    text += "; Note: This parameter can be configured via WebUI configuration\n";
-    text += "; Default: 0 = Disable client requested roaming query\n\n";
-    fputs(text.c_str(), configfilehandle);
-
-    if (rssithreshold.length())
-        rssithreshold = "RSSIThreshold = " + rssithreshold + "\n";
-    else
-        rssithreshold = "RSSIThreshold = 0\n";
-    fputs(rssithreshold.c_str(), configfilehandle);
+    if(type == "wifi"){  
+        text  = "\n;++++++++++++++++++++++++++++++++++\n";
+        text += "; WIFI Roaming:\n";
+        text += "; Network assisted roaming protocol is activated by default\n";
+        text += "; AP / mesh system needs to support roaming protocol 802.11k/v\n";
+        text += ";\n";
+        text += "; Optional feature (usually not neccessary):\n";
+        text += "; RSSI Threshold for client requested roaming query (RSSI < RSSIThreshold)\n";
+        text += "; Note: This parameter can be configured via WebUI configuration\n";
+        text += "; Default: 0 = Disable client requested roaming query\n\n";
+        fputs(text.c_str(), configfilehandle);
+
+        if (rssithreshold.length())
+            rssithreshold = "RSSIThreshold = " + rssithreshold + "\n";
+        else
+            rssithreshold = "RSSIThreshold = 0\n";
+        fputs(rssithreshold.c_str(), configfilehandle);
+    }
 
 
     fflush(configfilehandle);
     fflush(configfilehandle);
     fclose(configfilehandle);
     fclose(configfilehandle);
@@ -507,14 +555,15 @@ void CheckStartAPMode()
 {
 {
     isConfigINI = FileExists(CONFIG_FILE);
     isConfigINI = FileExists(CONFIG_FILE);
     isWlanINI = FileExists(WLAN_CONFIG_FILE);
     isWlanINI = FileExists(WLAN_CONFIG_FILE);
+    isLanINI = FileExists(LAN_CONFIG_FILE);
 
 
     if (!isConfigINI)
     if (!isConfigINI)
         ESP_LOGW(TAG, "config.ini not found!");
         ESP_LOGW(TAG, "config.ini not found!");
 
 
-    if (!isWlanINI)
-        ESP_LOGW(TAG, "wlan.ini not found!");
+    if (!isWlanINI && !isLanINI)
+        ESP_LOGW(TAG, "wlan.ini and lan.ini not found!");
 
 
-    if (!isConfigINI || !isWlanINI)
+    if (!isConfigINI || (!isWlanINI && !isLanINI))
     {
     {
         ESP_LOGI(TAG, "Starting access point for remote configuration");
         ESP_LOGI(TAG, "Starting access point for remote configuration");
         StatusLED(AP_OR_OTA, 2, true);
         StatusLED(AP_OR_OTA, 2, true);

+ 1 - 1
code/platformio.ini

@@ -10,7 +10,7 @@
 
 
 [platformio]
 [platformio]
     src_dir = main
     src_dir = main
-    default_envs = esp32cam
+    default_envs = esp32s3-aleksei
 
 
 [common:idf]
 [common:idf]
     build_flags = 
     build_flags = 

+ 8 - 6
code/sdkconfig.esp32s3-aleksei

@@ -856,9 +856,11 @@ CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=y
 CONFIG_ETH_ENABLED=y
 CONFIG_ETH_ENABLED=y
 CONFIG_ETH_USE_SPI_ETHERNET=y
 CONFIG_ETH_USE_SPI_ETHERNET=y
 # CONFIG_ETH_SPI_ETHERNET_DM9051 is not set
 # CONFIG_ETH_SPI_ETHERNET_DM9051 is not set
-# CONFIG_ETH_SPI_ETHERNET_W5500 is not set
+CONFIG_ETH_SPI_ETHERNET_W5500=y
 # CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set
 # CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set
-# CONFIG_ETH_USE_OPENETH is not set
+CONFIG_ETH_USE_OPENETH=y
+CONFIG_ETH_OPENETH_DMA_RX_BUFFER_NUM=4
+CONFIG_ETH_OPENETH_DMA_TX_BUFFER_NUM=4
 # CONFIG_ETH_TRANSMIT_MUTEX is not set
 # CONFIG_ETH_TRANSMIT_MUTEX is not set
 # end of Ethernet
 # end of Ethernet
 
 
@@ -1540,8 +1542,8 @@ CONFIG_LWIP_TCP_MSS=1440
 CONFIG_LWIP_TCP_TMR_INTERVAL=250
 CONFIG_LWIP_TCP_TMR_INTERVAL=250
 CONFIG_LWIP_TCP_MSL=60000
 CONFIG_LWIP_TCP_MSL=60000
 CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000
 CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000
-CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5760
-CONFIG_LWIP_TCP_WND_DEFAULT=5760
+CONFIG_LWIP_TCP_SND_BUF_DEFAULT=16384
+CONFIG_LWIP_TCP_WND_DEFAULT=16384
 CONFIG_LWIP_TCP_RECVMBOX_SIZE=6
 CONFIG_LWIP_TCP_RECVMBOX_SIZE=6
 CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE=6
 CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE=6
 CONFIG_LWIP_TCP_QUEUE_OOSEQ=y
 CONFIG_LWIP_TCP_QUEUE_OOSEQ=y
@@ -2300,8 +2302,8 @@ CONFIG_TCP_MAXRTX=12
 CONFIG_TCP_SYNMAXRTX=12
 CONFIG_TCP_SYNMAXRTX=12
 CONFIG_TCP_MSS=1440
 CONFIG_TCP_MSS=1440
 CONFIG_TCP_MSL=60000
 CONFIG_TCP_MSL=60000
-CONFIG_TCP_SND_BUF_DEFAULT=5760
-CONFIG_TCP_WND_DEFAULT=5760
+CONFIG_TCP_SND_BUF_DEFAULT=16384
+CONFIG_TCP_WND_DEFAULT=16384
 CONFIG_TCP_RECVMBOX_SIZE=6
 CONFIG_TCP_RECVMBOX_SIZE=6
 CONFIG_TCP_QUEUE_OOSEQ=y
 CONFIG_TCP_QUEUE_OOSEQ=y
 CONFIG_TCP_OVERSIZE_MSS=y
 CONFIG_TCP_OVERSIZE_MSS=y

+ 200 - 11
code/sdkconfig.esp32s3-aleksei.old

@@ -746,7 +746,6 @@ CONFIG_ESP_COEX_ENABLED=y
 # Common ESP-related
 # Common ESP-related
 #
 #
 # CONFIG_ESP_ERR_TO_NAME_LOOKUP is not set
 # CONFIG_ESP_ERR_TO_NAME_LOOKUP is not set
-CONFIG_ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
 # end of Common ESP-related
 # end of Common ESP-related
 
 
 #
 #
@@ -857,7 +856,7 @@ CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=y
 CONFIG_ETH_ENABLED=y
 CONFIG_ETH_ENABLED=y
 CONFIG_ETH_USE_SPI_ETHERNET=y
 CONFIG_ETH_USE_SPI_ETHERNET=y
 # CONFIG_ETH_SPI_ETHERNET_DM9051 is not set
 # CONFIG_ETH_SPI_ETHERNET_DM9051 is not set
-# CONFIG_ETH_SPI_ETHERNET_W5500 is not set
+CONFIG_ETH_SPI_ETHERNET_W5500=y
 # CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set
 # CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set
 # CONFIG_ETH_USE_OPENETH is not set
 # CONFIG_ETH_USE_OPENETH is not set
 # CONFIG_ETH_TRANSMIT_MUTEX is not set
 # CONFIG_ETH_TRANSMIT_MUTEX is not set
@@ -1070,11 +1069,9 @@ CONFIG_SPIRAM=y
 #
 #
 # SPI RAM config
 # SPI RAM config
 #
 #
-CONFIG_SPIRAM_MODE_QUAD=y
-# CONFIG_SPIRAM_MODE_OCT is not set
+# CONFIG_SPIRAM_MODE_QUAD is not set
+CONFIG_SPIRAM_MODE_OCT=y
 CONFIG_SPIRAM_TYPE_AUTO=y
 CONFIG_SPIRAM_TYPE_AUTO=y
-# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set
-# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set
 # CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set
 # CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set
 CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y
 CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y
 CONFIG_SPIRAM_CLK_IO=30
 CONFIG_SPIRAM_CLK_IO=30
@@ -1082,11 +1079,12 @@ CONFIG_SPIRAM_CS_IO=26
 # CONFIG_SPIRAM_XIP_FROM_PSRAM is not set
 # CONFIG_SPIRAM_XIP_FROM_PSRAM is not set
 # CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set
 # CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set
 # CONFIG_SPIRAM_RODATA is not set
 # CONFIG_SPIRAM_RODATA is not set
-# CONFIG_SPIRAM_SPEED_120M is not set
-# CONFIG_SPIRAM_SPEED_80M is not set
-CONFIG_SPIRAM_SPEED_40M=y
-CONFIG_SPIRAM_SPEED=40
+CONFIG_SPIRAM_SPEED_80M=y
+# CONFIG_SPIRAM_SPEED_40M is not set
+CONFIG_SPIRAM_SPEED=80
+# CONFIG_SPIRAM_ECC_ENABLE is not set
 CONFIG_SPIRAM_BOOT_INIT=y
 CONFIG_SPIRAM_BOOT_INIT=y
+# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set
 # CONFIG_SPIRAM_USE_MEMMAP is not set
 # CONFIG_SPIRAM_USE_MEMMAP is not set
 # CONFIG_SPIRAM_USE_CAPS_ALLOC is not set
 # CONFIG_SPIRAM_USE_CAPS_ALLOC is not set
 CONFIG_SPIRAM_USE_MALLOC=y
 CONFIG_SPIRAM_USE_MALLOC=y
@@ -1094,7 +1092,7 @@ CONFIG_SPIRAM_MEMTEST=y
 CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
 CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
 CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
 CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
 CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=40960
 CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=40960
-CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
+# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set
 # end of SPI RAM config
 # end of SPI RAM config
 # end of ESP PSRAM
 # end of ESP PSRAM
 
 
@@ -2146,3 +2144,194 @@ CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX=32768
 # end of Component config
 # end of Component config
 
 
 # CONFIG_IDF_EXPERIMENTAL_FEATURES is not set
 # CONFIG_IDF_EXPERIMENTAL_FEATURES is not set
+
+# Deprecated options for backward compatibility
+# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set
+# CONFIG_NO_BLOBS is not set
+# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set
+CONFIG_LOG_BOOTLOADER_LEVEL_ERROR=y
+# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set
+# CONFIG_LOG_BOOTLOADER_LEVEL_INFO is not set
+# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set
+# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set
+CONFIG_LOG_BOOTLOADER_LEVEL=1
+# CONFIG_APP_ROLLBACK_ENABLE is not set
+# CONFIG_FLASH_ENCRYPTION_ENABLED is not set
+# CONFIG_FLASHMODE_QIO is not set
+# CONFIG_FLASHMODE_QOUT is not set
+CONFIG_FLASHMODE_DIO=y
+# CONFIG_FLASHMODE_DOUT is not set
+CONFIG_MONITOR_BAUD=115200
+# CONFIG_OPTIMIZATION_LEVEL_DEBUG is not set
+# CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set
+# CONFIG_COMPILER_OPTIMIZATION_DEFAULT is not set
+CONFIG_OPTIMIZATION_LEVEL_RELEASE=y
+CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y
+# CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED is not set
+# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set
+CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED=y
+CONFIG_OPTIMIZATION_ASSERTION_LEVEL=0
+# CONFIG_CXX_EXCEPTIONS is not set
+CONFIG_STACK_CHECK_NONE=y
+# CONFIG_STACK_CHECK_NORM is not set
+# CONFIG_STACK_CHECK_STRONG is not set
+# CONFIG_STACK_CHECK_ALL is not set
+# CONFIG_WARN_WRITE_STRINGS is not set
+# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set
+CONFIG_ESP32_APPTRACE_DEST_NONE=y
+CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y
+# CONFIG_EXTERNAL_COEX_ENABLE is not set
+# CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set
+# CONFIG_MCPWM_ISR_IN_IRAM is not set
+# CONFIG_EVENT_LOOP_PROFILING is not set
+CONFIG_POST_EVENTS_FROM_ISR=y
+CONFIG_POST_EVENTS_FROM_IRAM_ISR=y
+CONFIG_GDBSTUB_SUPPORT_TASKS=y
+CONFIG_GDBSTUB_MAX_TASKS=32
+# CONFIG_OTA_ALLOW_HTTP is not set
+CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000
+CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000
+CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y
+# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS is not set
+# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_OSC is not set
+# CONFIG_ESP32S3_RTC_CLK_SRC_INT_8MD256 is not set
+CONFIG_ESP32S3_RTC_CLK_CAL_CYCLES=1024
+CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y
+# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set
+CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20
+CONFIG_ESP32_PHY_MAX_TX_POWER=20
+# CONFIG_REDUCE_PHY_TX_POWER is not set
+# CONFIG_ESP32_REDUCE_PHY_TX_POWER is not set
+CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y
+CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_DEFAULT_PSRAM_CLK_IO=30
+CONFIG_DEFAULT_PSRAM_CS_IO=26
+# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set
+CONFIG_ESP32S3_DEFAULT_CPU_FREQ_160=y
+# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240 is not set
+CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=160
+CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
+CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4864
+CONFIG_MAIN_TASK_STACK_SIZE=3584
+CONFIG_CONSOLE_UART_DEFAULT=y
+# CONFIG_CONSOLE_UART_CUSTOM is not set
+# CONFIG_CONSOLE_UART_NONE is not set
+# CONFIG_ESP_CONSOLE_UART_NONE is not set
+CONFIG_CONSOLE_UART=y
+CONFIG_CONSOLE_UART_NUM=0
+CONFIG_CONSOLE_UART_BAUDRATE=115200
+CONFIG_INT_WDT=y
+CONFIG_INT_WDT_TIMEOUT_MS=300
+CONFIG_INT_WDT_CHECK_CPU1=y
+# CONFIG_TASK_WDT is not set
+# CONFIG_ESP_TASK_WDT is not set
+# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set
+CONFIG_ESP32S3_DEBUG_OCDAWARE=y
+CONFIG_BROWNOUT_DET=y
+CONFIG_ESP32S3_BROWNOUT_DET=y
+CONFIG_ESP32S3_BROWNOUT_DET=y
+CONFIG_BROWNOUT_DET_LVL_SEL_7=y
+CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_7=y
+# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set
+# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_6 is not set
+# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set
+# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_5 is not set
+# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set
+# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_4 is not set
+# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set
+# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_3 is not set
+# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set
+# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_2 is not set
+# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set
+# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_1 is not set
+CONFIG_BROWNOUT_DET_LVL=7
+CONFIG_ESP32S3_BROWNOUT_DET_LVL=7
+CONFIG_IPC_TASK_STACK_SIZE=1280
+CONFIG_TIMER_TASK_STACK_SIZE=3584
+CONFIG_ESP32_WIFI_ENABLED=y
+CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16
+CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=16
+CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y
+CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0
+CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16
+CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=16
+# CONFIG_ESP32_WIFI_CSI_ENABLED is not set
+CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y
+CONFIG_ESP32_WIFI_TX_BA_WIN=6
+CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
+CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
+CONFIG_ESP32_WIFI_RX_BA_WIN=16
+CONFIG_ESP32_WIFI_RX_BA_WIN=16
+# CONFIG_ESP32_WIFI_AMSDU_TX_ENABLED is not set
+CONFIG_ESP32_WIFI_NVS_ENABLED=y
+CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y
+# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set
+CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752
+CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32
+CONFIG_ESP32_WIFI_IRAM_OPT=y
+CONFIG_ESP32_WIFI_RX_IRAM_OPT=y
+CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y
+CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA=y
+CONFIG_WPA_MBEDTLS_CRYPTO=y
+CONFIG_WPA_MBEDTLS_TLS_CLIENT=y
+# CONFIG_WPA_WAPI_PSK is not set
+# CONFIG_WPA_SUITE_B_192 is not set
+# CONFIG_WPA_11KV_SUPPORT is not set
+# CONFIG_WPA_MBO_SUPPORT is not set
+# CONFIG_WPA_DPP_SUPPORT is not set
+# CONFIG_WPA_11R_SUPPORT is not set
+# CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set
+# CONFIG_WPA_WPS_STRICT is not set
+# CONFIG_WPA_DEBUG_PRINT is not set
+# CONFIG_WPA_TESTING_OPTIONS is not set
+# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set
+# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set
+CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y
+CONFIG_TIMER_TASK_PRIORITY=1
+CONFIG_TIMER_TASK_STACK_DEPTH=2048
+CONFIG_TIMER_QUEUE_LENGTH=10
+# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set
+# CONFIG_L2_TO_L3_COPY is not set
+CONFIG_ESP_GRATUITOUS_ARP=y
+CONFIG_GARP_TMR_INTERVAL=60
+CONFIG_TCPIP_RECVMBOX_SIZE=32
+CONFIG_TCP_MAXRTX=12
+CONFIG_TCP_SYNMAXRTX=12
+CONFIG_TCP_MSS=1440
+CONFIG_TCP_MSL=60000
+CONFIG_TCP_SND_BUF_DEFAULT=5760
+CONFIG_TCP_WND_DEFAULT=5760
+CONFIG_TCP_RECVMBOX_SIZE=6
+CONFIG_TCP_QUEUE_OOSEQ=y
+CONFIG_TCP_OVERSIZE_MSS=y
+# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set
+# CONFIG_TCP_OVERSIZE_DISABLE is not set
+CONFIG_UDP_RECVMBOX_SIZE=6
+CONFIG_TCPIP_TASK_STACK_SIZE=3072
+CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y
+# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set
+# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set
+CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF
+# CONFIG_PPP_SUPPORT is not set
+CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_SYSTIMER=y
+CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_FRC1=y
+# CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC is not set
+# CONFIG_ESP32S3_TIME_SYSCALL_USE_SYSTIMER is not set
+# CONFIG_ESP32S3_TIME_SYSCALL_USE_FRC1 is not set
+# CONFIG_ESP32S3_TIME_SYSCALL_USE_NONE is not set
+CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5
+CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072
+CONFIG_ESP32_PTHREAD_STACK_MIN=768
+CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y
+# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set
+# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set
+CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1
+CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread"
+CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y
+# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set
+# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set
+CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y
+CONFIG_SUPPORT_TERMIOS=y
+CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1
+# End of deprecated options

+ 29 - 29
sd-card/html/edit_config_template.html

@@ -1744,14 +1744,14 @@
         </tr>
         </tr>
         <!------------- GPIO4 end ------------------>
         <!------------- GPIO4 end ------------------>
 
 
-        <!------------- GPIO12 begin ------------------>
+        <!------------- GPIO47 begin ------------------>
         <tr class="GPIO_item">
         <tr class="GPIO_item">
             <td class="indent1">
             <td class="indent1">
-                <input type="checkbox" id="GPIO_IO12_enabled" value="1"  onclick = 'InvertEnableItem("GPIO", "IO12")' unchecked>
-                <label for=GPIO_IO12_enabled><span id="GPIO_IO12_text">GPIO12 Configuration</span></label>
+                <input type="checkbox" id="GPIO_IO47_enabled" value="1"  onclick = 'InvertEnableItem("GPIO", "IO47")' unchecked>
+                <label for=GPIO_IO47_enabled><span id="GPIO_IO47_text">GPIO47 Configuration</span></label>
             </td>
             </td>
             <td>
             <td>
-                <select id="GPIO_IO12_value1">
+                <select id="GPIO_IO47_value1">
                     <option value="input">input</option>
                     <option value="input">input</option>
                     <option value="input-pullup">input pullup</option>
                     <option value="input-pullup">input pullup</option>
                     <option value="input-pulldown">input pulldown</option>
                     <option value="input-pulldown">input pulldown</option>
@@ -1761,15 +1761,15 @@
                     <option value="external-flash-ws281x">external flash light ws281x controlled</option>
                     <option value="external-flash-ws281x">external flash light ws281x controlled</option>
                 </select>
                 </select>
             </td>
             </td>
-            <td>$TOOLTIP_GPIO_IO12</td>
+            <td>$TOOLTIP_GPIO_IO47</td>
         </tr>
         </tr>
 
 
-        <tr class="GPIO_IO12 GPIO_item expert">
+        <tr class="GPIO_IO47 GPIO_item expert">
             <td class="indent2">
             <td class="indent2">
-                <span class="GPIO_IO12 GPIO_item">GPIO12 Use Interrupt</span>
+                <span class="GPIO_IO47 GPIO_item">GPIO47 Use Interrupt</span>
             </td>
             </td>
             <td>
             <td>
-                <select class="GPIO_IO12 GPIO_item" id="GPIO_IO12_value2">
+                <select class="GPIO_IO47 GPIO_item" id="GPIO_IO47_value2">
                     <option value="disabled">disabled</option>
                     <option value="disabled">disabled</option>
                     <option value="rising-edge">rising edge</option>
                     <option value="rising-edge">rising edge</option>
                     <option value="falling-edge">falling edge</option>
                     <option value="falling-edge">falling edge</option>
@@ -1781,45 +1781,45 @@
             <td></td>
             <td></td>
         </tr>
         </tr>
 
 
-        <tr class="GPIO_IO12 GPIO_item expert">
+        <tr class="GPIO_IO47 GPIO_item expert">
             <td class="indent2">
             <td class="indent2">
-                <span class="GPIO_IO12 GPIO_item">GPIO12 PWM Duty Cycle Resolution</span>
+                <span class="GPIO_IO47 GPIO_item">GPIO47 PWM Duty Cycle Resolution</span>
             </td>
             </td>
             <td>
             <td>
-                <input required type="number" id="GPIO_IO12_value3" min="1" max="20"
+                <input required type="number" id="GPIO_IO47_value3" min="1" max="20"
                     oninput="(!validity.rangeUnderflow||(value=1)) && (!validity.rangeOverflow||(value=20)) && 
                     oninput="(!validity.rangeUnderflow||(value=1)) && (!validity.rangeOverflow||(value=20)) && 
-                        (!validity.stepMismatch||(value=parseInt(this.value)));"><span class="GPIO_IO12 GPIO_item">Bits</span>
+                        (!validity.stepMismatch||(value=parseInt(this.value)));"><span class="GPIO_IO47 GPIO_item">Bits</span>
             </td>
             </td>
             <td></td>
             <td></td>
         </tr>
         </tr>
 
 
-        <tr class="GPIO_IO12 GPIO_item expert">
+        <tr class="GPIO_IO47 GPIO_item expert">
             <td class="indent2">
             <td class="indent2">
-                <span class="GPIO_IO12 GPIO_item">GPIO12 Enable MQTT</span>
+                <span class="GPIO_IO47 GPIO_item">GPIO47 Enable MQTT</span>
             </td>
             </td>
-            <td><input type="checkbox" id="GPIO_IO12_value4"></td>
+            <td><input type="checkbox" id="GPIO_IO47_value4"></td>
             <td></td>
             <td></td>
         </tr>
         </tr>
 
 
-        <tr class="GPIO_IO12 GPIO_item expert">
+        <tr class="GPIO_IO47 GPIO_item expert">
             <td class="indent2">
             <td class="indent2">
-                <span class="GPIO_IO12 GPIO_item">GPIO12 Enable REST API</span>
+                <span class="GPIO_IO47 GPIO_item">GPIO47 Enable REST API</span>
             </td>
             </td>
-            <td><input type="checkbox" id="GPIO_IO12_value5"></td>
+            <td><input type="checkbox" id="GPIO_IO47_value5"></td>
             <td></td>
             <td></td>
         </tr>
         </tr>
 
 
-        <tr class="GPIO_IO12 GPIO_item expert">
+        <tr class="GPIO_IO47 GPIO_item expert">
             <td class="indent2">
             <td class="indent2">
-                <span class="GPIO_IO12 GPIO_item">GPIO12 Name</span>
+                <span class="GPIO_IO47 GPIO_item">GPIO47 Name</span>
             </td>
             </td>
-            <td><input type="text" id="GPIO_IO12_value6"></td>
+            <td><input type="text" id="GPIO_IO47_value6"></td>
             <td></td>
             <td></td>
         </tr>
         </tr>
 
 
         <tr class="GPIO_item" unused_id="wstypeex3">
         <tr class="GPIO_item" unused_id="wstypeex3">
             <td class="indent1">
             <td class="indent1">
-                <span class="GPIO_IO12 GPIO_item" id="GPIO_LEDType_text">LED Type (NeoPixel)</span>
+                <span class="GPIO_IO47 GPIO_item" id="GPIO_LEDType_text">LED Type (NeoPixel)</span>
             </td>
             </td>
             <td class="GPIO_item">
             <td class="GPIO_item">
                 <select class="GPIO_item" id="GPIO_LEDType_value1">
                 <select class="GPIO_item" id="GPIO_LEDType_value1">
@@ -1848,7 +1848,7 @@
                 <span class="GPIO_item" id="GPIO_LEDColor_text">LED Color</span>
                 <span class="GPIO_item" id="GPIO_LEDColor_text">LED Color</span>
             </td>
             </td>
             <td>
             <td>
-                R <input required type="number" class="GPIO_IO12 GPIO_item" id="GPIO_LEDColor_value1"
+                R <input required type="number" class="GPIO_IO47 GPIO_item" id="GPIO_LEDColor_value1"
                     min="0" max="255" step="1" oninput="(!validity.rangeUnderflow||(value=0)) && (!validity.rangeOverflow||(value=255)) && 
                     min="0" max="255" step="1" oninput="(!validity.rangeUnderflow||(value=0)) && (!validity.rangeOverflow||(value=255)) && 
                         (!validity.stepMismatch||(value=parseInt(this.value)));">
                         (!validity.stepMismatch||(value=parseInt(this.value)));">
             </td>
             </td>
@@ -1858,7 +1858,7 @@
         <tr class="GPIO_item" unused_id="LEDRGBex9">
         <tr class="GPIO_item" unused_id="LEDRGBex9">
             <td></td>
             <td></td>
             <td>			
             <td>			
-                G <input required type="number" class="GPIO_IO12 GPIO_item" id="GPIO_LEDColor_value2"
+                G <input required type="number" class="GPIO_IO47 GPIO_item" id="GPIO_LEDColor_value2"
                     min="0" max="255" step="1" oninput="(!validity.rangeUnderflow||(value=0)) && (!validity.rangeOverflow||(value=255)) && 
                     min="0" max="255" step="1" oninput="(!validity.rangeUnderflow||(value=0)) && (!validity.rangeOverflow||(value=255)) && 
                         (!validity.stepMismatch||(value=parseInt(this.value)));">
                         (!validity.stepMismatch||(value=parseInt(this.value)));">
             </td>
             </td>
@@ -1867,12 +1867,12 @@
         <tr class="GPIO_item" unused_id="LEDRGBex9">
         <tr class="GPIO_item" unused_id="LEDRGBex9">
             <td></td>		
             <td></td>		
             <td>				
             <td>				
-                B <input required type="number" class="GPIO_IO12 GPIO_item" id="GPIO_LEDColor_value3"
+                B <input required type="number" class="GPIO_IO47 GPIO_item" id="GPIO_LEDColor_value3"
                     min="0" max="255" step="1" oninput="(!validity.rangeUnderflow||(value=0)) && (!validity.rangeOverflow||(value=255)) && 
                     min="0" max="255" step="1" oninput="(!validity.rangeUnderflow||(value=0)) && (!validity.rangeOverflow||(value=255)) && 
                         (!validity.stepMismatch||(value=parseInt(this.value)));">
                         (!validity.stepMismatch||(value=parseInt(this.value)));">
             </td>
             </td>
         </tr>
         </tr>
-        <!------------- GPIO12 end ------------------>
+        <!------------- GPIO47 end ------------------>
 
 
         <!------------- GPIO13 begin ------------------>
         <!------------- GPIO13 begin ------------------>
         <tr class="GPIO_IO13 GPIO_item expert">
         <tr class="GPIO_IO13 GPIO_item expert">
@@ -2394,7 +2394,7 @@ function UpdateInput() {
     WriteParameter(param, category, "GPIO", "IO1", true);
     WriteParameter(param, category, "GPIO", "IO1", true);
     WriteParameter(param, category, "GPIO", "IO3", true);
     WriteParameter(param, category, "GPIO", "IO3", true);
     WriteParameter(param, category, "GPIO", "IO4", true);
     WriteParameter(param, category, "GPIO", "IO4", true);
-    WriteParameter(param, category, "GPIO", "IO12", true);
+    WriteParameter(param, category, "GPIO", "IO47", true);
     WriteParameter(param, category, "GPIO", "IO13", true);
     WriteParameter(param, category, "GPIO", "IO13", true);
     WriteParameter(param, category, "GPIO", "LEDType", false);
     WriteParameter(param, category, "GPIO", "LEDType", false);
     WriteParameter(param, category, "GPIO", "LEDNumbers", false);
     WriteParameter(param, category, "GPIO", "LEDNumbers", false);
@@ -2562,7 +2562,7 @@ function ReadParameterAll() {
     ReadParameter(param, "GPIO", "IO1", true);
     ReadParameter(param, "GPIO", "IO1", true);
     ReadParameter(param, "GPIO", "IO3", true);
     ReadParameter(param, "GPIO", "IO3", true);
     ReadParameter(param, "GPIO", "IO4", true);
     ReadParameter(param, "GPIO", "IO4", true);
-    ReadParameter(param, "GPIO", "IO12", true);
+    ReadParameter(param, "GPIO", "IO47", true);
     ReadParameter(param, "GPIO", "IO13", true);
     ReadParameter(param, "GPIO", "IO13", true);
     ReadParameter(param, "GPIO", "LEDType", false);
     ReadParameter(param, "GPIO", "LEDType", false);
     ReadParameter(param, "GPIO", "LEDNumbers", false);
     ReadParameter(param, "GPIO", "LEDNumbers", false);
@@ -2641,7 +2641,7 @@ function UpdateExpertModus() {
         }
         }
     });	
     });	
 
 
-    Array.from(document.querySelector("#GPIO_IO12_value1").options).forEach(function(option_element) {
+    Array.from(document.querySelector("#GPIO_IO47_value1").options).forEach(function(option_element) {
         if (option_element.value != "external-flash-ws281x") {
         if (option_element.value != "external-flash-ws281x") {
             option_element.hidden = _hidden;
             option_element.hidden = _hidden;
         }
         }

+ 1 - 1
sd-card/html/readconfigparam.js

@@ -247,7 +247,7 @@ function ParseConfig() {
     ParamAddValue(param, catname, "IO1", 6, false, "",  [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
     ParamAddValue(param, catname, "IO1", 6, false, "",  [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
     ParamAddValue(param, catname, "IO3", 6, false, "",  [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
     ParamAddValue(param, catname, "IO3", 6, false, "",  [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
     ParamAddValue(param, catname, "IO4", 6, false, "",  [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
     ParamAddValue(param, catname, "IO4", 6, false, "",  [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
-    ParamAddValue(param, catname, "IO12", 6, false, "",  [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
+    ParamAddValue(param, catname, "IO47", 6, false, "",  [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
     ParamAddValue(param, catname, "IO13", 6, false, "",  [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
     ParamAddValue(param, catname, "IO13", 6, false, "",  [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
     ParamAddValue(param, catname, "LEDType");
     ParamAddValue(param, catname, "LEDType");
     ParamAddValue(param, catname, "LEDNumbers");
     ParamAddValue(param, catname, "LEDNumbers");