[MEM] Reduce ESP32 BLE firmware RAM usage (#2294)

- Fix addLog buffer overflow; reduce LOG_BUFFER_SIZE 6096→3072, ROW_LENGTH 1024→512
- Lazy-allocate web console log buffer (saves ~3.5KB when console not active)
- Stream WebUI responses in chunks to eliminate String heap allocations
- NimBLE buffer tuning: ACL bufs 20→12, HCI hi bufs 30→15, MSYS1 blocks 12→8, MTU 256→185
- BLE adv report flow control 100→50, LWIP sockets 16→10
- BLE scan duplicate cache 200→100 (align with sdkconfig)
- procBLETask stack 9500→8000 (788B headroom over measured peak)
- Cap BLE device vector at 80 with LRU eviction of non-listed devices
- Disable unused LWIP components: PPP, IPv6 autoconfig/DHCPv6
- Disable unused Arduino libs: SD, SD_MMC, FFat, LittleFS, NetBIOS

Measured over 30 min A/B test vs development:
  freemem: 58,805 → 68,755 avg (+10KB)
  minmem:  5,988 → 15,780 (+9.8KB)
  msgprc/scnct: identical (656 msgs, 26 scans)
  msgblck: 0 on both branches
  No crashes or errors

Co-authored-by: Florian <1technophile@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
authored and GitHub committed 2026-03-22 19:05:44 -05:00
1 parent 7d6a019699
commit 3a4eb55a79
4 files changed
+264 -317

No files matched your search

+4 -1
View File
@@ -100,7 +100,10 @@ extern String stateBTMeasures(bool);
#endif #endif
#ifndef BLEScanDuplicateCacheSize #ifndef BLEScanDuplicateCacheSize
# define BLEScanDuplicateCacheSize 200 # define BLEScanDuplicateCacheSize 100
#endif
#ifndef MaxBLEDevices
# define MaxBLEDevices 80
#endif #endif
#ifndef TimeBtwRead #ifndef TimeBtwRead
# define TimeBtwRead 55555 //define default time between 2 scans; in milliseconds # define TimeBtwRead 55555 //define default time between 2 scans; in milliseconds
+18 -1
View File
@@ -372,6 +372,23 @@ void createOrUpdateDevice(const char* mac, uint8_t flags, int model, int mac_typ
} }
BLEdevice* device = getDeviceByMac(mac); BLEdevice* device = getDeviceByMac(mac);
if (device == &NO_BT_DEVICE_FOUND) { if (device == &NO_BT_DEVICE_FOUND) {
// Evict oldest non-listed device when at capacity
if ((int)devices.size() >= MaxBLEDevices) {
int oldestIdx = -1;
unsigned long oldestTime = ULONG_MAX;
for (int i = 0; i < (int)devices.size(); i++) {
if (!devices[i]->isWhtL && !devices[i]->isBlkL && !devices[i]->connect &&
devices[i]->lastUpdate < oldestTime) {
oldestTime = devices[i]->lastUpdate;
oldestIdx = i;
}
}
if (oldestIdx >= 0) {
THEENGS_LOG_TRACE(F("%.4s evict %s" CR), "BLE", devices[oldestIdx]->macAdr);
delete devices[oldestIdx];
devices.erase(devices.begin() + oldestIdx);
}
}
THEENGS_LOG_TRACE(F("add %s" CR), mac); THEENGS_LOG_TRACE(F("add %s" CR), mac);
//new device //new device
device = new BLEdevice(); device = new BLEdevice();
@@ -889,7 +906,7 @@ void setupBTTasksAndBLE() {
# if defined(USE_ESP_IDF) || defined(USE_BLUFI) # if defined(USE_ESP_IDF) || defined(USE_BLUFI)
14500, 14500,
# else # else
9500, /* Stack size in bytes */ 8000, /* Stack size in bytes */
# endif # endif
NULL, /* Task input parameter */ NULL, /* Task input parameter */
2, /* Priority of the task (set higher than core task) */ 2, /* Priority of the task (set higher than core task) */
+228 -297
View File
@@ -27,6 +27,8 @@
# include <WebServer.h> // Docs for this are here - https://github.com/espressif/arduino-esp32/tree/master/libraries/WebServer # include <WebServer.h> // Docs for this are here - https://github.com/espressif/arduino-esp32/tree/master/libraries/WebServer
# include <WiFi.h> # include <WiFi.h>
# include <cstdarg>
# include "TheengsCommon.h" # include "TheengsCommon.h"
# include "config_WebContent.h" # include "config_WebContent.h"
# include "config_WebUI.h" # include "config_WebUI.h"
@@ -71,14 +73,19 @@ extern void receivingDATA(const char* topicOri, const char* datacallback);
/*------------------- Web Console Globals ----------------------*/ /*------------------- Web Console Globals ----------------------*/
# define ROW_LENGTH 1024 # define ROW_LENGTH 512
const uint16_t LOG_BUFFER_SIZE = 6096; const uint16_t LOG_BUFFER_SIZE = 3072;
uint32_t log_buffer_pointer; uint32_t log_buffer_pointer;
void* log_buffer_mutex; void* log_buffer_mutex;
char log_buffer[LOG_BUFFER_SIZE]; // Log buffer in HEAP char* log_buffer = nullptr; // Lazy-allocated on first console access
const uint16_t MAX_LOGSZ = LOG_BUFFER_SIZE - 96; const uint16_t MAX_LOGSZ = LOG_BUFFER_SIZE - 96;
# define LOG_BUFFER_IDLE_TIMEOUT 120000 // Free log buffer after 2 minutes of console inactivity
unsigned long log_buffer_last_access = 0;
static char* line = nullptr;
int lineIndex = 0;
const uint16_t TOPSZ = 151; // Max number of characters in topic string const uint16_t TOPSZ = 151; // Max number of characters in topic string
uint8_t masterlog_level; // Master log level used to override set log level uint8_t masterlog_level; // Master log level used to override set log level
bool reset_web_log_flag = false; // Reset web console log bool reset_web_log_flag = false; // Reset web console log
@@ -88,6 +95,27 @@ String authFailResponse = "Authentication Failed";
bool webUISecure = WEBUI_AUTH; bool webUISecure = WEBUI_AUTH;
boolean displayMetric = DISPLAY_METRIC; boolean displayMetric = DISPLAY_METRIC;
static void ensureLogBuffer() {
if (!log_buffer) {
log_buffer = (char*)calloc(LOG_BUFFER_SIZE, 1);
log_buffer_pointer = 0;
}
log_buffer_last_access = millis();
}
static void freeLogBufferIfIdle() {
if (log_buffer && (millis() - log_buffer_last_access > LOG_BUFFER_IDLE_TIMEOUT)) {
free(log_buffer);
log_buffer = nullptr;
log_buffer_pointer = 0;
if (line) {
free(line);
line = nullptr;
lineIndex = 0;
}
}
}
/*********************************************************************************************\ /*********************************************************************************************\
* ESP32 AutoMutex * ESP32 AutoMutex
\*********************************************************************************************/ \*********************************************************************************************/
@@ -412,6 +440,38 @@ bool exists(String path) {
} }
# endif # endif
/*------------------- Chunked Response Helpers ----------------------*/
// Send HTML pages in chunks to avoid large String heap allocations.
// Each helper puts a temporary buffer on its own stack frame, sends
// the chunk, then the buffer is freed when the helper returns.
static void beginChunkedResponse() {
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
server.send(200, "text/html", "");
}
static void sendHeaderChunk(const char* title) {
char buffer[768];
snprintf(buffer, sizeof(buffer), header_html, title);
server.sendContent(buffer);
}
static void sendBodyChunk(const char* fmt, ...) {
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE];
va_list args;
va_start(args, fmt);
vsnprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, fmt, args);
va_end(args);
server.sendContent(buffer);
}
static void sendFooterChunk() {
char buffer[256];
snprintf(buffer, sizeof(buffer), footer, OMG_VERSION);
server.sendContent(buffer);
server.sendContent(""); // End chunked transfer
}
/** /**
* @brief / - Page * @brief / - Page
* *
@@ -433,18 +493,13 @@ void handleRoot() {
THEENGS_LOG_WARNING(F("[WebUI] Restart" CR)); THEENGS_LOG_WARNING(F("[WebUI] Restart" CR));
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; beginChunkedResponse();
sendHeaderChunk((String(gateway_name) + " - Restart").c_str());
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Restart").c_str()); server.sendContent(restart_script);
String response = String(buffer); server.sendContent(script);
response += String(restart_script); server.sendContent(style);
response += String(script); sendBodyChunk(reset_body, jsonChar, gateway_name, "Restart");
response += String(style); sendFooterChunk();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, reset_body, jsonChar, gateway_name, "Restart");
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
delay(2000); // Wait for web page to be sent before delay(2000); // Wait for web page to be sent before
@@ -456,19 +511,13 @@ void handleRoot() {
} else { } else {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
beginChunkedResponse();
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; sendHeaderChunk((String(gateway_name) + " - Main Menu").c_str());
server.sendContent(root_script);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Main Menu").c_str()); server.sendContent(script);
String response = String(buffer); server.sendContent(style);
response += String(root_script); sendBodyChunk(root_body, jsonChar, gateway_name);
response += String(script); sendFooterChunk();
response += String(style);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, root_body, jsonChar, gateway_name);
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} }
} }
@@ -486,18 +535,12 @@ void handleCN() {
} else { } else {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
beginChunkedResponse();
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; sendHeaderChunk((String(gateway_name) + " - Configuration").c_str());
server.sendContent(script);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Configuration").c_str()); server.sendContent(style);
String response = String(buffer); sendBodyChunk(config_body, jsonChar, gateway_name);
response += String(script); sendFooterChunk();
response += String(style);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_body, jsonChar, gateway_name);
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} }
} }
@@ -534,19 +577,12 @@ void handleWU() {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
beginChunkedResponse();
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; sendHeaderChunk((String(gateway_name) + " - Configure WebUI").c_str());
server.sendContent(script);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Configure WebUI").c_str()); server.sendContent(style);
String response = String(buffer); sendBodyChunk(config_webui_body, jsonChar, gateway_name, (displayMetric ? "checked" : ""), (webUISecure ? "checked" : ""));
response += String(script); sendFooterChunk();
response += String(style);
int logLevel = Log.getLevel();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_webui_body, jsonChar, gateway_name, (displayMetric ? "checked" : ""), (webUISecure ? "checked" : ""));
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} }
/** /**
@@ -628,19 +664,13 @@ void handleWI() {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
beginChunkedResponse();
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; sendHeaderChunk((String(gateway_name) + " - Configure WiFi").c_str());
server.sendContent(wifi_script);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Configure WiFi").c_str()); server.sendContent(script);
String response = String(buffer); server.sendContent(style);
response += String(wifi_script); sendBodyChunk(config_wifi_body, jsonChar, gateway_name, WiFiScan.c_str(), WiFi.SSID().c_str());
response += String(script); sendFooterChunk();
response += String(style);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_wifi_body, jsonChar, gateway_name, WiFiScan.c_str(), WiFi.SSID().c_str());
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
return; return;
} else if (server.hasArg("save")) { } else if (server.hasArg("save")) {
@@ -664,18 +694,13 @@ void handleWI() {
THEENGS_LOG_WARNING(F("[WebUI] Save WiFi and Restart" CR)); THEENGS_LOG_WARNING(F("[WebUI] Save WiFi and Restart" CR));
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; beginChunkedResponse();
sendHeaderChunk((String(gateway_name) + " - Save WiFi and Restart").c_str());
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Save WiFi and Restart").c_str()); server.sendContent(restart_script);
String response = String(buffer); server.sendContent(script);
response += String(restart_script); server.sendContent(style);
response += String(script); sendBodyChunk(reset_body, jsonChar, gateway_name, "Save WiFi and Restart");
response += String(style); sendFooterChunk();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, reset_body, jsonChar, gateway_name, "Save WiFi and Restart");
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
delay(2000); // Wait for web page to be sent before delay(2000); // Wait for web page to be sent before
XtoSYS((char*)topic.c_str(), WEBtoSYS); XtoSYS((char*)topic.c_str(), WEBtoSYS);
@@ -687,19 +712,13 @@ void handleWI() {
} }
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
beginChunkedResponse();
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; sendHeaderChunk((String(gateway_name) + " - Configure WiFi").c_str());
server.sendContent(wifi_script);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Configure WiFi").c_str()); server.sendContent(script);
String response = String(buffer); server.sendContent(style);
response += String(wifi_script); sendBodyChunk(config_wifi_body, jsonChar, gateway_name, WiFiScan.c_str(), WiFi.SSID().c_str());
response += String(script); sendFooterChunk();
response += String(style);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_wifi_body, jsonChar, gateway_name, WiFiScan.c_str(), WiFi.SSID().c_str());
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} }
/** /**
@@ -799,18 +818,13 @@ void handleMQ() {
WEBtoSYS["save_cnt"] = true; WEBtoSYS["save_cnt"] = true;
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; beginChunkedResponse();
sendHeaderChunk((String(gateway_name) + " - Save MQTT and Reconnect").c_str());
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Save MQTT and Reconnect").c_str()); server.sendContent(restart_script);
String response = String(buffer); server.sendContent(script);
response += String(restart_script); server.sendContent(style);
response += String(script); sendBodyChunk(reset_body, jsonChar, gateway_name, "Save MQTT and Reconnect");
response += String(style); sendFooterChunk();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, reset_body, jsonChar, gateway_name, "Save MQTT and Reconnect");
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
delay(2000); // Wait for web page to be sent before delay(2000); // Wait for web page to be sent before
String topic = String(mqtt_topic) + String(gateway_name) + String(subjectMQTTtoSYSset); String topic = String(mqtt_topic) + String(gateway_name) + String(subjectMQTTtoSYSset);
@@ -825,31 +839,25 @@ void handleMQ() {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
beginChunkedResponse();
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; sendHeaderChunk((String(gateway_name) + " - Configure MQTT").c_str());
server.sendContent(script);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Configure MQTT").c_str()); server.sendContent(style);
String response = String(buffer);
response += String(script);
response += String(style);
// mqtt server (mh), mqtt port (ml), mqtt username (mu), mqtt password (mp), secure connection (sc), server certificate (msc), mqtt topic (mt), discovery prefix (dp) (last one only #ifdef ZmqttDiscovery) // mqtt server (mh), mqtt port (ml), mqtt username (mu), mqtt password (mp), secure connection (sc), server certificate (msc), mqtt topic (mt), discovery prefix (dp) (last one only #ifdef ZmqttDiscovery)
# if MQTT_BROKER_MODE # if MQTT_BROKER_MODE
# ifdef ZmqttDiscovery # ifdef ZmqttDiscovery
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_mqtt_body, jsonChar, gateway_name, "", "1883", "", "", gateway_name, mqtt_topic, discovery_prefix); sendBodyChunk(config_mqtt_body, jsonChar, gateway_name, "", "1883", "", "", gateway_name, mqtt_topic, discovery_prefix);
# else # else
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_mqtt_body, jsonChar, gateway_name, "", "1883", "", "", gateway_name, mqtt_topic); sendBodyChunk(config_mqtt_body, jsonChar, gateway_name, "", "1883", "", "", gateway_name, mqtt_topic);
# endif # endif
# else # else
# ifdef ZmqttDiscovery # ifdef ZmqttDiscovery
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_mqtt_body, jsonChar, gateway_name, cnt_parameters_array[CNT_DEFAULT_INDEX].mqtt_server, cnt_parameters_array[CNT_DEFAULT_INDEX].mqtt_port, cnt_parameters_array[CNT_DEFAULT_INDEX].mqtt_user, (cnt_parameters_array[CNT_DEFAULT_INDEX].isConnectionSecure ? "checked" : ""), gateway_name, mqtt_topic, discovery_prefix); sendBodyChunk(config_mqtt_body, jsonChar, gateway_name, cnt_parameters_array[CNT_DEFAULT_INDEX].mqtt_server, cnt_parameters_array[CNT_DEFAULT_INDEX].mqtt_port, cnt_parameters_array[CNT_DEFAULT_INDEX].mqtt_user, (cnt_parameters_array[CNT_DEFAULT_INDEX].isConnectionSecure ? "checked" : ""), gateway_name, mqtt_topic, discovery_prefix);
# else # else
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_mqtt_body, jsonChar, gateway_name, cnt_parameters_array[CNT_DEFAULT_INDEX].mqtt_server, cnt_parameters_array[CNT_DEFAULT_INDEX].mqtt_port, cnt_parameters_array[CNT_DEFAULT_INDEX].mqtt_user, (cnt_parameters_array[CNT_DEFAULT_INDEX].isConnectionSecure ? "checked" : ""), gateway_name, mqtt_topic); sendBodyChunk(config_mqtt_body, jsonChar, gateway_name, cnt_parameters_array[CNT_DEFAULT_INDEX].mqtt_server, cnt_parameters_array[CNT_DEFAULT_INDEX].mqtt_port, cnt_parameters_array[CNT_DEFAULT_INDEX].mqtt_user, (cnt_parameters_array[CNT_DEFAULT_INDEX].isConnectionSecure ? "checked" : ""), gateway_name, mqtt_topic);
# endif # endif
# endif # endif
response += String(buffer); sendFooterChunk();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} }
# ifndef ESPWifiManualSetup # ifndef ESPWifiManualSetup
@@ -893,18 +901,13 @@ void handleCG() {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; beginChunkedResponse();
sendHeaderChunk((String(gateway_name) + " - Save and Restart").c_str());
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Save and Restart").c_str()); server.sendContent(restart_script);
String response = String(buffer); server.sendContent(script);
response += String(restart_script); server.sendContent(style);
response += String(script); sendBodyChunk(reset_body, jsonChar, gateway_name, "Save and Restart");
response += String(style); sendFooterChunk();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, reset_body, jsonChar, gateway_name, "Save and Restart");
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
if (pwUpdate) { if (pwUpdate) {
StaticJsonDocument<JSON_MSG_BUFFER> jsonBuffer; StaticJsonDocument<JSON_MSG_BUFFER> jsonBuffer;
@@ -922,23 +925,17 @@ void handleCG() {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
beginChunkedResponse();
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; sendHeaderChunk((String(gateway_name) + " - Configure gateway").c_str());
server.sendContent(script);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Configure gateway").c_str()); server.sendContent(style);
String response = String(buffer); sendBodyChunk(config_gateway_body, jsonChar, gateway_name
response += String(script);
response += String(style);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_gateway_body, jsonChar, gateway_name
# ifdef ZmqttDiscovery # ifdef ZmqttDiscovery
, ,
(SYSConfig.discovery ? "checked" : "") (SYSConfig.discovery ? "checked" : "")
# endif # endif
); );
response += String(buffer); sendFooterChunk();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} }
# endif # endif
@@ -963,19 +960,13 @@ void handleLO() {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
beginChunkedResponse();
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; sendHeaderChunk((String(gateway_name) + " - Configure Logging").c_str());
server.sendContent(script);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Configure Logging").c_str()); server.sendContent(style);
String response = String(buffer);
response += String(script);
response += String(style);
int logLevel = Log.getLevel(); int logLevel = Log.getLevel();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_logging_body, jsonChar, gateway_name, (logLevel == 0 ? "selected" : ""), (logLevel == 1 ? "selected" : ""), (logLevel == 2 ? "selected" : ""), (logLevel == 3 ? "selected" : ""), (logLevel == 4 ? "selected" : ""), (logLevel == 5 ? "selected" : ""), (logLevel == 6 ? "selected" : "")); sendBodyChunk(config_logging_body, jsonChar, gateway_name, (logLevel == 0 ? "selected" : ""), (logLevel == 1 ? "selected" : ""), (logLevel == 2 ? "selected" : ""), (logLevel == 3 ? "selected" : ""), (logLevel == 4 ? "selected" : ""), (logLevel == 5 ? "selected" : ""), (logLevel == 6 ? "selected" : ""));
response += String(buffer); sendFooterChunk();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} }
# ifdef ZgatewayBT # ifdef ZgatewayBT
@@ -1096,17 +1087,14 @@ void handleBL() {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
beginChunkedResponse();
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; sendHeaderChunk((String(gateway_name) + " - Configure BLE").c_str());
server.sendContent(ble_script);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Configure BLE").c_str()); server.sendContent(script);
String response = String(buffer); server.sendContent(style);
response += String(ble_script);
response += String(script);
response += String(style);
// Scan settings // Scan settings
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_ble_body_scan, sendBodyChunk(config_ble_body_scan,
jsonChar, gateway_name, jsonChar, gateway_name,
(BTConfig.enabled ? "checked" : ""), (BTConfig.enabled ? "checked" : ""),
(BTConfig.adaptiveScan ? "checked" : ""), (BTConfig.adaptiveScan ? "checked" : ""),
@@ -1116,33 +1104,29 @@ void handleBL() {
(BTConfig.forcePassiveScan ? "checked" : ""), (BTConfig.forcePassiveScan ? "checked" : ""),
(BTConfig.bleConnect ? "checked" : ""), (BTConfig.bleConnect ? "checked" : ""),
BTConfig.minRssi); BTConfig.minRssi);
response += String(buffer);
// Publish settings // Publish settings
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_ble_body_publish, sendBodyChunk(config_ble_body_publish,
(BTConfig.pubOnlySensors ? "checked" : ""), (BTConfig.pubOnlySensors ? "checked" : ""),
(BTConfig.pubRandomMACs ? "checked" : ""), (BTConfig.pubRandomMACs ? "checked" : ""),
(BTConfig.pubAdvData ? "checked" : ""), (BTConfig.pubAdvData ? "checked" : ""),
(BTConfig.pubBeaconUuidForTopic ? "checked" : ""), (BTConfig.pubBeaconUuidForTopic ? "checked" : ""),
(BTConfig.filterConnectable ? "checked" : ""), (BTConfig.filterConnectable ? "checked" : ""),
(BTConfig.ignoreWBlist ? "checked" : "")); (BTConfig.ignoreWBlist ? "checked" : ""));
response += String(buffer);
// Presence settings // Presence settings
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_ble_body_presence, sendBodyChunk(config_ble_body_presence,
(BTConfig.presenceEnable ? "checked" : ""), (BTConfig.presenceEnable ? "checked" : ""),
(BTConfig.presenceUseBeaconUuid ? "checked" : ""), (BTConfig.presenceUseBeaconUuid ? "checked" : ""),
BTConfig.presenceTopic.c_str(), BTConfig.presenceTopic.c_str(),
BTConfig.presenceAwayTimer, BTConfig.presenceAwayTimer,
BTConfig.movingTimer); BTConfig.movingTimer);
response += String(buffer);
// External decoder settings // External decoder settings
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_ble_body_decoder, sendBodyChunk(config_ble_body_decoder,
(BTConfig.extDecoderEnable ? "checked" : ""), (BTConfig.extDecoderEnable ? "checked" : ""),
BTConfig.extDecoderTopic.c_str(), BTConfig.extDecoderTopic.c_str(),
BTConfig.intervalConnect); BTConfig.intervalConnect);
response += String(buffer);
# if BLEDecryptor # if BLEDecryptor
// Encryption settings // Encryption settings
@@ -1158,18 +1142,13 @@ void handleBL() {
aeskeysstring.pop_back(); aeskeysstring.pop_back();
} }
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_ble_body_encrypt, sendBodyChunk(config_ble_body_encrypt,
ble_aes, aeskeysstring.c_str()); ble_aes, aeskeysstring.c_str());
response += String(buffer);
# endif # endif
// Footer // Save button + footer
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, "%s", config_ble_body_footer); server.sendContent(config_ble_body_footer);
response += String(buffer); sendFooterChunk();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} }
# endif # endif
@@ -1274,13 +1253,11 @@ void handleLA() {
} }
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
beginChunkedResponse();
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; sendHeaderChunk((String(gateway_name) + " - Configure LORA").c_str());
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Configure LORA").c_str()); server.sendContent(script);
String response = String(buffer); server.sendContent(style);
response += String(script); sendBodyChunk(config_lora_body,
response += String(style);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_lora_body,
jsonChar, jsonChar,
gateway_name, gateway_name,
LORAConfig.frequency == 868000000 ? "selected" : "", LORAConfig.frequency == 868000000 ? "selected" : "",
@@ -1326,11 +1303,7 @@ void handleLA() {
LORAConfig.crc ? "checked" : "", LORAConfig.crc ? "checked" : "",
LORAConfig.invertIQ ? "checked" : "", LORAConfig.invertIQ ? "checked" : "",
LORAConfig.onlyKnown ? "checked" : ""); LORAConfig.onlyKnown ? "checked" : "");
sendFooterChunk();
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} }
# elif defined(ZgatewayRTL_433) || defined(ZgatewayPilight) || defined(ZgatewayRF) || defined(ZgatewayRF2) || defined(ZactuatorSomfy) # elif defined(ZgatewayRTL_433) || defined(ZgatewayPilight) || defined(ZgatewayRF) || defined(ZgatewayRF2) || defined(ZactuatorSomfy)
# include <map> # include <map>
@@ -1440,18 +1413,12 @@ void handleRF() {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; beginChunkedResponse();
sendHeaderChunk((String(gateway_name) + " - Configure RF").c_str());
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Configure RF").c_str()); server.sendContent(script);
String response = String(buffer); server.sendContent(style);
response += String(script); sendBodyChunk(config_rf_body, jsonChar, gateway_name, iRFConfig.getFrequency(), activeReceiverHtml.c_str());
response += String(style); sendFooterChunk();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_rf_body, jsonChar, gateway_name, iRFConfig.getFrequency(), activeReceiverHtml.c_str());
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} }
# endif # endif
@@ -1471,19 +1438,13 @@ void handleRT() {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
THEENGS_LOG_WARNING(F("[WebUI] Erase and Restart" CR)); THEENGS_LOG_WARNING(F("[WebUI] Erase and Restart" CR));
beginChunkedResponse();
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; sendHeaderChunk((String(gateway_name) + " - Erase and Restart").c_str());
server.sendContent(restart_script);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Erase and Restart").c_str()); server.sendContent(script);
String response = String(buffer); server.sendContent(style);
response += String(restart_script); sendBodyChunk(reset_body, jsonChar, gateway_name, "Erase and Restart");
response += String(script); sendFooterChunk();
response += String(style);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, reset_body, jsonChar, gateway_name, "Erase and Restart");
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
eraseConfig(); eraseConfig();
} else { } else {
@@ -1516,13 +1477,10 @@ void handleCL() {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
beginChunkedResponse();
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; sendHeaderChunk((String(gateway_name) + " - Configure Cloud").c_str());
server.sendContent(script);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Configure Cloud").c_str()); server.sendContent(style);
String response = String(buffer);
response += String(script);
response += String(style);
char cloudEnabled[8] = {0}; char cloudEnabled[8] = {0};
if (isCloudEnabled()) { if (isCloudEnabled()) {
@@ -1536,14 +1494,11 @@ void handleCL() {
requestToken = esp_random(); requestToken = esp_random();
# ifdef ESP32_ETHERNET # ifdef ESP32_ETHERNET
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_cloud_body, jsonChar, gateway_name, " cloud checked", " Not", (String(CLOUDGATEWAY) + "token/start").c_str(), (char*)ETH.macAddress().c_str(), ("http://" + String(TheengsUtils::ip2CharArray(ETH.localIP())) + "/").c_str(), gateway_name, uptime(), requestToken); sendBodyChunk(config_cloud_body, jsonChar, gateway_name, " cloud checked", " Not", (String(CLOUDGATEWAY) + "token/start").c_str(), (char*)ETH.macAddress().c_str(), ("http://" + String(TheengsUtils::ip2CharArray(ETH.localIP())) + "/").c_str(), gateway_name, uptime(), requestToken);
# else # else
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_cloud_body, jsonChar, gateway_name, cloudEnabled, deviceToken, (String(CLOUDGATEWAY) + "token/start").c_str(), (char*)WiFi.macAddress().c_str(), ("http://" + String(TheengsUtils::ip2CharArray(WiFi.localIP())) + "/").c_str(), gateway_name, uptime(), requestToken); sendBodyChunk(config_cloud_body, jsonChar, gateway_name, cloudEnabled, deviceToken, (String(CLOUDGATEWAY) + "token/start").c_str(), (char*)WiFi.macAddress().c_str(), ("http://" + String(TheengsUtils::ip2CharArray(WiFi.localIP())) + "/").c_str(), gateway_name, uptime(), requestToken);
# endif # endif
response += String(buffer); sendFooterChunk();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} }
/** /**
@@ -1566,18 +1521,12 @@ void handleTK() {
setCloudEnabled(true); setCloudEnabled(true);
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
beginChunkedResponse();
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; sendHeaderChunk((String(gateway_name) + " - Received Device Token").c_str());
server.sendContent(script);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Received Device Token").c_str()); server.sendContent(style);
String response = String(buffer); sendBodyChunk(token_body, jsonChar, gateway_name);
response += String(script); sendFooterChunk();
response += String(style);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, token_body, jsonChar, gateway_name);
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} else { } else {
WEBUI_TRACE_LOG(F("handleTK: uptime: %u, uptime: %u, ok: %T" CR), server.arg("uptime").toInt(), uptime(), server.arg("uptime").toInt() + 600 > uptime()); WEBUI_TRACE_LOG(F("handleTK: uptime: %u, uptime: %u, ok: %T" CR), server.arg("uptime").toInt(), uptime(), server.arg("uptime").toInt() + 600 > uptime());
WEBUI_TRACE_LOG(F("handleTK: RT: %d, RT: %d, ok: %T " CR), server.arg("RT").toInt(), requestToken, server.arg("RT").toInt() == requestToken); WEBUI_TRACE_LOG(F("handleTK: RT: %d, RT: %d, ok: %T " CR), server.arg("RT").toInt(), requestToken, server.arg("RT").toInt() == requestToken);
@@ -1648,23 +1597,13 @@ void handleIN() {
THEENGS_LOG_WARNING(F("[WebUI] informationDisplay content length ( %d ) greater than WEB_TEMPLATE_BUFFER_MAX_SIZE. Display truncated" CR), informationDisplay.length()); THEENGS_LOG_WARNING(F("[WebUI] informationDisplay content length ( %d ) greater than WEB_TEMPLATE_BUFFER_MAX_SIZE. Display truncated" CR), informationDisplay.length());
} }
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; beginChunkedResponse();
sendHeaderChunk((String(gateway_name) + " - Information").c_str());
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Information").c_str()); sendBodyChunk(information_script, informationDisplay.c_str());
String response = String(buffer); server.sendContent(script);
server.sendContent(style);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, information_script, informationDisplay.c_str()); sendBodyChunk(information_body, jsonChar, gateway_name);
response += String(buffer); sendFooterChunk();
response += String(script);
response += String(style);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, information_body, jsonChar, gateway_name);
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} }
} }
@@ -1731,36 +1670,26 @@ void handleUP() {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; beginChunkedResponse();
sendHeaderChunk((String(gateway_name) + " - Firmware Upgrade").c_str());
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Firmware Upgrade").c_str()); server.sendContent(script);
String response = String(buffer); server.sendContent(style);
response += String(script);
response += String(style);
String systemUrl = RELEASE_LINK + latestVersion + "/" + ENV_NAME + "-firmware.bin"; String systemUrl = RELEASE_LINK + latestVersion + "/" + ENV_NAME + "-firmware.bin";
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, upgrade_body, jsonChar, gateway_name, systemUrl.c_str()); sendBodyChunk(upgrade_body, jsonChar, gateway_name, systemUrl.c_str());
response += String(buffer); sendFooterChunk();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} }
# endif # endif
void sendRestartPage() { void sendRestartPage() {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; beginChunkedResponse();
sendHeaderChunk((String(gateway_name) + " - Updating Firmware and Restart").c_str());
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Updating Firmware and Restart").c_str()); server.sendContent(restart_script);
String response = String(buffer); server.sendContent(script);
response += String(restart_script); server.sendContent(style);
response += String(script); sendBodyChunk(reset_body, jsonChar, gateway_name, "Updating Firmware and Restart");
response += String(style); sendFooterChunk();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, reset_body, jsonChar, gateway_name, "Updating Firmware and Restart");
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
delay(2000); // Wait for web page to be sent before delay(2000); // Wait for web page to be sent before
} }
@@ -1772,6 +1701,7 @@ void sendRestartPage() {
void handleCS() { void handleCS() {
WEBUI_TRACE_LOG(F("handleCS: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method()); WEBUI_TRACE_LOG(F("handleCS: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
WEBUI_SECURE WEBUI_SECURE
ensureLogBuffer();
if (server.args() && server.hasArg("c2")) { if (server.args() && server.hasArg("c2")) {
for (uint8_t i = 0; i < server.args(); i++) { for (uint8_t i = 0; i < server.args(); i++) {
WEBUI_TRACE_LOG(F("handleCS Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str()); WEBUI_TRACE_LOG(F("handleCS Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str());
@@ -1814,19 +1744,13 @@ void handleCS() {
} else { } else {
char jsonChar[100]; char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1); serializeJson(modules, jsonChar, measureJson(modules) + 1);
beginChunkedResponse();
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE]; sendHeaderChunk((String(gateway_name) + " - Console").c_str());
server.sendContent(console_script);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Console").c_str()); server.sendContent(script);
String response = String(buffer); server.sendContent(style);
response += String(console_script); sendBodyChunk(console_body, jsonChar, gateway_name);
response += String(script); sendFooterChunk();
response += String(style);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, console_body, jsonChar, gateway_name);
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
} }
} }
@@ -1923,6 +1847,7 @@ unsigned long nextWebUIMessage = uptime() + DISPLAY_WEBUI_INTERVAL;
void WebUILoop() { void WebUILoop() {
server.handleClient(); server.handleClient();
freeLogBufferIfIdle();
if (uptime() >= nextWebUIMessage && uxQueueMessagesWaiting(webUIQueue)) { if (uptime() >= nextWebUIMessage && uxQueueMessagesWaiting(webUIQueue)) {
webUIQueueMessage* message = nullptr; webUIQueueMessage* message = nullptr;
@@ -2764,11 +2689,17 @@ size_t SerialWeb::write(const uint8_t* buffer, size_t size) {
return Serial.write(buffer, size); return Serial.write(buffer, size);
} }
char line[ROW_LENGTH];
int lineIndex = 0;
void addLog(const uint8_t* buffer, size_t size) { void addLog(const uint8_t* buffer, size_t size) {
if (!log_buffer) {
return; // Skip logging when console buffer is not allocated
}
if (!line) {
line = (char*)malloc(ROW_LENGTH);
if (!line) return;
lineIndex = 0;
}
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
if (char(buffer[i]) == 10 | lineIndex > ROW_LENGTH - 2) { if (char(buffer[i]) == 10 | lineIndex >= ROW_LENGTH - 2) {
if (char(buffer[i]) != 10) { if (char(buffer[i]) != 10) {
line[lineIndex++] = char(buffer[i]); line[lineIndex++] = char(buffer[i]);
} }
+14 -18
View File
@@ -45,7 +45,7 @@ CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE=100
# CONFIG_BTDM_BLE_MESH_SCAN_DUPL_EN is not set # CONFIG_BTDM_BLE_MESH_SCAN_DUPL_EN is not set
CONFIG_BTDM_CTRL_FULL_SCAN_SUPPORTED=y CONFIG_BTDM_CTRL_FULL_SCAN_SUPPORTED=y
CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y
CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=50
CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20
CONFIG_BTDM_RESERVE_DRAM=0xdb5c CONFIG_BTDM_RESERVE_DRAM=0xdb5c
CONFIG_BTDM_CTRL_HLI=y CONFIG_BTDM_CTRL_HLI=y
@@ -85,14 +85,14 @@ CONFIG_BT_NIMBLE_SM_SC=y
# CONFIG_BT_NIMBLE_SM_SC_DEBUG_KEYS is not set # CONFIG_BT_NIMBLE_SM_SC_DEBUG_KEYS is not set
CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME="nimble" CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME="nimble"
CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN=31 CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN=31
CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=256 CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=185
CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE=0 CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE=0
CONFIG_BT_NIMBLE_ACL_BUF_COUNT=20 CONFIG_BT_NIMBLE_ACL_BUF_COUNT=12
CONFIG_BT_NIMBLE_ACL_BUF_SIZE=255 CONFIG_BT_NIMBLE_ACL_BUF_SIZE=255
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70 CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT=30 CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT=15
CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT=8 CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT=8
CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT=12 CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT=8
CONFIG_BT_NIMBLE_HS_FLOW_CTRL=y CONFIG_BT_NIMBLE_HS_FLOW_CTRL=y
CONFIG_BT_NIMBLE_HS_FLOW_CTRL_ITVL=1000 CONFIG_BT_NIMBLE_HS_FLOW_CTRL_ITVL=1000
CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH=2 CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH=2
@@ -187,11 +187,11 @@ CONFIG_ARDUINO_SELECTIVE_Ticker=y
CONFIG_ARDUINO_SELECTIVE_Update=y CONFIG_ARDUINO_SELECTIVE_Update=y
# CONFIG_ARDUINO_SELECTIVE_Zigbee is not set # CONFIG_ARDUINO_SELECTIVE_Zigbee is not set
CONFIG_ARDUINO_SELECTIVE_FS=y CONFIG_ARDUINO_SELECTIVE_FS=y
CONFIG_ARDUINO_SELECTIVE_SD=y # CONFIG_ARDUINO_SELECTIVE_SD is not set
CONFIG_ARDUINO_SELECTIVE_SD_MMC=y # CONFIG_ARDUINO_SELECTIVE_SD_MMC is not set
CONFIG_ARDUINO_SELECTIVE_SPIFFS=y CONFIG_ARDUINO_SELECTIVE_SPIFFS=y
CONFIG_ARDUINO_SELECTIVE_FFat=y # CONFIG_ARDUINO_SELECTIVE_FFat is not set
CONFIG_ARDUINO_SELECTIVE_LittleFS=y # CONFIG_ARDUINO_SELECTIVE_LittleFS is not set
CONFIG_ARDUINO_SELECTIVE_Network=y CONFIG_ARDUINO_SELECTIVE_Network=y
CONFIG_ARDUINO_SELECTIVE_Ethernet=y CONFIG_ARDUINO_SELECTIVE_Ethernet=y
CONFIG_ARDUINO_SELECTIVE_PPP=y CONFIG_ARDUINO_SELECTIVE_PPP=y
@@ -201,7 +201,7 @@ CONFIG_ARDUINO_SELECTIVE_DNSServer=y
CONFIG_ARDUINO_SELECTIVE_ESPmDNS=y CONFIG_ARDUINO_SELECTIVE_ESPmDNS=y
CONFIG_ARDUINO_SELECTIVE_HTTPClient=y CONFIG_ARDUINO_SELECTIVE_HTTPClient=y
# CONFIG_ARDUINO_SELECTIVE_Matter is not set # CONFIG_ARDUINO_SELECTIVE_Matter is not set
CONFIG_ARDUINO_SELECTIVE_NetBIOS=y # CONFIG_ARDUINO_SELECTIVE_NetBIOS is not set
CONFIG_ARDUINO_SELECTIVE_WebServer=y CONFIG_ARDUINO_SELECTIVE_WebServer=y
CONFIG_ARDUINO_SELECTIVE_WiFi=y CONFIG_ARDUINO_SELECTIVE_WiFi=y
CONFIG_ARDUINO_SELECTIVE_NetworkClientSecure=y CONFIG_ARDUINO_SELECTIVE_NetworkClientSecure=y
@@ -247,7 +247,7 @@ CONFIG_LWIP_TCP_MSS=1436
CONFIG_LWIP_TCP_RTO_TIME=3000 CONFIG_LWIP_TCP_RTO_TIME=3000
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096 CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096
CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0=y CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0=y
CONFIG_LWIP_MAX_SOCKETS=16 CONFIG_LWIP_MAX_SOCKETS=10
CONFIG_LWIP_IP_FORWARD=y CONFIG_LWIP_IP_FORWARD=y
CONFIG_LWIP_IPV4_NAPT=y CONFIG_LWIP_IPV4_NAPT=y
CONFIG_LWIP_DHCP_RESTORE_LAST_IP=n CONFIG_LWIP_DHCP_RESTORE_LAST_IP=n
@@ -255,13 +255,9 @@ CONFIG_LWIP_DHCP_OPTIONS_LEN=128
CONFIG_LWIP_SNTP_MAX_SERVERS=3 CONFIG_LWIP_SNTP_MAX_SERVERS=3
CONFIG_LWIP_SNTP_UPDATE_DELAY=10800000 CONFIG_LWIP_SNTP_UPDATE_DELAY=10800000
CONFIG_LWIP_DHCP_GET_NTP_SRV=y CONFIG_LWIP_DHCP_GET_NTP_SRV=y
CONFIG_LWIP_IPV6_AUTOCONFIG=y # CONFIG_LWIP_IPV6_AUTOCONFIG is not set
CONFIG_LWIP_IPV6_DHCP6=y # CONFIG_LWIP_IPV6_DHCP6 is not set
CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS=2 # CONFIG_LWIP_PPP_SUPPORT is not set
CONFIG_LWIP_PPP_SUPPORT=y
CONFIG_LWIP_PPP_NOTIFY_PHASE_SUPPORT=y
CONFIG_LWIP_PPP_PAP_SUPPORT=y
CONFIG_LWIP_PPP_ENABLE_IPV6=n
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT=y CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT=y