From 980de08584774fe7bd5ff06eaf1b119cf2d96ca6 Mon Sep 17 00:00:00 2001 From: bonamin Date: Wed, 4 Feb 2026 17:00:27 +0200 Subject: [PATCH] Fix Infinite Loop Bug, Melody Download crashes and dwnld skip if melody is builin. --- vesper/documentation/common_commands.txt | 4 ++ vesper/src/FileManager/FileManager.cpp | 59 ++++++++++++++++++------ vesper/src/FileManager/FileManager.hpp | 3 +- vesper/vesper.ino | 3 +- 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/vesper/documentation/common_commands.txt b/vesper/documentation/common_commands.txt index a65226a..9959c3a 100644 --- a/vesper/documentation/common_commands.txt +++ b/vesper/documentation/common_commands.txt @@ -1,5 +1,9 @@ COMMANDS: + +PV26A28BC01R01 + + { "cmd":"system", "contents": diff --git a/vesper/src/FileManager/FileManager.cpp b/vesper/src/FileManager/FileManager.cpp index fa21c88..f354f79 100644 --- a/vesper/src/FileManager/FileManager.cpp +++ b/vesper/src/FileManager/FileManager.cpp @@ -1,4 +1,5 @@ #include "FileManager.hpp" +#include "../BuiltInMelodies/BuiltInMelodies.hpp" FileManager::FileManager(ConfigManager* config) : configManager(config) { // Constructor - store reference to ConfigManager @@ -15,23 +16,34 @@ bool FileManager::initializeSD() { bool FileManager::addMelody(JsonVariant doc) { LOG_INFO("Adding melody from JSON data..."); - + // Extract URL and filename from JSON if (!doc.containsKey("download_url") || !doc.containsKey("melodys_uid")) { LOG_ERROR("Missing required parameters: download_url or melodys_uid"); return false; } - + const char* url = doc["download_url"]; - const char* filename = doc["melodys_uid"]; - + const char* melodyUid = doc["melodys_uid"]; + + // Check if this is a built-in melody - skip download if it exists + if (BuiltInMelodies::isBuiltInMelody(melodyUid)) { + const BuiltInMelodies::MelodyInfo* builtinMelody = BuiltInMelodies::findMelodyByUID(melodyUid); + if (builtinMelody != nullptr) { + LOG_INFO("Melody '%s' is a built-in melody, skipping download", melodyUid); + return true; // Success - no download needed + } + // If starts with builtin_ but not found, log warning and try download anyway + LOG_WARNING("Melody '%s' has builtin_ prefix but not found in library, attempting download", melodyUid); + } + // Download the melody file to /melodies directory - if (downloadFile(url, "/melodies", filename)) { - LOG_INFO("Melody download successful: %s", filename); + if (downloadFile(url, "/melodies", melodyUid)) { + LOG_INFO("Melody download successful: %s", melodyUid); return true; } - - LOG_ERROR("Melody download failed: %s", filename); + + LOG_ERROR("Melody download failed: %s", melodyUid); return false; } @@ -62,11 +74,13 @@ bool FileManager::downloadFile(const String& url, const String& directory, const bool isHttps = url.startsWith("https://"); HTTPClient http; + WiFiClientSecure* secureClient = nullptr; // Configure HTTP client based on protocol if (isHttps) { - WiFiClientSecure* secureClient = new WiFiClientSecure(); + secureClient = new WiFiClientSecure(); secureClient->setInsecure(); // Skip certificate validation for Firebase + secureClient->setTimeout(15); // 15 second timeout for TLS operations http.begin(*secureClient, url); LOG_DEBUG("Using HTTPS with secure client"); } else { @@ -77,17 +91,28 @@ bool FileManager::downloadFile(const String& url, const String& directory, const http.setTimeout(30000); // 30 second timeout for large files http.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS); // Follow redirects automatically + // Disable task watchdog for current task during blocking HTTPS operation + // The TLS handshake can take several seconds and would trigger watchdog + LOG_DEBUG("Disabling watchdog for download..."); + esp_task_wdt_delete(NULL); + LOG_DEBUG("Sending HTTP GET request..."); int httpCode = http.GET(); + // Re-enable task watchdog after HTTP request completes + esp_task_wdt_add(NULL); + LOG_DEBUG("Watchdog re-enabled after HTTP request"); + if (httpCode != HTTP_CODE_OK && httpCode != HTTP_CODE_MOVED_PERMANENTLY && httpCode != HTTP_CODE_FOUND) { LOG_ERROR("HTTP GET failed, code: %d, error: %s", httpCode, http.errorToString(httpCode).c_str()); http.end(); + if (secureClient) delete secureClient; return false; } if (!initializeSD()) { http.end(); + if (secureClient) delete secureClient; return false; } @@ -95,6 +120,7 @@ bool FileManager::downloadFile(const String& url, const String& directory, const if (!ensureDirectoryExists(directory)) { LOG_ERROR("Failed to create directory: %s", directory.c_str()); http.end(); + if (secureClient) delete secureClient; return false; } @@ -107,6 +133,7 @@ bool FileManager::downloadFile(const String& url, const String& directory, const if (!file) { LOG_ERROR("Failed to open file for writing: %s", fullPath.c_str()); http.end(); + if (secureClient) delete secureClient; return false; } @@ -134,7 +161,7 @@ bool FileManager::downloadFile(const String& url, const String& directory, const file.write(buffer, bytesRead); totalBytes += bytesRead; - // Log progress every 5KB + // Log progress every 5 seconds if (millis() - lastLog > 5000) { LOG_DEBUG("Download progress: %u bytes", totalBytes); lastLog = millis(); @@ -142,10 +169,10 @@ bool FileManager::downloadFile(const String& url, const String& directory, const } } - // Aggressive task yielding every 100ms to prevent watchdog timeout - if (millis() - lastYield > 100) { + // Aggressive task yielding every 50ms to prevent watchdog timeout + if (millis() - lastYield > 50) { yield(); - vTaskDelay(1 / portTICK_PERIOD_MS); // Let other tasks run + vTaskDelay(5 / portTICK_PERIOD_MS); // Let other tasks run (5ms) lastYield = millis(); } @@ -154,14 +181,16 @@ bool FileManager::downloadFile(const String& url, const String& directory, const break; } - // Small delay if no data available yet + // Yield and small delay if no data available yet if (!availableSize) { - delay(10); + yield(); + vTaskDelay(10 / portTICK_PERIOD_MS); } } file.close(); http.end(); + if (secureClient) delete secureClient; LOG_INFO("Download complete, file saved to: %s (%u bytes)", fullPath.c_str(), totalBytes); return true; } diff --git a/vesper/src/FileManager/FileManager.hpp b/vesper/src/FileManager/FileManager.hpp index 9ec496d..cfacc67 100644 --- a/vesper/src/FileManager/FileManager.hpp +++ b/vesper/src/FileManager/FileManager.hpp @@ -24,13 +24,14 @@ #include #include #include +#include #include "../Logging/Logging.hpp" #include "../ConfigManager/ConfigManager.hpp" class FileManager { private: ConfigManager* configManager; - + public: // Constructor FileManager(ConfigManager* config); diff --git a/vesper/vesper.ino b/vesper/vesper.ino index b8f39bc..fca4dd4 100644 --- a/vesper/vesper.ino +++ b/vesper/vesper.ino @@ -64,7 +64,7 @@ * 👨‍💻 AUTHOR: BellSystems bonamin */ -#define FW_VERSION "152" +#define FW_VERSION "153" /* @@ -80,6 +80,7 @@ * v140 - Changed FW Updates to Direct-to-Flash and added manual update functionality with version check * v151 - Fixed Clock Alerts not running properly * v152 - Fix RTC Time Reports, added sync_time_to_LCD functionality + * v153 - Fix Infinite Loop Bug and Melody Download crashes. * ═══════════════════════════════════════════════════════════════════════════════ */