feat: Add central logging pragma (#843)
## Summary
* Definition and use of a central LOG function, that can later be
extended or completely be removed (for public use where debugging
information may not be required) to save flash by suppressing the
-DENABLE_SERIAL_LOG like in the slim branch
* **What changes are included?**
## Additional Context
* By using the central logger the usual:
```
#include <HardwareSerial.h>
...
Serial.printf("[%lu] [WCS] Obfuscating/deobfuscating %zu bytes\n", millis(), data.size());
```
would then become
```
#include <Logging.h>
...
LOG_DBG("WCS", "Obfuscating/deobfuscating %zu bytes", data.size());
```
You do have ``LOG_DBG`` for debug messages, ``LOG_ERR`` for error
messages and ``LOG_INF`` for informational messages. Depending on the
verbosity level defined (see below) soe of these message types will be
suppressed/not-compiled.
* The normal compilation (default) will create a firmware.elf file of
42.194.356 bytes, the same code via slim will create 42.024.048 bytes -
170.308 bytes less
* Firmware.bin : 6.469.984 bytes for default, 6.418.672 bytes for slim -
51.312 bytes less
### AI Usage
While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.
Did you use AI tools to help write this code? _NO_
---------
Co-authored-by: Xuan Son Nguyen <son@huggingface.co>
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include <Epub.h>
|
||||
#include <FsHelpers.h>
|
||||
#include <HalStorage.h>
|
||||
#include <Logging.h>
|
||||
#include <WiFi.h>
|
||||
#include <esp_task_wdt.h>
|
||||
|
||||
@@ -44,7 +45,7 @@ void clearEpubCacheIfNeeded(const String& filePath) {
|
||||
// Only clear cache for .epub files
|
||||
if (StringUtils::checkFileExtension(filePath, ".epub")) {
|
||||
Epub(filePath.c_str(), "/.crosspoint").clearCache();
|
||||
Serial.printf("[%lu] [WEB] Cleared epub cache for: %s\n", millis(), filePath.c_str());
|
||||
LOG_DBG("WEB", "Cleared epub cache for: %s", filePath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +90,7 @@ CrossPointWebServer::~CrossPointWebServer() { stop(); }
|
||||
|
||||
void CrossPointWebServer::begin() {
|
||||
if (running) {
|
||||
Serial.printf("[%lu] [WEB] Web server already running\n", millis());
|
||||
LOG_DBG("WEB", "Web server already running");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -99,18 +100,17 @@ void CrossPointWebServer::begin() {
|
||||
const bool isInApMode = (wifiMode & WIFI_MODE_AP) && (WiFi.softAPgetStationNum() >= 0); // AP is running
|
||||
|
||||
if (!isStaConnected && !isInApMode) {
|
||||
Serial.printf("[%lu] [WEB] Cannot start webserver - no valid network (mode=%d, status=%d)\n", millis(), wifiMode,
|
||||
WiFi.status());
|
||||
LOG_DBG("WEB", "Cannot start webserver - no valid network (mode=%d, status=%d)", wifiMode, WiFi.status());
|
||||
return;
|
||||
}
|
||||
|
||||
// Store AP mode flag for later use (e.g., in handleStatus)
|
||||
apMode = isInApMode;
|
||||
|
||||
Serial.printf("[%lu] [WEB] [MEM] Free heap before begin: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
Serial.printf("[%lu] [WEB] Network mode: %s\n", millis(), apMode ? "AP" : "STA");
|
||||
LOG_DBG("WEB", "[MEM] Free heap before begin: %d bytes", ESP.getFreeHeap());
|
||||
LOG_DBG("WEB", "Network mode: %s", apMode ? "AP" : "STA");
|
||||
|
||||
Serial.printf("[%lu] [WEB] Creating web server on port %d...\n", millis(), port);
|
||||
LOG_DBG("WEB", "Creating web server on port %d...", port);
|
||||
server.reset(new WebServer(port));
|
||||
|
||||
// Disable WiFi sleep to improve responsiveness and prevent 'unreachable' errors.
|
||||
@@ -120,15 +120,15 @@ void CrossPointWebServer::begin() {
|
||||
// Note: WebServer class doesn't have setNoDelay() in the standard ESP32 library.
|
||||
// We rely on disabling WiFi sleep for responsiveness.
|
||||
|
||||
Serial.printf("[%lu] [WEB] [MEM] Free heap after WebServer allocation: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
LOG_DBG("WEB", "[MEM] Free heap after WebServer allocation: %d bytes", ESP.getFreeHeap());
|
||||
|
||||
if (!server) {
|
||||
Serial.printf("[%lu] [WEB] Failed to create WebServer!\n", millis());
|
||||
LOG_ERR("WEB", "Failed to create WebServer!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup routes
|
||||
Serial.printf("[%lu] [WEB] Setting up routes...\n", millis());
|
||||
LOG_DBG("WEB", "Setting up routes...");
|
||||
server->on("/", HTTP_GET, [this] { handleRoot(); });
|
||||
server->on("/files", HTTP_GET, [this] { handleFileList(); });
|
||||
|
||||
@@ -157,43 +157,41 @@ void CrossPointWebServer::begin() {
|
||||
server->on("/api/settings", HTTP_POST, [this] { handlePostSettings(); });
|
||||
|
||||
server->onNotFound([this] { handleNotFound(); });
|
||||
Serial.printf("[%lu] [WEB] [MEM] Free heap after route setup: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
LOG_DBG("WEB", "[MEM] Free heap after route setup: %d bytes", ESP.getFreeHeap());
|
||||
|
||||
server->begin();
|
||||
|
||||
// Start WebSocket server for fast binary uploads
|
||||
Serial.printf("[%lu] [WEB] Starting WebSocket server on port %d...\n", millis(), wsPort);
|
||||
LOG_DBG("WEB", "Starting WebSocket server on port %d...", wsPort);
|
||||
wsServer.reset(new WebSocketsServer(wsPort));
|
||||
wsInstance = const_cast<CrossPointWebServer*>(this);
|
||||
wsServer->begin();
|
||||
wsServer->onEvent(wsEventCallback);
|
||||
Serial.printf("[%lu] [WEB] WebSocket server started\n", millis());
|
||||
LOG_DBG("WEB", "WebSocket server started");
|
||||
|
||||
udpActive = udp.begin(LOCAL_UDP_PORT);
|
||||
Serial.printf("[%lu] [WEB] Discovery UDP %s on port %d\n", millis(), udpActive ? "enabled" : "failed",
|
||||
LOCAL_UDP_PORT);
|
||||
LOG_DBG("WEB", "Discovery UDP %s on port %d", udpActive ? "enabled" : "failed", LOCAL_UDP_PORT);
|
||||
|
||||
running = true;
|
||||
|
||||
Serial.printf("[%lu] [WEB] Web server started on port %d\n", millis(), port);
|
||||
LOG_DBG("WEB", "Web server started on port %d", port);
|
||||
// Show the correct IP based on network mode
|
||||
const String ipAddr = apMode ? WiFi.softAPIP().toString() : WiFi.localIP().toString();
|
||||
Serial.printf("[%lu] [WEB] Access at http://%s/\n", millis(), ipAddr.c_str());
|
||||
Serial.printf("[%lu] [WEB] WebSocket at ws://%s:%d/\n", millis(), ipAddr.c_str(), wsPort);
|
||||
Serial.printf("[%lu] [WEB] [MEM] Free heap after server.begin(): %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
LOG_DBG("WEB", "Access at http://%s/", ipAddr.c_str());
|
||||
LOG_DBG("WEB", "WebSocket at ws://%s:%d/", ipAddr.c_str(), wsPort);
|
||||
LOG_DBG("WEB", "[MEM] Free heap after server.begin(): %d bytes", ESP.getFreeHeap());
|
||||
}
|
||||
|
||||
void CrossPointWebServer::stop() {
|
||||
if (!running || !server) {
|
||||
Serial.printf("[%lu] [WEB] stop() called but already stopped (running=%d, server=%p)\n", millis(), running,
|
||||
server.get());
|
||||
LOG_DBG("WEB", "stop() called but already stopped (running=%d, server=%p)", running, server.get());
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [WEB] STOP INITIATED - setting running=false first\n", millis());
|
||||
LOG_DBG("WEB", "STOP INITIATED - setting running=false first");
|
||||
running = false; // Set this FIRST to prevent handleClient from using server
|
||||
|
||||
Serial.printf("[%lu] [WEB] [MEM] Free heap before stop: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
LOG_DBG("WEB", "[MEM] Free heap before stop: %d bytes", ESP.getFreeHeap());
|
||||
|
||||
// Close any in-progress WebSocket upload
|
||||
if (wsUploadInProgress && wsUploadFile) {
|
||||
@@ -203,11 +201,11 @@ void CrossPointWebServer::stop() {
|
||||
|
||||
// Stop WebSocket server
|
||||
if (wsServer) {
|
||||
Serial.printf("[%lu] [WEB] Stopping WebSocket server...\n", millis());
|
||||
LOG_DBG("WEB", "Stopping WebSocket server...");
|
||||
wsServer->close();
|
||||
wsServer.reset();
|
||||
wsInstance = nullptr;
|
||||
Serial.printf("[%lu] [WEB] WebSocket server stopped\n", millis());
|
||||
LOG_DBG("WEB", "WebSocket server stopped");
|
||||
}
|
||||
|
||||
if (udpActive) {
|
||||
@@ -219,18 +217,18 @@ void CrossPointWebServer::stop() {
|
||||
delay(20);
|
||||
|
||||
server->stop();
|
||||
Serial.printf("[%lu] [WEB] [MEM] Free heap after server->stop(): %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
LOG_DBG("WEB", "[MEM] Free heap after server->stop(): %d bytes", ESP.getFreeHeap());
|
||||
|
||||
// Brief delay before deletion
|
||||
delay(10);
|
||||
|
||||
server.reset();
|
||||
Serial.printf("[%lu] [WEB] Web server stopped and deleted\n", millis());
|
||||
Serial.printf("[%lu] [WEB] [MEM] Free heap after delete server: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
LOG_DBG("WEB", "Web server stopped and deleted");
|
||||
LOG_DBG("WEB", "[MEM] Free heap after delete server: %d bytes", ESP.getFreeHeap());
|
||||
|
||||
// Note: Static upload variables (uploadFileName, uploadPath, uploadError) are declared
|
||||
// later in the file and will be cleared when they go out of scope or on next upload
|
||||
Serial.printf("[%lu] [WEB] [MEM] Free heap final: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
LOG_DBG("WEB", "[MEM] Free heap final: %d bytes", ESP.getFreeHeap());
|
||||
}
|
||||
|
||||
void CrossPointWebServer::handleClient() {
|
||||
@@ -243,13 +241,13 @@ void CrossPointWebServer::handleClient() {
|
||||
|
||||
// Double-check server pointer is valid
|
||||
if (!server) {
|
||||
Serial.printf("[%lu] [WEB] WARNING: handleClient called with null server!\n", millis());
|
||||
LOG_DBG("WEB", "WARNING: handleClient called with null server!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Print debug every 10 seconds to confirm handleClient is being called
|
||||
if (millis() - lastDebugPrint > 10000) {
|
||||
Serial.printf("[%lu] [WEB] handleClient active, server running on port %d\n", millis(), port);
|
||||
LOG_DBG("WEB", "handleClient active, server running on port %d", port);
|
||||
lastDebugPrint = millis();
|
||||
}
|
||||
|
||||
@@ -297,7 +295,7 @@ CrossPointWebServer::WsUploadStatus CrossPointWebServer::getWsUploadStatus() con
|
||||
|
||||
void CrossPointWebServer::handleRoot() const {
|
||||
server->send(200, "text/html", HomePageHtml);
|
||||
Serial.printf("[%lu] [WEB] Served root page\n", millis());
|
||||
LOG_DBG("WEB", "Served root page");
|
||||
}
|
||||
|
||||
void CrossPointWebServer::handleNotFound() const {
|
||||
@@ -326,17 +324,17 @@ void CrossPointWebServer::handleStatus() const {
|
||||
void CrossPointWebServer::scanFiles(const char* path, const std::function<void(FileInfo)>& callback) const {
|
||||
FsFile root = Storage.open(path);
|
||||
if (!root) {
|
||||
Serial.printf("[%lu] [WEB] Failed to open directory: %s\n", millis(), path);
|
||||
LOG_DBG("WEB", "Failed to open directory: %s", path);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!root.isDirectory()) {
|
||||
Serial.printf("[%lu] [WEB] Not a directory: %s\n", millis(), path);
|
||||
LOG_DBG("WEB", "Not a directory: %s", path);
|
||||
root.close();
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [WEB] Scanning files in: %s\n", millis(), path);
|
||||
LOG_DBG("WEB", "Scanning files in: %s", path);
|
||||
|
||||
FsFile file = root.openNextFile();
|
||||
char name[500];
|
||||
@@ -422,7 +420,7 @@ void CrossPointWebServer::handleFileListData() const {
|
||||
const size_t written = serializeJson(doc, output, outputSize);
|
||||
if (written >= outputSize) {
|
||||
// JSON output truncated; skip this entry to avoid sending malformed JSON
|
||||
Serial.printf("[%lu] [WEB] Skipping file entry with oversized JSON for name: %s\n", millis(), info.name.c_str());
|
||||
LOG_DBG("WEB", "Skipping file entry with oversized JSON for name: %s", info.name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -436,7 +434,7 @@ void CrossPointWebServer::handleFileListData() const {
|
||||
server->sendContent("]");
|
||||
// End of streamed response, empty chunk to signal client
|
||||
server->sendContent("");
|
||||
Serial.printf("[%lu] [WEB] Served file listing page for path: %s\n", millis(), currentPath.c_str());
|
||||
LOG_DBG("WEB", "Served file listing page for path: %s", currentPath.c_str());
|
||||
}
|
||||
|
||||
void CrossPointWebServer::handleDownload() const {
|
||||
@@ -517,8 +515,7 @@ static bool flushUploadBuffer(CrossPointWebServer::UploadState& state) {
|
||||
esp_task_wdt_reset(); // Reset watchdog after SD write
|
||||
|
||||
if (written != state.bufferPos) {
|
||||
Serial.printf("[%lu] [WEB] [UPLOAD] Buffer flush failed: expected %d, wrote %d\n", millis(), state.bufferPos,
|
||||
written);
|
||||
LOG_DBG("WEB", "[UPLOAD] Buffer flush failed: expected %d, wrote %d", state.bufferPos, written);
|
||||
state.bufferPos = 0;
|
||||
return false;
|
||||
}
|
||||
@@ -535,7 +532,7 @@ void CrossPointWebServer::handleUpload(UploadState& state) const {
|
||||
|
||||
// Safety check: ensure server is still valid
|
||||
if (!running || !server) {
|
||||
Serial.printf("[%lu] [WEB] [UPLOAD] ERROR: handleUpload called but server not running!\n", millis());
|
||||
LOG_DBG("WEB", "[UPLOAD] ERROR: handleUpload called but server not running!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -572,8 +569,8 @@ void CrossPointWebServer::handleUpload(UploadState& state) const {
|
||||
state.path = "/";
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [WEB] [UPLOAD] START: %s to path: %s\n", millis(), state.fileName.c_str(), state.path.c_str());
|
||||
Serial.printf("[%lu] [WEB] [UPLOAD] Free heap: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
LOG_DBG("WEB", "[UPLOAD] START: %s to path: %s", state.fileName.c_str(), state.path.c_str());
|
||||
LOG_DBG("WEB", "[UPLOAD] Free heap: %d bytes", ESP.getFreeHeap());
|
||||
|
||||
// Create file path
|
||||
String filePath = state.path;
|
||||
@@ -583,7 +580,7 @@ void CrossPointWebServer::handleUpload(UploadState& state) const {
|
||||
// Check if file already exists - SD operations can be slow
|
||||
esp_task_wdt_reset();
|
||||
if (Storage.exists(filePath.c_str())) {
|
||||
Serial.printf("[%lu] [WEB] [UPLOAD] Overwriting existing file: %s\n", millis(), filePath.c_str());
|
||||
LOG_DBG("WEB", "[UPLOAD] Overwriting existing file: %s", filePath.c_str());
|
||||
esp_task_wdt_reset();
|
||||
Storage.remove(filePath.c_str());
|
||||
}
|
||||
@@ -592,12 +589,12 @@ void CrossPointWebServer::handleUpload(UploadState& state) const {
|
||||
esp_task_wdt_reset();
|
||||
if (!Storage.openFileForWrite("WEB", filePath, state.file)) {
|
||||
state.error = "Failed to create file on SD card";
|
||||
Serial.printf("[%lu] [WEB] [UPLOAD] FAILED to create file: %s\n", millis(), filePath.c_str());
|
||||
LOG_DBG("WEB", "[UPLOAD] FAILED to create file: %s", filePath.c_str());
|
||||
return;
|
||||
}
|
||||
esp_task_wdt_reset();
|
||||
|
||||
Serial.printf("[%lu] [WEB] [UPLOAD] File created successfully: %s\n", millis(), filePath.c_str());
|
||||
LOG_DBG("WEB", "[UPLOAD] File created successfully: %s", filePath.c_str());
|
||||
} else if (upload.status == UPLOAD_FILE_WRITE) {
|
||||
if (state.file && state.error.isEmpty()) {
|
||||
// Buffer incoming data and flush when buffer is full
|
||||
@@ -630,8 +627,8 @@ void CrossPointWebServer::handleUpload(UploadState& state) const {
|
||||
if (state.size - lastLoggedSize >= 102400) {
|
||||
const unsigned long elapsed = millis() - uploadStartTime;
|
||||
const float kbps = (elapsed > 0) ? (state.size / 1024.0) / (elapsed / 1000.0) : 0;
|
||||
Serial.printf("[%lu] [WEB] [UPLOAD] %d bytes (%.1f KB), %.1f KB/s, %d writes\n", millis(), state.size,
|
||||
state.size / 1024.0, kbps, writeCount);
|
||||
LOG_DBG("WEB", "[UPLOAD] %d bytes (%.1f KB), %.1f KB/s, %d writes", state.size, state.size / 1024.0, kbps,
|
||||
writeCount);
|
||||
lastLoggedSize = state.size;
|
||||
}
|
||||
}
|
||||
@@ -648,10 +645,10 @@ void CrossPointWebServer::handleUpload(UploadState& state) const {
|
||||
const unsigned long elapsed = millis() - uploadStartTime;
|
||||
const float avgKbps = (elapsed > 0) ? (state.size / 1024.0) / (elapsed / 1000.0) : 0;
|
||||
const float writePercent = (elapsed > 0) ? (totalWriteTime * 100.0 / elapsed) : 0;
|
||||
Serial.printf("[%lu] [WEB] [UPLOAD] Complete: %s (%d bytes in %lu ms, avg %.1f KB/s)\n", millis(),
|
||||
state.fileName.c_str(), state.size, elapsed, avgKbps);
|
||||
Serial.printf("[%lu] [WEB] [UPLOAD] Diagnostics: %d writes, total write time: %lu ms (%.1f%%)\n", millis(),
|
||||
writeCount, totalWriteTime, writePercent);
|
||||
LOG_DBG("WEB", "[UPLOAD] Complete: %s (%d bytes in %lu ms, avg %.1f KB/s)", state.fileName.c_str(), state.size,
|
||||
elapsed, avgKbps);
|
||||
LOG_DBG("WEB", "[UPLOAD] Diagnostics: %d writes, total write time: %lu ms (%.1f%%)", writeCount, totalWriteTime,
|
||||
writePercent);
|
||||
|
||||
// Clear epub cache to prevent stale metadata issues when overwriting files
|
||||
String filePath = state.path;
|
||||
@@ -671,7 +668,7 @@ void CrossPointWebServer::handleUpload(UploadState& state) const {
|
||||
Storage.remove(filePath.c_str());
|
||||
}
|
||||
state.error = "Upload aborted";
|
||||
Serial.printf("[%lu] [WEB] Upload aborted\n", millis());
|
||||
LOG_DBG("WEB", "Upload aborted");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -716,7 +713,7 @@ void CrossPointWebServer::handleCreateFolder() const {
|
||||
if (!folderPath.endsWith("/")) folderPath += "/";
|
||||
folderPath += folderName;
|
||||
|
||||
Serial.printf("[%lu] [WEB] Creating folder: %s\n", millis(), folderPath.c_str());
|
||||
LOG_DBG("WEB", "Creating folder: %s", folderPath.c_str());
|
||||
|
||||
// Check if already exists
|
||||
if (Storage.exists(folderPath.c_str())) {
|
||||
@@ -726,10 +723,10 @@ void CrossPointWebServer::handleCreateFolder() const {
|
||||
|
||||
// Create the folder
|
||||
if (Storage.mkdir(folderPath.c_str())) {
|
||||
Serial.printf("[%lu] [WEB] Folder created successfully: %s\n", millis(), folderPath.c_str());
|
||||
LOG_DBG("WEB", "Folder created successfully: %s", folderPath.c_str());
|
||||
server->send(200, "text/plain", "Folder created: " + folderName);
|
||||
} else {
|
||||
Serial.printf("[%lu] [WEB] Failed to create folder: %s\n", millis(), folderPath.c_str());
|
||||
LOG_DBG("WEB", "Failed to create folder: %s", folderPath.c_str());
|
||||
server->send(500, "text/plain", "Failed to create folder");
|
||||
}
|
||||
}
|
||||
@@ -808,10 +805,10 @@ void CrossPointWebServer::handleRename() const {
|
||||
file.close();
|
||||
|
||||
if (success) {
|
||||
Serial.printf("[%lu] [WEB] Renamed file: %s -> %s\n", millis(), itemPath.c_str(), newPath.c_str());
|
||||
LOG_DBG("WEB", "Renamed file: %s -> %s", itemPath.c_str(), newPath.c_str());
|
||||
server->send(200, "text/plain", "Renamed successfully");
|
||||
} else {
|
||||
Serial.printf("[%lu] [WEB] Failed to rename file: %s -> %s\n", millis(), itemPath.c_str(), newPath.c_str());
|
||||
LOG_ERR("WEB", "Failed to rename file: %s -> %s", itemPath.c_str(), newPath.c_str());
|
||||
server->send(500, "text/plain", "Failed to rename file");
|
||||
}
|
||||
}
|
||||
@@ -901,10 +898,10 @@ void CrossPointWebServer::handleMove() const {
|
||||
file.close();
|
||||
|
||||
if (success) {
|
||||
Serial.printf("[%lu] [WEB] Moved file: %s -> %s\n", millis(), itemPath.c_str(), newPath.c_str());
|
||||
LOG_DBG("WEB", "Moved file: %s -> %s", itemPath.c_str(), newPath.c_str());
|
||||
server->send(200, "text/plain", "Moved successfully");
|
||||
} else {
|
||||
Serial.printf("[%lu] [WEB] Failed to move file: %s -> %s\n", millis(), itemPath.c_str(), newPath.c_str());
|
||||
LOG_ERR("WEB", "Failed to move file: %s -> %s", itemPath.c_str(), newPath.c_str());
|
||||
server->send(500, "text/plain", "Failed to move file");
|
||||
}
|
||||
}
|
||||
@@ -935,7 +932,7 @@ void CrossPointWebServer::handleDelete() const {
|
||||
|
||||
// Check if item starts with a dot (hidden/system file)
|
||||
if (itemName.startsWith(".")) {
|
||||
Serial.printf("[%lu] [WEB] Delete rejected - hidden/system item: %s\n", millis(), itemPath.c_str());
|
||||
LOG_DBG("WEB", "Delete rejected - hidden/system item: %s", itemPath.c_str());
|
||||
server->send(403, "text/plain", "Cannot delete system files");
|
||||
return;
|
||||
}
|
||||
@@ -943,7 +940,7 @@ void CrossPointWebServer::handleDelete() const {
|
||||
// Check against explicitly protected items
|
||||
for (size_t i = 0; i < HIDDEN_ITEMS_COUNT; i++) {
|
||||
if (itemName.equals(HIDDEN_ITEMS[i])) {
|
||||
Serial.printf("[%lu] [WEB] Delete rejected - protected item: %s\n", millis(), itemPath.c_str());
|
||||
LOG_DBG("WEB", "Delete rejected - protected item: %s", itemPath.c_str());
|
||||
server->send(403, "text/plain", "Cannot delete protected items");
|
||||
return;
|
||||
}
|
||||
@@ -951,12 +948,12 @@ void CrossPointWebServer::handleDelete() const {
|
||||
|
||||
// Check if item exists
|
||||
if (!Storage.exists(itemPath.c_str())) {
|
||||
Serial.printf("[%lu] [WEB] Delete failed - item not found: %s\n", millis(), itemPath.c_str());
|
||||
LOG_DBG("WEB", "Delete failed - item not found: %s", itemPath.c_str());
|
||||
server->send(404, "text/plain", "Item not found");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [WEB] Attempting to delete %s: %s\n", millis(), itemType.c_str(), itemPath.c_str());
|
||||
LOG_DBG("WEB", "Attempting to delete %s: %s", itemType.c_str(), itemPath.c_str());
|
||||
|
||||
bool success = false;
|
||||
|
||||
@@ -970,7 +967,7 @@ void CrossPointWebServer::handleDelete() const {
|
||||
// Folder is not empty
|
||||
entry.close();
|
||||
dir.close();
|
||||
Serial.printf("[%lu] [WEB] Delete failed - folder not empty: %s\n", millis(), itemPath.c_str());
|
||||
LOG_DBG("WEB", "Delete failed - folder not empty: %s", itemPath.c_str());
|
||||
server->send(400, "text/plain", "Folder is not empty. Delete contents first.");
|
||||
return;
|
||||
}
|
||||
@@ -983,17 +980,17 @@ void CrossPointWebServer::handleDelete() const {
|
||||
}
|
||||
|
||||
if (success) {
|
||||
Serial.printf("[%lu] [WEB] Successfully deleted: %s\n", millis(), itemPath.c_str());
|
||||
LOG_DBG("WEB", "Successfully deleted: %s", itemPath.c_str());
|
||||
server->send(200, "text/plain", "Deleted successfully");
|
||||
} else {
|
||||
Serial.printf("[%lu] [WEB] Failed to delete: %s\n", millis(), itemPath.c_str());
|
||||
LOG_ERR("WEB", "Failed to delete: %s", itemPath.c_str());
|
||||
server->send(500, "text/plain", "Failed to delete item");
|
||||
}
|
||||
}
|
||||
|
||||
void CrossPointWebServer::handleSettingsPage() const {
|
||||
server->send(200, "text/html", SettingsPageHtml);
|
||||
Serial.printf("[%lu] [WEB] Served settings page\n", millis());
|
||||
LOG_DBG("WEB", "Served settings page");
|
||||
}
|
||||
|
||||
void CrossPointWebServer::handleGetSettings() const {
|
||||
@@ -1062,7 +1059,7 @@ void CrossPointWebServer::handleGetSettings() const {
|
||||
|
||||
const size_t written = serializeJson(doc, output, outputSize);
|
||||
if (written >= outputSize) {
|
||||
Serial.printf("[%lu] [WEB] Skipping oversized setting JSON for: %s\n", millis(), s.key);
|
||||
LOG_DBG("WEB", "Skipping oversized setting JSON for: %s", s.key);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1076,7 +1073,7 @@ void CrossPointWebServer::handleGetSettings() const {
|
||||
|
||||
server->sendContent("]");
|
||||
server->sendContent("");
|
||||
Serial.printf("[%lu] [WEB] Served settings API\n", millis());
|
||||
LOG_DBG("WEB", "Served settings API");
|
||||
}
|
||||
|
||||
void CrossPointWebServer::handlePostSettings() {
|
||||
@@ -1149,7 +1146,7 @@ void CrossPointWebServer::handlePostSettings() {
|
||||
|
||||
SETTINGS.saveToFile();
|
||||
|
||||
Serial.printf("[%lu] [WEB] Applied %d setting(s)\n", millis(), applied);
|
||||
LOG_DBG("WEB", "Applied %d setting(s)", applied);
|
||||
server->send(200, "text/plain", String("Applied ") + String(applied) + " setting(s)");
|
||||
}
|
||||
|
||||
@@ -1169,7 +1166,7 @@ void CrossPointWebServer::wsEventCallback(uint8_t num, WStype_t type, uint8_t* p
|
||||
void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) {
|
||||
switch (type) {
|
||||
case WStype_DISCONNECTED:
|
||||
Serial.printf("[%lu] [WS] Client %u disconnected\n", millis(), num);
|
||||
LOG_DBG("WS", "Client %u disconnected", num);
|
||||
// Clean up any in-progress upload
|
||||
if (wsUploadInProgress && wsUploadFile) {
|
||||
wsUploadFile.close();
|
||||
@@ -1178,20 +1175,20 @@ void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t*
|
||||
if (!filePath.endsWith("/")) filePath += "/";
|
||||
filePath += wsUploadFileName;
|
||||
Storage.remove(filePath.c_str());
|
||||
Serial.printf("[%lu] [WS] Deleted incomplete upload: %s\n", millis(), filePath.c_str());
|
||||
LOG_DBG("WS", "Deleted incomplete upload: %s", filePath.c_str());
|
||||
}
|
||||
wsUploadInProgress = false;
|
||||
break;
|
||||
|
||||
case WStype_CONNECTED: {
|
||||
Serial.printf("[%lu] [WS] Client %u connected\n", millis(), num);
|
||||
LOG_DBG("WS", "Client %u connected", num);
|
||||
break;
|
||||
}
|
||||
|
||||
case WStype_TEXT: {
|
||||
// Parse control messages
|
||||
String msg = String((char*)payload);
|
||||
Serial.printf("[%lu] [WS] Text from client %u: %s\n", millis(), num, msg.c_str());
|
||||
LOG_DBG("WS", "Text from client %u: %s", num, msg.c_str());
|
||||
|
||||
if (msg.startsWith("START:")) {
|
||||
// Parse: START:<filename>:<size>:<path>
|
||||
@@ -1216,8 +1213,8 @@ void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t*
|
||||
if (!filePath.endsWith("/")) filePath += "/";
|
||||
filePath += wsUploadFileName;
|
||||
|
||||
Serial.printf("[%lu] [WS] Starting upload: %s (%d bytes) to %s\n", millis(), wsUploadFileName.c_str(),
|
||||
wsUploadSize, filePath.c_str());
|
||||
LOG_DBG("WS", "Starting upload: %s (%d bytes) to %s", wsUploadFileName.c_str(), wsUploadSize,
|
||||
filePath.c_str());
|
||||
|
||||
// Check if file exists and remove it
|
||||
esp_task_wdt_reset();
|
||||
@@ -1283,8 +1280,8 @@ void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t*
|
||||
unsigned long elapsed = millis() - wsUploadStartTime;
|
||||
float kbps = (elapsed > 0) ? (wsUploadSize / 1024.0) / (elapsed / 1000.0) : 0;
|
||||
|
||||
Serial.printf("[%lu] [WS] Upload complete: %s (%d bytes in %lu ms, %.1f KB/s)\n", millis(),
|
||||
wsUploadFileName.c_str(), wsUploadSize, elapsed, kbps);
|
||||
LOG_DBG("WS", "Upload complete: %s (%d bytes in %lu ms, %.1f KB/s)", wsUploadFileName.c_str(), wsUploadSize,
|
||||
elapsed, kbps);
|
||||
|
||||
// Clear epub cache to prevent stale metadata issues when overwriting files
|
||||
String filePath = wsUploadPath;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "HttpDownloader.h"
|
||||
|
||||
#include <HTTPClient.h>
|
||||
#include <HardwareSerial.h>
|
||||
#include <Logging.h>
|
||||
#include <StreamString.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
@@ -25,7 +25,7 @@ bool HttpDownloader::fetchUrl(const std::string& url, Stream& outContent) {
|
||||
}
|
||||
HTTPClient http;
|
||||
|
||||
Serial.printf("[%lu] [HTTP] Fetching: %s\n", millis(), url.c_str());
|
||||
LOG_DBG("HTTP", "Fetching: %s", url.c_str());
|
||||
|
||||
http.begin(*client, url.c_str());
|
||||
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||
@@ -40,7 +40,7 @@ bool HttpDownloader::fetchUrl(const std::string& url, Stream& outContent) {
|
||||
|
||||
const int httpCode = http.GET();
|
||||
if (httpCode != HTTP_CODE_OK) {
|
||||
Serial.printf("[%lu] [HTTP] Fetch failed: %d\n", millis(), httpCode);
|
||||
LOG_ERR("HTTP", "Fetch failed: %d", httpCode);
|
||||
http.end();
|
||||
return false;
|
||||
}
|
||||
@@ -49,7 +49,7 @@ bool HttpDownloader::fetchUrl(const std::string& url, Stream& outContent) {
|
||||
|
||||
http.end();
|
||||
|
||||
Serial.printf("[%lu] [HTTP] Fetch success\n", millis());
|
||||
LOG_DBG("HTTP", "Fetch success");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -75,8 +75,8 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
|
||||
}
|
||||
HTTPClient http;
|
||||
|
||||
Serial.printf("[%lu] [HTTP] Downloading: %s\n", millis(), url.c_str());
|
||||
Serial.printf("[%lu] [HTTP] Destination: %s\n", millis(), destPath.c_str());
|
||||
LOG_DBG("HTTP", "Downloading: %s", url.c_str());
|
||||
LOG_DBG("HTTP", "Destination: %s", destPath.c_str());
|
||||
|
||||
http.begin(*client, url.c_str());
|
||||
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||
@@ -91,13 +91,13 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
|
||||
|
||||
const int httpCode = http.GET();
|
||||
if (httpCode != HTTP_CODE_OK) {
|
||||
Serial.printf("[%lu] [HTTP] Download failed: %d\n", millis(), httpCode);
|
||||
LOG_ERR("HTTP", "Download failed: %d", httpCode);
|
||||
http.end();
|
||||
return HTTP_ERROR;
|
||||
}
|
||||
|
||||
const size_t contentLength = http.getSize();
|
||||
Serial.printf("[%lu] [HTTP] Content-Length: %zu\n", millis(), contentLength);
|
||||
LOG_DBG("HTTP", "Content-Length: %zu", contentLength);
|
||||
|
||||
// Remove existing file if present
|
||||
if (Storage.exists(destPath.c_str())) {
|
||||
@@ -107,7 +107,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
|
||||
// Open file for writing
|
||||
FsFile file;
|
||||
if (!Storage.openFileForWrite("HTTP", destPath.c_str(), file)) {
|
||||
Serial.printf("[%lu] [HTTP] Failed to open file for writing\n", millis());
|
||||
LOG_ERR("HTTP", "Failed to open file for writing");
|
||||
http.end();
|
||||
return FILE_ERROR;
|
||||
}
|
||||
@@ -115,7 +115,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
|
||||
// Get the stream for chunked reading
|
||||
WiFiClient* stream = http.getStreamPtr();
|
||||
if (!stream) {
|
||||
Serial.printf("[%lu] [HTTP] Failed to get stream\n", millis());
|
||||
LOG_ERR("HTTP", "Failed to get stream");
|
||||
file.close();
|
||||
Storage.remove(destPath.c_str());
|
||||
http.end();
|
||||
@@ -143,7 +143,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
|
||||
|
||||
const size_t written = file.write(buffer, bytesRead);
|
||||
if (written != bytesRead) {
|
||||
Serial.printf("[%lu] [HTTP] Write failed: wrote %zu of %zu bytes\n", millis(), written, bytesRead);
|
||||
LOG_ERR("HTTP", "Write failed: wrote %zu of %zu bytes", written, bytesRead);
|
||||
file.close();
|
||||
Storage.remove(destPath.c_str());
|
||||
http.end();
|
||||
@@ -160,11 +160,11 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
|
||||
file.close();
|
||||
http.end();
|
||||
|
||||
Serial.printf("[%lu] [HTTP] Downloaded %zu bytes\n", millis(), downloaded);
|
||||
LOG_DBG("HTTP", "Downloaded %zu bytes", downloaded);
|
||||
|
||||
// Verify download size if known
|
||||
if (contentLength > 0 && downloaded != contentLength) {
|
||||
Serial.printf("[%lu] [HTTP] Size mismatch: got %zu, expected %zu\n", millis(), downloaded, contentLength);
|
||||
LOG_ERR("HTTP", "Size mismatch: got %zu, expected %zu", downloaded, contentLength);
|
||||
Storage.remove(destPath.c_str());
|
||||
return HTTP_ERROR;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "OtaUpdater.h"
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <Logging.h>
|
||||
|
||||
#include "esp_http_client.h"
|
||||
#include "esp_https_ota.h"
|
||||
@@ -39,7 +40,7 @@ esp_err_t event_handler(esp_http_client_event_t* event) {
|
||||
local_buf = static_cast<char*>(calloc(content_len + 1, sizeof(char)));
|
||||
output_len = 0;
|
||||
if (local_buf == NULL) {
|
||||
Serial.printf("[%lu] [OTA] HTTP Client Out of Memory Failed, Allocation %d\n", millis(), content_len);
|
||||
LOG_ERR("OTA", "HTTP Client Out of Memory Failed, Allocation %d", content_len);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
@@ -52,7 +53,7 @@ esp_err_t event_handler(esp_http_client_event_t* event) {
|
||||
/* Code might be hits here, It happened once (for version checking) but I need more logs to handle that */
|
||||
int chunked_len;
|
||||
esp_http_client_get_chunk_length(event->client, &chunked_len);
|
||||
Serial.printf("[%lu] [OTA] esp_http_client_is_chunked_response failed, chunked_len: %d\n", millis(), chunked_len);
|
||||
LOG_DBG("OTA", "esp_http_client_is_chunked_response failed, chunked_len: %d", chunked_len);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
@@ -88,20 +89,20 @@ OtaUpdater::OtaUpdaterError OtaUpdater::checkForUpdate() {
|
||||
|
||||
esp_http_client_handle_t client_handle = esp_http_client_init(&client_config);
|
||||
if (!client_handle) {
|
||||
Serial.printf("[%lu] [OTA] HTTP Client Handle Failed\n", millis());
|
||||
LOG_ERR("OTA", "HTTP Client Handle Failed");
|
||||
return INTERNAL_UPDATE_ERROR;
|
||||
}
|
||||
|
||||
esp_err = esp_http_client_set_header(client_handle, "User-Agent", "CrossPoint-ESP32-" CROSSPOINT_VERSION);
|
||||
if (esp_err != ESP_OK) {
|
||||
Serial.printf("[%lu] [OTA] esp_http_client_set_header Failed : %s\n", millis(), esp_err_to_name(esp_err));
|
||||
LOG_ERR("OTA", "esp_http_client_set_header Failed : %s", esp_err_to_name(esp_err));
|
||||
esp_http_client_cleanup(client_handle);
|
||||
return INTERNAL_UPDATE_ERROR;
|
||||
}
|
||||
|
||||
esp_err = esp_http_client_perform(client_handle);
|
||||
if (esp_err != ESP_OK) {
|
||||
Serial.printf("[%lu] [OTA] esp_http_client_perform Failed : %s\n", millis(), esp_err_to_name(esp_err));
|
||||
LOG_ERR("OTA", "esp_http_client_perform Failed : %s", esp_err_to_name(esp_err));
|
||||
esp_http_client_cleanup(client_handle);
|
||||
return HTTP_ERROR;
|
||||
}
|
||||
@@ -109,7 +110,7 @@ OtaUpdater::OtaUpdaterError OtaUpdater::checkForUpdate() {
|
||||
/* esp_http_client_close will be called inside cleanup as well*/
|
||||
esp_err = esp_http_client_cleanup(client_handle);
|
||||
if (esp_err != ESP_OK) {
|
||||
Serial.printf("[%lu] [OTA] esp_http_client_cleanupp Failed : %s\n", millis(), esp_err_to_name(esp_err));
|
||||
LOG_ERR("OTA", "esp_http_client_cleanup Failed : %s", esp_err_to_name(esp_err));
|
||||
return INTERNAL_UPDATE_ERROR;
|
||||
}
|
||||
|
||||
@@ -119,17 +120,17 @@ OtaUpdater::OtaUpdaterError OtaUpdater::checkForUpdate() {
|
||||
filter["assets"][0]["size"] = true;
|
||||
const DeserializationError error = deserializeJson(doc, local_buf, DeserializationOption::Filter(filter));
|
||||
if (error) {
|
||||
Serial.printf("[%lu] [OTA] JSON parse failed: %s\n", millis(), error.c_str());
|
||||
LOG_ERR("OTA", "JSON parse failed: %s", error.c_str());
|
||||
return JSON_PARSE_ERROR;
|
||||
}
|
||||
|
||||
if (!doc["tag_name"].is<std::string>()) {
|
||||
Serial.printf("[%lu] [OTA] No tag_name found\n", millis());
|
||||
LOG_ERR("OTA", "No tag_name found");
|
||||
return JSON_PARSE_ERROR;
|
||||
}
|
||||
|
||||
if (!doc["assets"].is<JsonArray>()) {
|
||||
Serial.printf("[%lu] [OTA] No assets found\n", millis());
|
||||
LOG_ERR("OTA", "No assets found");
|
||||
return JSON_PARSE_ERROR;
|
||||
}
|
||||
|
||||
@@ -146,11 +147,11 @@ OtaUpdater::OtaUpdaterError OtaUpdater::checkForUpdate() {
|
||||
}
|
||||
|
||||
if (!updateAvailable) {
|
||||
Serial.printf("[%lu] [OTA] No firmware.bin asset found\n", millis());
|
||||
LOG_ERR("OTA", "No firmware.bin asset found");
|
||||
return NO_UPDATE;
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [OTA] Found update: %s\n", millis(), latestVersion.c_str());
|
||||
LOG_DBG("OTA", "Found update: %s", latestVersion.c_str());
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -233,7 +234,7 @@ OtaUpdater::OtaUpdaterError OtaUpdater::installUpdate() {
|
||||
|
||||
esp_err = esp_https_ota_begin(&ota_config, &ota_handle);
|
||||
if (esp_err != ESP_OK) {
|
||||
Serial.printf("[%lu] [OTA] HTTP OTA Begin Failed: %s\n", millis(), esp_err_to_name(esp_err));
|
||||
LOG_DBG("OTA", "HTTP OTA Begin Failed: %s", esp_err_to_name(esp_err));
|
||||
return INTERNAL_UPDATE_ERROR;
|
||||
}
|
||||
|
||||
@@ -249,24 +250,23 @@ OtaUpdater::OtaUpdaterError OtaUpdater::installUpdate() {
|
||||
esp_wifi_set_ps(WIFI_PS_MIN_MODEM);
|
||||
|
||||
if (esp_err != ESP_OK) {
|
||||
Serial.printf("[%lu] [OTA] esp_https_ota_perform Failed: %s\n", millis(), esp_err_to_name(esp_err));
|
||||
LOG_ERR("OTA", "esp_https_ota_perform Failed: %s", esp_err_to_name(esp_err));
|
||||
esp_https_ota_finish(ota_handle);
|
||||
return HTTP_ERROR;
|
||||
}
|
||||
|
||||
if (!esp_https_ota_is_complete_data_received(ota_handle)) {
|
||||
Serial.printf("[%lu] [OTA] esp_https_ota_is_complete_data_received Failed: %s\n", millis(),
|
||||
esp_err_to_name(esp_err));
|
||||
LOG_ERR("OTA", "esp_https_ota_is_complete_data_received Failed: %s", esp_err_to_name(esp_err));
|
||||
esp_https_ota_finish(ota_handle);
|
||||
return INTERNAL_UPDATE_ERROR;
|
||||
}
|
||||
|
||||
esp_err = esp_https_ota_finish(ota_handle);
|
||||
if (esp_err != ESP_OK) {
|
||||
Serial.printf("[%lu] [OTA] esp_https_ota_finish Failed: %s\n", millis(), esp_err_to_name(esp_err));
|
||||
LOG_ERR("OTA", "esp_https_ota_finish Failed: %s", esp_err_to_name(esp_err));
|
||||
return INTERNAL_UPDATE_ERROR;
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [OTA] Update completed\n", millis());
|
||||
LOG_INF("OTA", "Update completed");
|
||||
return OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user