String optimizations

This commit is contained in:
Stefan Ostermann 2025-07-30 11:00:57 +02:00
parent f40483873a
commit 00048face4
2 changed files with 46 additions and 28 deletions

View File

@ -455,7 +455,8 @@ DirectoryNode *DirectoryNode::advanceToNextMP3(const String *currentGlobal)
String DirectoryNode::getDirectoryStructureHTML() const String DirectoryNode::getDirectoryStructureHTML() const
{ {
String html; String html;
html.reserve(1024); // Reserve memory for better performance html.reserve(512);
if (name == "/") if (name == "/")
{ {
html += "<ul>\n"; html += "<ul>\n";
@ -487,7 +488,7 @@ void DirectoryNode::appendIndentation(String &html, int level) const
{ {
for (int i = 0; i < level; i++) for (int i = 0; i < level; i++)
{ {
html += " "; html.concat(" ");
} }
} }

View File

@ -481,7 +481,7 @@ void playNextMp3()
{ {
stop(); stop();
continuousMode = true; continuousMode = true;
if (currentNode == NULL) if (currentNode == nullptr)
{ {
currentNode = rootNode.findFirstDirectoryWithMP3s(); currentNode = rootNode.findFirstDirectoryWithMP3s();
if (currentNode) if (currentNode)
@ -494,14 +494,14 @@ void playNextMp3()
currentNode = rootNode.advanceToNextMP3(currentNode->getCurrentPlaying()); currentNode = rootNode.advanceToNextMP3(currentNode->getCurrentPlaying());
} }
if (currentNode != NULL) if (currentNode != nullptr)
{ {
currentNode->setSecondsPlayed(0); currentNode->setSecondsPlayed(0);
} }
Serial.print("Now advancing to "); Serial.print("Advancing to ");
String mp3File = currentNode->getCurrentPlayingFilePath(); String mp3File = currentNode->getCurrentPlayingFilePath();
Serial.println(mp3File.c_str()); Serial.println(mp3File);
deactivateRFID(); deactivateRFID();
activateSD(); activateSD();
playFile(mp3File.c_str()); playFile(mp3File.c_str());
@ -620,6 +620,12 @@ String getState()
{ {
// Use static buffer to avoid repeated allocations // Use static buffer to avoid repeated allocations
static DynamicJsonDocument jsonState(512); static DynamicJsonDocument jsonState(512);
static String output;
output.reserve(512); // Pre-allocate string buffer
output.clear();
jsonState.clear(); // Clear previous data jsonState.clear(); // Clear previous data
jsonState["playing"] = audio.isRunning(); jsonState["playing"] = audio.isRunning();
@ -627,7 +633,7 @@ String getState()
if (currentNode != nullptr) if (currentNode != nullptr)
jsonState["title"] = *currentNode->getCurrentPlaying(); jsonState["title"] = *currentNode->getCurrentPlaying();
else else
jsonState["title"] = "Angehalten"; jsonState["title"] = "Stopped";
if (currentNode != nullptr) if (currentNode != nullptr)
jsonState["filepath"] = currentNode->getCurrentPlayingFilePath(); jsonState["filepath"] = currentNode->getCurrentPlayingFilePath();
@ -641,8 +647,7 @@ String getState()
jsonState["uid"] = lastUid; jsonState["uid"] = lastUid;
jsonState["heap"] = free_heap; jsonState["heap"] = free_heap;
String output;
output.reserve(512); // Pre-allocate string buffer
serializeJson(jsonState, output); serializeJson(jsonState, output);
return output; return output;
@ -656,7 +661,9 @@ void saveMappingToFile(const String filename)
{ {
for (const auto &pair : rfid_map) for (const auto &pair : rfid_map)
{ {
file.println(pair.first + "=" + pair.second); file.print(pair.first);
file.print("="); // Using F() macro
file.println(pair.second);
} }
file.close(); file.close();
Serial.println("Mapping saved to file."); Serial.println("Mapping saved to file.");
@ -751,12 +758,18 @@ String processor(const String &var)
} }
return out; return out;
}; };
String html = "<table style='width:100%;border-collapse:collapse;'><tr><th style='border:1px solid #ccc;padding:4px;'>RFID</th><th style='border:1px solid #ccc;padding:4px;'>Song</th></tr>"; String html;
html.reserve(256);
html.concat(F("<table style='width:100%;border-collapse:collapse;'><tr><th style='border:1px solid #ccc;padding:4px;'>RFID</th><th style='border:1px solid #ccc;padding:4px;'>Song</th></tr>"));
for (const auto &pair : rfid_map) for (const auto &pair : rfid_map)
{ {
html += "<tr><td style='border:1px solid #ccc;padding:4px;'>" + htmlEscape(pair.first) + "</td><td style='border:1px solid #ccc;padding:4px;'>" + htmlEscape(pair.second) + "</td></tr>"; html.concat(F("<tr><td style='border:1px solid #ccc;padding:4px;'>"));
html.concat(htmlEscape(pair.first));
html.concat(F("</td><td style='border:1px solid #ccc;padding:4px;'>"));
html.concat(htmlEscape(pair.second));
html.concat("</td></tr>");
} }
html += "</table>"; html.concat("</table>");
return html; return html;
} }
@ -886,12 +899,12 @@ void previous()
} }
else else
{ {
Serial.println("previous(): Global previous song is null"); Serial.println("prev: Global previous song is null");
} }
} }
else else
{ {
Serial.println("previous(): No previous song found globally - at beginning of playlist"); Serial.println("prev: No previous song found, beginning again");
// Optionally restart current song or do nothing // Optionally restart current song or do nothing
audio.setAudioPlayPosition(0); audio.setAudioPlayPosition(0);
currentNode->setSecondsPlayed(0); currentNode->setSecondsPlayed(0);
@ -1006,7 +1019,7 @@ void setup()
// Optimize audio buffer size to save memory (ESP32-audioI2S optimization) // Optimize audio buffer size to save memory (ESP32-audioI2S optimization)
audio.setBufferSize(8192); // Reduced from default large buffer (saves 40-600KB!) audio.setBufferSize(8192); // Reduced from default large buffer (saves 40-600KB!)
Serial.println("Audio initialized."); Serial.println("Audio init");
lastVoltage = getBatteryVoltageMv(); lastVoltage = getBatteryVoltageMv();
@ -1045,7 +1058,7 @@ void setup()
else else
{ {
// Fallback: serve minimal error if file not found // Fallback: serve minimal error if file not found
request->send(404, "text/plain", "ERROR: /system/index.html on SD Card not found!"); request->send(404, "text/plain", "ERROR: /system/index.html not found!");
} }
webrequestActive = false; webrequestActive = false;
}); });
@ -1061,7 +1074,7 @@ void setup()
else else
{ {
// Fallback: serve minimal CSS if file not found // Fallback: serve minimal CSS if file not found
request->send(404, "text/plain", "ERROR: /system/style.css on SD Card not found!"); request->send(404, "text/plain", "ERROR: /system/style.css ot found!");
} }
webrequestActive = false; webrequestActive = false;
}); });
@ -1079,7 +1092,7 @@ void setup()
else else
{ {
// Fallback: serve minimal JS if file not found // Fallback: serve minimal JS if file not found
request->send(404, "text/plain", "ERROR: /system/script.js on SD Card not found!"); request->send(404, "text/plain", "ERROR: /system/script.js not found!");
} }
webrequestActive = false; webrequestActive = false;
}); });
@ -1135,11 +1148,11 @@ void setup()
server.on("/delete_file", HTTP_GET, handleDeleteFile); server.on("/delete_file", HTTP_GET, handleDeleteFile);
server.begin(); server.begin();
Serial.println("Wifi initialized."); Serial.println("Wifi init");
} }
else else
{ {
Serial.println("Wifi timed out. Fallback no Wifi."); Serial.println("Wifi timed out. Fallback.");
} }
Serial.println("Activating Brownout detector..."); Serial.println("Activating Brownout detector...");
@ -1155,13 +1168,11 @@ void setup()
0); /* Core where the task should run */ 0); /* Core where the task should run */
lastInteraction = millis(); lastInteraction = millis();
Serial.println("initialization done."); Serial.println("Init done.");
} }
void id_song_action(AsyncWebServerRequest *request) void id_song_action(AsyncWebServerRequest *request)
{ {
Serial.println("song by id!");
int params = request->params(); int params = request->params();
for (int i = 0; i < params; i++) for (int i = 0; i < params; i++)
{ {
@ -1209,7 +1220,13 @@ void volume_action(AsyncWebServerRequest *request)
const String getSysDir(const String filename) const String getSysDir(const String filename)
{ {
return "/" + sys_dir + "/" + filename; static String st_sys_str(96);
st_sys_str.clear();
st_sys_str.concat("/");
st_sys_str.concat(sys_dir);
st_sys_str.concat("/");
st_sys_str.concat(filename);
return st_sys_str;
} }
void loop() void loop()
@ -1252,7 +1269,7 @@ void loop()
{ {
sleepSoundPlayed = true; sleepSoundPlayed = true;
prepareSleepMode = true; prepareSleepMode = true;
if (currentNode != NULL) if (currentNode != nullptr)
{ {
String progressPath = getSysDir(progress_file); String progressPath = getSysDir(progress_file);
writeSongProgress(progressPath.c_str(), currentNode->getCurrentPlayingId(), currentNode->getSecondsPlayed()); writeSongProgress(progressPath.c_str(), currentNode->getCurrentPlayingId(), currentNode->getSecondsPlayed());
@ -1264,7 +1281,7 @@ void loop()
if (now - lastInteraction > config.sleepDelay) if (now - lastInteraction > config.sleepDelay)
{ {
Serial.println("entering deep sleep..."); Serial.println("entering deep sleep..");
deactivateRFID(); deactivateRFID();
deactivateSD(); deactivateSD();
esp_deep_sleep_start(); esp_deep_sleep_start();
@ -1332,7 +1349,7 @@ void loop()
{ {
if (voltage_threshold_counter > 3) if (voltage_threshold_counter > 3)
{ {
Serial.println("entering deep sleep due to low voltage..."); Serial.println("deep sleep due to low volts..");
lastInteraction = millis() - config.sleepMessageDelay; lastInteraction = millis() - config.sleepMessageDelay;
voltage_threshold_counter = 0; voltage_threshold_counter = 0;
} }