HTTPS server

This commit is contained in:
iranl
2024-12-31 14:54:10 +01:00
parent ff6bf704a2
commit c8c2980537
8 changed files with 389 additions and 51 deletions

View File

@@ -52,20 +52,16 @@ See the "[Connecting via Ethernet](#connecting-via-ethernet-optional)" section f
## Recommended ESP32 devices
- If WIFI6 is absolutely required: ESP32-C6
- If PoE is required: Any of the above mentioned devices with PoE or any other ESP device in combination with a SPI Ethernet module ([W5500](https://www.aliexpress.com/w/wholesale-w5500.html)) and [PoE to Ethernet and USB type B/C splitter](https://aliexpress.com/w/wholesale-poe-splitter-usb-c.html)
- If you want maximum performance and intend to run any or multiple of the following:
- a Nuki Lock and Nuki Opener and/or
- MQTT SSL and/or
- HTTP SSL and/or
- large amounts of keypad codes, timecontrol or authorization entries
- Developing/debugging Nuki devices and/or Nuki Hub
We don't recommend using single-core ESP32 devices (ESP32-C3, ESP32-C6, ESP32-H2, ESP32-Solo1).<br>
Although NukiHub supports single-core devices, NukiHub uses both CPU cores (if available) to process tasks (e.g. HTTP server/MQTT client/BLE scanner/BLE client) and thus runs much better on dual-core devices.<br>
An ESP32-S3 with 2MB of PSRAM or more (look for an ESP32-S3 with the designation N>=4 and R>=2 such as an ESP32-S3 N16R8)
When buying a new device in 2025 we can only recommend the ESP32-S3 with PSRAM (look for an ESP32-S3 with the designation N>=4 and R>=2 such as an ESP32-S3 N16R8).<br>
The ESP32-S3 is a dual-core CPU with many GPIO's, ability to enlarge RAM using PSRAM, ability to connect Ethernet modules over SPI and optionally power the device with a PoE splitter.<br>
The only functions missing from the ESP32-S3 as compared to other ESP devices is the ability to use some Ethernet modules only supported by the original ESP32 (and ESP32-P4) and the ability to connect over WIFI6 (C6 or ESP32-P4 with C6 module)
- In general when buying a new device when size and a couple of dollars more or less are not an issue: An ESP32-S3 with 2MB of PSRAM or more.<br>
The ESP32-S3 is a dual-core CPU with many GPIO's, ability to enlarge RAM using PSRAM, ability to connect Ethernet modules over SPI and optionally power the device with a PoE splitter. The only functions missing from the ESP32-S3 as compared to other ESP devices is the ability to use some Ethernet modules only supported by the original ESP32 and the ability to connect over WIFI6 (C6)
Other considerations:
- If PoE is required: An ESP32-S3 with PSRAM in combination with a SPI Ethernet module ([W5500](https://www.aliexpress.com/w/wholesale-w5500.html)) and [PoE to Ethernet and USB type B/C splitter](https://aliexpress.com/w/wholesale-poe-splitter-usb-c.html) or the M5stack Atom S3R with the M5stack AtomPoe W5500 module
- If WIFI6 is absolutely required (it probably isn't): ESP32-C6
## Feature comparison
@@ -194,6 +190,8 @@ In a browser navigate to the IP address assigned to the ESP32.
- RSSI Publish interval: Set to a positive integer to set the amount of seconds between updates to the maintenance/wifiRssi MQTT topic with the current Wi-Fi RSSI, set to -1 to disable, default 60.
- Restart on disconnect: Enable to restart the Nuki Hub when disconnected from the network.
- Check for Firmware Updates every 24h: Enable to allow the Nuki Hub to check the latest release of the Nuki Hub firmware on boot and every 24 hours. Requires the Nuki Hub to be able to connect to github.com. The latest version will be published to MQTT and will be visible on the main page of the Web Configurator.
- HTTP SSL Certificate (PSRAM enabled devices only): Optionally set to the SSL certificate of the HTTPS server, see the "[HTTPS Server](#https-server-optional-psram-enabled-devices-only)" section of this README.
- HTTP SSL Key (PSRAM enabled devices only): Optionally set to the SSL key of the HTTPS server, see the "[HTTPS Server](#https-server-optional-psram-enabled-devices-only)" section of this README.
#### IP Address assignment
@@ -575,6 +573,23 @@ openssl req -new -key server.key -out server.csr -subj "/C=US/ST=YourState/L=You
# sign it
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650
```
## HTTPS Server (optional, PSRAM enabled devices only)
The Webconfigurator can use/force HTTPS on PSRAM enabled devices.<br>
To enable SSL encryption, supply the certificate and key in the Network configuration page and reboot NukiHub.<br>
Example self-signed certificate creation for your HTTPS server:
```console
# make a Certificate and key pair, MAKE SURE THE CN MATCHES THE DOMAIN AT WHICH NUKIHUB IS AVAILABLE
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout nukihub.key -out nukihub.crt -subj "/C=US/ST=YourState/L=YourCity/O=YourOrganization/OU=YourUnit/CN=YourCAName"
```
Although you can use the HTTPS server in this way your client device will not trust the certificate by default.
An option would be to configure a proxy SSL server (such as Caddy, Traefik, nginx) with a non-self signed (e.g. let's encrypt) SSL certificate and have this proxy server connect to NukiHub over SSL and trust the self-signed NukiHub certificate for this connection.
## Home Assistant Discovery (optional)
This software supports [MQTT Discovery](https://www.home-assistant.io/docs/mqtt/discovery/) for integrating Nuki Hub with Home Assistant.<br>

View File

@@ -33,8 +33,8 @@ build_unflags =
build_flags =
-fexceptions
-DTLS_CA_MAX_SIZE=2200
-DTLS_CERT_MAX_SIZE=1500
-DTLS_KEY_MAX_SIZE=1800
-DTLS_CERT_MAX_SIZE=2200
-DTLS_KEY_MAX_SIZE=2200
-DESP_PLATFORM
-DESP32
-DARDUINO_ARCH_ESP32

View File

@@ -74,7 +74,6 @@ CONFIG_ARDUINO_SELECTIVE_ESP_SR=n
CONFIG_ARDUINO_SELECTIVE_Zigbee=n
CONFIG_ARDUINO_SELECTIVE_SD=n
CONFIG_ARDUINO_SELECTIVE_SD_MMC=n
CONFIG_ARDUINO_SELECTIVE_SPIFFS=n
CONFIG_ARDUINO_SELECTIVE_FFat=n
CONFIG_ARDUINO_SELECTIVE_LittleFS=n
CONFIG_ARDUINO_SELECTIVE_PPP=n
@@ -98,11 +97,15 @@ CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="resources/github_root_ca.pem"
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH=y
CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
CONFIG_HTTPD_MAX_REQ_HDR_LEN=2048
CONFIG_HTTPD_MAX_URI_LEN=512
CONFIG_HTTPD_ERR_RESP_NO_DELAY=y
CONFIG_HTTPD_PURGE_BUF_LEN=32
CONFIG_HTTPD_WS_SUPPORT=y
CONFIG_ESP_HTTPS_SERVER_ENABLE=n
CONFIG_ESP_HTTPS_SERVER_ENABLE=y
CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE=y
CONFIG_BOOTLOADER_WDT_TIME_MS=120000
CONFIG_LWIP_MAX_SOCKETS=24
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=1024
CONFIG_ARDUINO_LOOP_STACK_SIZE=12288

View File

@@ -5,7 +5,7 @@
#define NUKI_HUB_VERSION "9.07"
#define NUKI_HUB_VERSION_INT (uint32_t)907
#define NUKI_HUB_BUILD "unknownbuildnr"
#define NUKI_HUB_DATE "2024-12-30"
#define NUKI_HUB_DATE "2024-12-31"
#define GITHUB_LATEST_RELEASE_URL (char*)"https://github.com/technyon/nuki_hub/releases/latest"
#define GITHUB_OTA_MANIFEST_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/manifest.json"

View File

@@ -5,7 +5,9 @@
#include "RestartReason.h"
#include <esp_task_wdt.h>
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
#include <esp_psram.h>
#include "esp_psram.h"
#include "FS.h"
#include "SPIFFS.h"
#endif
#ifndef CONFIG_IDF_TARGET_ESP32H2
#include <esp_wifi.h>
@@ -297,6 +299,14 @@ void WebCfgServer::initialize()
{
return buildMqttSSLConfigHtml(request, resp, 2);
}
else if (value == "httpcrtconfig")
{
return buildHttpSSLConfigHtml(request, resp, 1);
}
else if (value == "httpkeyconfig")
{
return buildHttpSSLConfigHtml(request, resp, 2);
}
else if (value == "nukicfg")
{
return buildNukiConfigHtml(request, resp);
@@ -428,6 +438,10 @@ void WebCfgServer::initialize()
{
return buildConfirmHtml(request, resp, message, 3, true, "/get?page=mqttconfig");
}
else if(request->hasParam("httpssl"))
{
return buildConfirmHtml(request, resp, message, 3, true, "/get?page=ntwconfig");
}
else
{
return buildConfirmHtml(request, resp, message, 3, true);
@@ -1588,6 +1602,74 @@ bool WebCfgServer::processArgs(PsychicRequest *request, PsychicResponse* resp, S
configChanged = true;
}
}
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
else if(key == "HTTPCRT")
{
if (!SPIFFS.begin(true)) {
Log->println("SPIFFS Mount Failed");
}
else
{
if(value != "")
{
File file = SPIFFS.open("/http_ssl.crt", FILE_WRITE);
if (!file) {
Log->println("Failed to open /http_ssl.crt for writing");
}
else
{
if (!file.print(value))
{
Log->println("Failed to write /http_ssl.crt");
}
file.close();
}
}
else
{
if (!SPIFFS.remove("/http_ssl.crt")) {
Serial.println("Failed to delete /http_ssl.crt");
}
}
Log->print(F("Setting changed: "));
Log->println(key);
configChanged = true;
}
}
else if(key == "HTTPKEY")
{
if (!SPIFFS.begin(true)) {
Log->println("SPIFFS Mount Failed");
}
else
{
if(value != "")
{
File file = SPIFFS.open("/http_ssl.key", FILE_WRITE);
if (!file) {
Log->println("Failed to open /http_ssl.key for writing");
}
else
{
if (!file.print(value))
{
Log->println("Failed to write /http_ssl.key");
}
file.close();
}
}
else
{
if (!SPIFFS.remove("/http_ssl.key")) {
Serial.println("Failed to delete /http_ssl.key");
}
}
Log->print(F("Setting changed: "));
Log->println(key);
configChanged = true;
}
}
#endif
else if(key == "NWHW")
{
if(_preferences->getInt(preference_network_hardware, 0) != value.toInt())
@@ -3681,6 +3763,13 @@ esp_err_t WebCfgServer::buildNetworkConfigHtml(PsychicRequest *request, PsychicR
printCheckBox(&response, "RSTDISC", "Restart on disconnect", _preferences->getBool(preference_restart_on_disconnect), "");
printCheckBox(&response, "CHECKUPDATE", "Check for Firmware Updates every 24h", _preferences->getBool(preference_check_updates), "");
printCheckBox(&response, "FINDBESTRSSI", "Find WiFi AP with strongest signal", _preferences->getBool(preference_find_best_rssi, false), "");
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
if(esp_psram_get_size() > 0)
{
response.print("<tr><td>Set HTTP SSL Certificate</td><td><button title=\"Set HTTP SSL Certificate\" onclick=\" window.open('/get?page=httpcrtconfig', '_self'); return false;\">Change</button></td></tr>");
response.print("<tr><td>Set HTTP SSL Key</td><td><button title=\"Set MQTT SSL Key\" onclick=\" window.open('/get?page=httpkeyconfig', '_self'); return false;\">Change</button></td></tr>");
}
#endif
response.print("</table>");
response.print("<h3>IP Address assignment</h3>");
response.print("<table>");
@@ -3722,7 +3811,7 @@ esp_err_t WebCfgServer::buildMqttConfigHtml(PsychicRequest *request, PsychicResp
printCheckBox(&response, "OPENERCONT", "Set Nuki Opener Lock/Unlock action in Home Assistant to Continuous mode", _preferences->getBool(preference_opener_continuous_mode), "");
}
response.print("<tr><td>Set MQTT SSL CA Certificate</td><td><button title=\"Set MQTT SSL CA Certificate\" onclick=\" window.open('/get?page=mqttcaconfig', '_self'); return false;\">Change</button></td></tr>");
response.print("<tr><td>Set MQTT SSL Client Certificate</td><td><button title=\"Set MQTT Client CA Certificate\" onclick=\" window.open('/get?page=mqttcrtconfig', '_self'); return false;\">Change</button></td></tr>");
response.print("<tr><td>Set MQTT SSL Client Certificate</td><td><button title=\"Set MQTT Client Certificate\" onclick=\" window.open('/get?page=mqttcrtconfig', '_self'); return false;\">Change</button></td></tr>");
response.print("<tr><td>Set MQTT SSL Client Key</td><td><button title=\"Set MQTT SSL Client Key\" onclick=\" window.open('/get?page=mqttkeyconfig', '_self'); return false;\">Change</button></td></tr>");
printInputField(&response, "NETTIMEOUT", "MQTT Timeout until restart (seconds; -1 to disable)", _preferences->getInt(preference_network_timeout), 5, "");
printCheckBox(&response, "MQTTLOG", "Enable MQTT logging", _preferences->getBool(preference_mqtt_log_enabled), "");
@@ -3773,6 +3862,81 @@ esp_err_t WebCfgServer::buildMqttSSLConfigHtml(PsychicRequest *request, PsychicR
return response.endSend();
}
esp_err_t WebCfgServer::buildHttpSSLConfigHtml(PsychicRequest *request, PsychicResponse* resp, int type)
{
PsychicStreamResponse response(resp, "text/html");
response.beginSend();
buildHtmlHeader(&response);
response.print("<form class=\"adapt\" method=\"post\" action=\"post\">");
response.print("<input type=\"hidden\" name=\"page\" value=\"savecfg\">");
response.print("<input type=\"hidden\" name=\"httpssl\" value=\"1\">");
response.print("<h3>HTTP SSL Configuration</h3>");
response.print("<table>");
if (type == 1)
{
char cert[4400] = {0};
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
if (!SPIFFS.begin(true)) {
Log->println("SPIFFS Mount Failed");
}
else
{
File file = SPIFFS.open("/http_ssl.crt");
if (!file || file.isDirectory()) {
Log->println("http_ssl.crt not found");
}
else
{
Log->println("Reading http_ssl.crt");
uint32_t i = 0;
while(file.available()){
cert[i] = file.read();
i++;
}
file.close();
}
}
#endif
printTextarea(&response, "HTTPCRT", "HTTP SSL Certificate (*, optional)", cert, 4400, true, true);
}
else
{
char key[2200] = {0};
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
if (!SPIFFS.begin(true)) {
Log->println("SPIFFS Mount Failed");
}
else
{
File file = SPIFFS.open("/http_ssl.key");
if (!file || file.isDirectory()) {
Log->println("http_ssl.key not found");
}
else
{
Log->println("Reading http_ssl.key");
uint32_t i = 0;
while(file.available()){
key[i] = file.read();
i++;
}
file.close();
}
}
#endif
printTextarea(&response, "HTTPKEY", "HTTP SSL Key (*, optional)", key, 2200, true, true);
}
response.print("</table>");
response.print("<br><input type=\"submit\" name=\"submit\" value=\"Save\">");
response.print("</form>");
response.print("</body>");
response.print("</html>");
return response.endSend();
}
esp_err_t WebCfgServer::buildAdvancedConfigHtml(PsychicRequest *request, PsychicResponse* resp)
{
PsychicStreamResponse response(resp, "text/html");
@@ -4348,6 +4512,10 @@ esp_err_t WebCfgServer::buildInfoHtml(PsychicRequest *request, PsychicResponse*
response.print(_preferences->getString(preference_cred_password, "").length() > 0 ? "***" : "Not set");
response.print("\nWeb configurator enabled: ");
response.print(_preferences->getBool(preference_webserver_enabled, true) ? "Yes" : "No");
//response.print("\nHTTP SSL CRT: ");
//response.print(_preferences->getString(preference_http_crt, "").length() > 0 ? "***" : "Not set");
//response.print("\nHTTP SSL Key: ");
//response.print(_preferences->getString(preference_http_key, "").length() > 0 ? "***" : "Not set");
response.print("\nPublish debug information enabled: ");
response.print(_preferences->getBool(preference_publish_debug_info, false) ? "Yes" : "No");
response.print("\nMQTT log enabled: ");

View File

@@ -59,6 +59,7 @@ private:
esp_err_t buildNetworkConfigHtml(PsychicRequest *request, PsychicResponse* resp);
esp_err_t buildMqttConfigHtml(PsychicRequest *request, PsychicResponse* resp);
esp_err_t buildMqttSSLConfigHtml(PsychicRequest *request, PsychicResponse* resp, int type=0);
esp_err_t buildHttpSSLConfigHtml(PsychicRequest *request, PsychicResponse* resp, int type=0);
esp_err_t buildStatusHtml(PsychicRequest *request, PsychicResponse* resp);
esp_err_t buildAdvancedConfigHtml(PsychicRequest *request, PsychicResponse* resp);
esp_err_t buildNukiConfigHtml(PsychicRequest *request, PsychicResponse* resp);

View File

@@ -10,6 +10,11 @@
#include "esp32-hal-log.h"
#include "hal/wdt_hal.h"
#include "esp_chip_info.h"
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
#include "esp_psram.h"
#include "FS.h"
#include "SPIFFS.h"
#endif
#ifndef NUKI_HUB_UPDATER
#include "NukiWrapper.h"
@@ -65,8 +70,10 @@ int64_t restartTs = 10 * 60 * 1000;
#endif
PsychicHttpServer* psychicServer = nullptr;
PsychicHttpsServer* psychicSSLServer = nullptr;
NukiNetwork* network = nullptr;
WebCfgServer* webCfgServer = nullptr;
WebCfgServer* webCfgServerSSL = nullptr;
Preferences* preferences = nullptr;
RTC_NOINIT_ATTR int espRunning;
@@ -539,6 +546,73 @@ void setup()
if(!doOta)
{
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
bool failed = false;
if (esp_psram_get_size() <= 0) {
Log->println("Not running on PSRAM enabled device");
failed = true;
}
else
{
if (!SPIFFS.begin(true)) {
Log->println("SPIFFS Mount Failed");
failed = true;
}
else
{
File file = SPIFFS.open("/http_ssl.crt");
if (!file || file.isDirectory()) {
failed = true;
Log->println("http_ssl.crt not found");
}
else
{
char cert[4400] = {0};
Log->println("Reading http_ssl.crt");
uint32_t i = 0;
while(file.available()){
cert[i] = file.read();
i++;
}
file.close();
File file2 = SPIFFS.open("/http_ssl.key");
if (!file2 || file2.isDirectory()) {
failed = true;
Log->println("http_ssl.key not found");
}
else
{
char key[2200] = {0};
Log->println("Reading http_ssl.key");
i = 0;
while(file2.available()){
key[i] = file2.read();
i++;
}
file2.close();
psychicSSLServer = new PsychicHttpsServer;
psychicSSLServer->ssl_config.httpd.max_open_sockets = 8;
psychicSSLServer->setCertificate(cert, key);
psychicSSLServer->config.stack_size = HTTPD_TASK_SIZE;
webCfgServerSSL = new WebCfgServer(network, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicSSLServer);
webCfgServerSSL->initialize();
psychicSSLServer->onNotFound([](PsychicRequest* request, PsychicResponse* response) {
return response->redirect("/");
});
psychicSSLServer->begin();
}
}
}
}
if (failed)
{
#endif
psychicServer = new PsychicHttpServer;
psychicServer->config.stack_size = HTTPD_TASK_SIZE;
webCfgServer = new WebCfgServer(network, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicServer);
@@ -547,6 +621,9 @@ void setup()
return response->redirect("/");
});
psychicServer->begin();
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
}
#endif
}
#else
if(preferences->getBool(preference_enable_bootloop_reset, false))
@@ -633,17 +710,86 @@ void setup()
if(!doOta && !disableNetwork && (forceEnableWebServer || preferences->getBool(preference_webserver_enabled, true) || preferences->getBool(preference_webserial_enabled, false)))
{
psychicServer = new PsychicHttpServer;
psychicServer->config.stack_size = HTTPD_TASK_SIZE;
if(forceEnableWebServer || preferences->getBool(preference_webserver_enabled, true))
{
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
bool failed = false;
if (esp_psram_get_size() <= 0) {
Log->println("Not running on PSRAM enabled device");
failed = true;
}
else
{
if (!SPIFFS.begin(true)) {
Log->println("SPIFFS Mount Failed");
failed = true;
}
else
{
File file = SPIFFS.open("/http_ssl.crt");
if (!file || file.isDirectory()) {
failed = true;
Log->println("http_ssl.crt not found");
}
else
{
char cert[4400] = {0};
Log->println("Reading http_ssl.crt");
uint32_t i = 0;
while(file.available()){
cert[i] = file.read();
i++;
}
file.close();
File file2 = SPIFFS.open("/http_ssl.key");
if (!file2 || file2.isDirectory()) {
failed = true;
Log->println("http_ssl.key not found");
}
else
{
char key[2200] = {0};
Log->println("Reading http_ssl.key");
i = 0;
while(file2.available()){
key[i] = file2.read();
i++;
}
file2.close();
psychicSSLServer = new PsychicHttpsServer;
psychicSSLServer->ssl_config.httpd.max_open_sockets = 8;
psychicSSLServer->setCertificate(cert, key);
psychicSSLServer->config.stack_size = HTTPD_TASK_SIZE;
webCfgServerSSL = new WebCfgServer(nuki, nukiOpener, network, gpio, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicSSLServer);
webCfgServerSSL->initialize();
psychicSSLServer->onNotFound([](PsychicRequest* request, PsychicResponse* response) {
return response->redirect("/");
});
psychicSSLServer->begin();
}
}
}
}
if (failed)
{
#endif
psychicServer = new PsychicHttpServer;
psychicServer->config.stack_size = HTTPD_TASK_SIZE;
webCfgServer = new WebCfgServer(nuki, nukiOpener, network, gpio, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicServer);
webCfgServer->initialize();
psychicServer->onNotFound([](PsychicRequest* request, PsychicResponse* response) {
return response->redirect("/");
});
psychicServer->begin();
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
}
#endif
}
/*
#ifdef DEBUG_NUKIHUB

View File

@@ -18,7 +18,6 @@ CONFIG_ARDUINO_SELECTIVE_ESP_SR=n
CONFIG_ARDUINO_SELECTIVE_Zigbee=n
CONFIG_ARDUINO_SELECTIVE_SD=n
CONFIG_ARDUINO_SELECTIVE_SD_MMC=n
CONFIG_ARDUINO_SELECTIVE_SPIFFS=n
CONFIG_ARDUINO_SELECTIVE_FFat=n
CONFIG_ARDUINO_SELECTIVE_LittleFS=n
CONFIG_ARDUINO_SELECTIVE_PPP=n
@@ -43,10 +42,16 @@ CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL=y
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH=y
CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
CONFIG_HTTPD_MAX_REQ_HDR_LEN=2048
CONFIG_HTTPD_MAX_URI_LEN=512
CONFIG_HTTPD_ERR_RESP_NO_DELAY=y
CONFIG_HTTPD_PURGE_BUF_LEN=32
CONFIG_HTTPD_WS_SUPPORT=y
CONFIG_ESP_HTTPS_SERVER_ENABLE=n
CONFIG_LOG_MASTER_LEVEL=y
CONFIG_ESP_HTTPS_SERVER_ENABLE=y
CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE=y
CONFIG_BOOTLOADER_WDT_TIME_MS=120000
CONFIG_BOOTLOADER_WDT_TIME_MS=120000
CONFIG_LWIP_MAX_SOCKETS=24
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=1024
CONFIG_ARDUINO_LOOP_STACK_SIZE=12288