From a1d486dd2de11e2df21f3e9789c31bd553fb23a2 Mon Sep 17 00:00:00 2001 From: Stefan Ostermann Date: Mon, 28 Jul 2025 14:15:11 +0200 Subject: [PATCH] fixed some crashes, html.. --- src/DirectoryNode.cpp | 114 ++++++++++++++++++++++---------------- src/main.cpp | 126 +++++++++++++++++++++++++++++++++++------- web/index.html | 19 ++++--- 3 files changed, 181 insertions(+), 78 deletions(-) diff --git a/src/DirectoryNode.cpp b/src/DirectoryNode.cpp index 85e8226..ae46e78 100644 --- a/src/DirectoryNode.cpp +++ b/src/DirectoryNode.cpp @@ -119,7 +119,10 @@ void DirectoryNode::buildDirectoryTree(const char *currentPath) } else if (String(entry.name()).endsWith(".mp3")||String(entry.name()).endsWith(".MP3")) { - mp3Files.push_back(entry.name()); + String fullPath = String(currentPath); + if (!fullPath.endsWith("/")) fullPath += "/"; + fullPath += entry.name(); + mp3Files.push_back(fullPath); ids.push_back(getNextId()); } entry.close(); @@ -182,75 +185,97 @@ void DirectoryNode::advanceToFirstMP3InThisNode() DirectoryNode *DirectoryNode::advanceToMP3(const uint16_t id) { - - + // First check MP3 files in this directory for (size_t i = 0; i < ids.size(); i++) + { + if (id == ids[i]) { - if (id == ids[i]) - { - // Found the current MP3 file - currentPlaying = &mp3Files[i]; - currentPlayingId = id; - return this; - } + // Found the current MP3 file + currentPlaying = &mp3Files[i]; + currentPlayingId = id; + return this; } + } + // Recursively search subdirectories for (auto subdir : subdirectories) { + // Check if the ID matches a subdirectory ID if (subdir->getId() == id) { subdir->advanceToFirstMP3InThisNode(); return subdir; } - // Have each subdirectory advance its song - for (size_t i = 0; i < subdir->ids.size(); i++) + // Recursively search in subdirectory + DirectoryNode* result = subdir->advanceToMP3(id); + if (result != nullptr && result->getCurrentPlaying() != nullptr) { - if (id == subdir->ids[i]) - { - // Found the current MP3 file - subdir->currentPlaying = &subdir->mp3Files[i]; - subdir->currentPlayingId = id; - return subdir; - } + return result; } } - // If we get here, there were no MP3 files or subdirectories left to check - currentPlaying = nullptr; - Serial.println("no more nodes found"); - return this; + // If we get here, no song with this ID was found + Serial.println("advanceToMP3: No song found for ID: " + String(id)); + return nullptr; } DirectoryNode *DirectoryNode::advanceToMP3(const String *currentGlobal) { + if (currentGlobal == nullptr) { + Serial.println("advanceToMP3: currentGlobal is null"); + return nullptr; + } + + // Check if the input is an absolute path (starts with '/') or just a filename + bool isAbsolutePath = currentGlobal->startsWith("/"); + + // First, check MP3 files in this directory + for (size_t i = 0; i < mp3Files.size(); i++) + { + if (isAbsolutePath) { + // For absolute paths, do exact match + if (*currentGlobal == mp3Files[i]) + { + setCurrentPlaying(&mp3Files[i]); + return this; + } + } else { + // For filenames, extract filename from full path and compare + String filename = mp3Files[i]; + int lastSlash = filename.lastIndexOf('/'); + if (lastSlash != -1) { + filename = filename.substring(lastSlash + 1); + } + if (*currentGlobal == filename) + { + setCurrentPlaying(&mp3Files[i]); + return this; + } + } + } + + // Recursively search subdirectories for (auto subdir : subdirectories) { - if (subdir->getName() == *currentGlobal) + // Check if the string matches a directory name (only for non-absolute paths) + if (!isAbsolutePath && subdir->getName() == *currentGlobal) { subdir->advanceToFirstMP3InThisNode(); return subdir; } - // Have each subdirectory advance its song - for (size_t i = 0; i < subdir->mp3Files.size(); i++) + // Recursively search in subdirectory + DirectoryNode* result = subdir->advanceToMP3(currentGlobal); + if (result != nullptr && result->getCurrentPlaying() != nullptr) { - if (*currentGlobal == subdir->mp3Files[i]) - { - // Found the current MP3 file - if (i < subdir->mp3Files.size() - 1) - { - subdir->setCurrentPlaying(&subdir->mp3Files[i]); - return subdir; - } - } + return result; } } - // If we get here, there were no MP3 files or subdirectories left to check - currentPlaying = nullptr; - Serial.println("no more nodes found"); - return this; + // If we get here, no matching song was found + Serial.println("advanceToMP3: No song found for: " + *currentGlobal); + return nullptr; } /** @@ -466,16 +491,7 @@ String DirectoryNode::getCurrentPlayingFilePath() const { if (currentPlaying != nullptr) { - String filePath = name; - if (!filePath.startsWith("/")) { - filePath = "/"+filePath; - } - if (!filePath.endsWith("/")) - { - filePath += "/"; - } - filePath += *currentPlaying; - return filePath; + return *currentPlaying; } return ""; } diff --git a/src/main.cpp b/src/main.cpp index 42c8fb1..c301a5c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -302,26 +302,43 @@ void playSongById(uint16_t id, uint32_t continueSeconds = 0) { currentNode = rootNode.advanceToMP3(id); - if (currentNode==nullptr) { + if (currentNode == nullptr) { + Serial.println("No node found for ID: " + String(id)); + return; + } + + // Check if the current playing song is valid + if (currentNode->getCurrentPlaying() == nullptr) { + currentNode = nullptr; + Serial.println("No song found for ID: " + String(id)); return; } String mp3File = currentNode->getCurrentPlayingFilePath(); - Serial.print("playing by id: "); - Serial.print(id);Serial.print(" ");Serial.println(continueSeconds); - - Serial.println(mp3File.c_str()); - deactivateRFID(); - activateSD(); - - if (currentNode != nullptr && currentNode->getCurrentPlaying()==nullptr) { + if (mp3File.length() == 0) { currentNode = nullptr; - Serial.println("no node by id found, exiting playSongById"); + Serial.println("Empty file path for ID: " + String(id)); return; } - playFile(mp3File.c_str()); - if (continueSeconds!=0) { + Serial.print("Playing by ID: "); + Serial.print(id); + Serial.print(" "); + Serial.println(continueSeconds); + Serial.println(mp3File.c_str()); + + deactivateRFID(); + activateSD(); + + if (!playFile(mp3File.c_str())) { + Serial.println("Failed to play file: " + mp3File); + currentNode = nullptr; + activateRFID(); + deactivateSD(); + return; + } + + if (continueSeconds != 0) { audio.setAudioPlayPosition(continueSeconds); } activateRFID(); @@ -330,12 +347,45 @@ void playSongById(uint16_t id, uint32_t continueSeconds = 0) void playSongByName(String song) { + if (song.length() == 0) { + Serial.println("Empty song name provided"); + return; + } + currentNode = rootNode.advanceToMP3(&song); + if (currentNode == nullptr) { + Serial.println("No node found for song: " + song); + return; + } + + // Check if the current playing song is valid + if (currentNode->getCurrentPlaying() == nullptr) { + currentNode = nullptr; + Serial.println("No song found for name: " + song); + return; + } + String mp3File = currentNode->getCurrentPlayingFilePath(); - Serial.println(mp3File.c_str()); + if (mp3File.length() == 0) { + currentNode = nullptr; + Serial.println("Empty file path for song: " + song); + return; + } + + Serial.println("Playing song: " + mp3File); deactivateRFID(); activateSD(); - playFile(mp3File.c_str()); + + if (!playFile(mp3File.c_str())) { + Serial.println("Failed to play file: " + mp3File); + currentNode = nullptr; + activateRFID(); + deactivateSD(); + return; + } + + activateRFID(); + deactivateSD(); } void playSongByPath(String path) @@ -345,13 +395,23 @@ void playSongByPath(String path) void playSongByRFID(String id) { - auto songit = rfid_map.find(id); - if (songit==rfid_map.end()) { - Serial.println("song for uid not found."); + if (id.length() == 0) { + Serial.println("Empty RFID ID provided"); return; } - Serial.println("searching for "); - Serial.println(songit->second); + + auto songit = rfid_map.find(id); + if (songit == rfid_map.end()) { + Serial.println("Song for UID not found: " + id); + return; + } + + if (songit->second.length() == 0) { + Serial.println("Empty song name mapped to RFID: " + id); + return; + } + + Serial.println("Searching for song: " + songit->second); playSongByName(songit->second); } @@ -517,7 +577,7 @@ void editMapping(AsyncWebServerRequest *request) { } } -std::map readDataFromFile(const char *filename) { +std::map readDataFromFile(String filename) { File file = SD.open(filename); @@ -530,6 +590,7 @@ std::map readDataFromFile(const char *filename) { // Extract key and value String key = line.substring(0, separatorIndex).c_str(); String value = line.substring(separatorIndex + 1).c_str(); + Serial.println("found rfid mapping for "+value); // Add key-value pair to the map rfid_map[key] = value; } @@ -549,6 +610,29 @@ String processor(const String &var) { return rootNode.getDirectoryStructureHTML(); } + + if (var == "MAPPING") { + auto htmlEscape = [](const String& s) -> String { + String out; + for (size_t i = 0; i < s.length(); ++i) { + char c = s[i]; + if (c == '&') out += "&"; + else if (c == '<') out += ""; + else if (c == '>') out += ""; + else if (c == '"') out += ""; + else if (c == '\'') out += ""; + else out += c; + } + return out; + }; + String html = ""; + for (const auto& pair : rfid_map) { + html += ""; + } + html += "
RFIDSong
" + htmlEscape(pair.first) + "" + htmlEscape(pair.second) + "
"; + return html; + } + return String(); // Return empty string instead of creating new String } @@ -747,7 +831,7 @@ void setup() rootNode.buildDirectoryTree("/"); rootNode.printDirectoryTree(); - readDataFromFile(mapping_file.c_str()); + readDataFromFile(getSysDir(mapping_file)); diff --git a/web/index.html b/web/index.html index 60c97a6..6a583cb 100644 --- a/web/index.html +++ b/web/index.html @@ -8,9 +8,7 @@

🎵 HannaBox 🎵



-
-
-
+
@@ -42,11 +40,13 @@ - +

Edit RFID Mapping

+ Hint: Use a folder or filename, not the absolute file path! +
%MAPPING%

@@ -77,8 +79,9 @@
-
+

Delete File

+