[ai] dir streaming, still problems
This commit is contained in:
parent
dc735c044f
commit
083dfd6e2a
|
|
@ -578,6 +578,44 @@ String DirectoryNode::getDirectoryStructureHTML() const {
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DirectoryNode::streamDirectoryHTML(Print &out) const {
|
||||||
|
if (name == "/") {
|
||||||
|
out.println(F("<ul>"));
|
||||||
|
delay(0); // yield to WiFi/other tasks
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name != "/") {
|
||||||
|
out.print(F("<li data-id=\""));
|
||||||
|
out.print(id);
|
||||||
|
out.print(F("\"><b>"));
|
||||||
|
out.print(name);
|
||||||
|
out.println(F("</b></li>"));
|
||||||
|
delay(0); // yield periodically while streaming
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mp3Files.size(); i++) {
|
||||||
|
out.print(F("<li data-id=\""));
|
||||||
|
out.print(ids[i]);
|
||||||
|
out.print(F("\">"));
|
||||||
|
out.print(mp3Files[i]);
|
||||||
|
out.println(F("</li>"));
|
||||||
|
if ((i & 0x0F) == 0) { // yield every ~16 items
|
||||||
|
delay(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DirectoryNode* child : subdirectories) {
|
||||||
|
delay(0); // yield before descending
|
||||||
|
child->streamDirectoryHTML(out);
|
||||||
|
delay(0); // and after returning
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == "/") {
|
||||||
|
out.println(F("</ul>"));
|
||||||
|
delay(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NEW: Calculate exact required size first
|
// NEW: Calculate exact required size first
|
||||||
size_t DirectoryNode::calculateHTMLSize() const {
|
size_t DirectoryNode::calculateHTMLSize() const {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#ifndef DIRECTORYNODE_H_
|
#ifndef DIRECTORYNODE_H_
|
||||||
#define DIRECTORYNODE_H_
|
#define DIRECTORYNODE_H_
|
||||||
|
class Print;
|
||||||
|
|
||||||
#include <SD.h>
|
#include <SD.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -55,6 +56,7 @@ public:
|
||||||
DirectoryNode* advanceToMP3(const uint16_t id);
|
DirectoryNode* advanceToMP3(const uint16_t id);
|
||||||
void advanceToFirstMP3InThisNode();
|
void advanceToFirstMP3InThisNode();
|
||||||
String getDirectoryStructureHTML() const;
|
String getDirectoryStructureHTML() const;
|
||||||
|
void streamDirectoryHTML(Print &out) const;
|
||||||
size_t calculateHTMLSize() const;
|
size_t calculateHTMLSize() const;
|
||||||
void appendIndentation(String& html, int level) const;
|
void appendIndentation(String& html, int level) const;
|
||||||
DirectoryNode* findFirstDirectoryWithMP3s();
|
DirectoryNode* findFirstDirectoryWithMP3s();
|
||||||
|
|
|
||||||
11
src/main.cpp
11
src/main.cpp
|
|
@ -1217,15 +1217,14 @@ server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||||
{
|
{
|
||||||
webreq_enter();
|
webreq_enter();
|
||||||
request->onDisconnect([](){ webreq_exit(); });
|
request->onDisconnect([](){ webreq_exit(); });
|
||||||
// Stream the response to avoid lifetime issues with temporary Strings and to prevent wrong Content-Length
|
// Stream the response directly from the directory tree to avoid large temporary Strings
|
||||||
AsyncResponseStream* stream = request->beginResponseStream("text/html; charset=UTF-8");
|
AsyncResponseStream* stream = request->beginResponseStream("text/html; charset=UTF-8");
|
||||||
stream->addHeader("Cache-Control", "no-store");
|
stream->addHeader("Cache-Control", "no-store");
|
||||||
stream->addHeader("Connection", "close");
|
stream->addHeader("Connection", "close");
|
||||||
// Build HTML under lock, then print into stream
|
// Generate HTML directly into the stream under lock
|
||||||
dir_lock_acquire();
|
dir_lock_acquire();
|
||||||
String html = rootNode.getDirectoryStructureHTML();
|
rootNode.streamDirectoryHTML(*stream);
|
||||||
dir_lock_release();
|
dir_lock_release();
|
||||||
stream->print(html);
|
|
||||||
request->send(stream);
|
request->send(stream);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1508,12 +1507,8 @@ void loop()
|
||||||
if (webreq_cnt > 0 && webrequest_blockings > MAX_WEBREQUEST_BLOCKINGS) {
|
if (webreq_cnt > 0 && webrequest_blockings > MAX_WEBREQUEST_BLOCKINGS) {
|
||||||
Serial.println("excessive webrequest blocking - suppress reset");
|
Serial.println("excessive webrequest blocking - suppress reset");
|
||||||
// Avoid resetting server mid-response to prevent mixing headers/body or truncation
|
// Avoid resetting server mid-response to prevent mixing headers/body or truncation
|
||||||
server.reset();
|
|
||||||
init_webserver();
|
|
||||||
|
|
||||||
webreq_cnt = 0;
|
webreq_cnt = 0;
|
||||||
webrequest_blockings = 0;
|
webrequest_blockings = 0;
|
||||||
server.begin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audio.isRunning())
|
if (audio.isRunning())
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,9 @@ setInterval(updateProgress, 500); // Update progress every second
|
||||||
if ((this.__url || '').indexOf('/upload') !== -1) {
|
if ((this.__url || '').indexOf('/upload') !== -1) {
|
||||||
timeoutMs = 600000; // 10 minutes for uploads
|
timeoutMs = 600000; // 10 minutes for uploads
|
||||||
} else if (this.__method === 'GET') {
|
} else if (this.__method === 'GET') {
|
||||||
timeoutMs = 3500;
|
|
||||||
} else {
|
|
||||||
timeoutMs = 6000;
|
timeoutMs = 6000;
|
||||||
|
} else {
|
||||||
|
timeoutMs = 8000;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isIdempotentGET && inflightKeys.has(key)) {
|
if (isIdempotentGET && inflightKeys.has(key)) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue