ESP32 - 具有可变内容的网络服务器网页
ESP32 - Webserver webpage with variable content
我将 ESP32 配置为网络服务器。我有多个网页,我将其包含为文件
例如index.h
const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
some divs here....
</html>
)=====";
这个页面的内容是div形成了一个table的结构。
在我的程序中,我有 2 个变量 numrows
和 numtables
,它们定义了我必须显示多少 table 以及每个 table 有多少行。那里的所有 ID 都应该相应地调整 ID。例如,第二个 table 的第一个 div 可能是 id="t2d1"
.
问题是:像上面那样在外部文件中声明了网页,如何在向用户显示页面之前动态更改内容?
您应该 post Minimal, Reproducible Example 以获得详细的建议。否则我们只能猜测你的框架、语言、网络服务器等是什么
取决于您的网络服务器的工作方式。如果它很简单并且希望您一次给它整个页面,则必须分配一块 RAM(例如,从堆中动态分配,或者可能在编译时从数据部分分配)并在其中生成网页在将其交给服务器之前。
在极其简单的情况下,您可以 snprintf()
整个页面并将其移交:
const size_t MAX_PAGE_LEN = 128;
const char template[] = "<html><head><title> %s </title></head><body> %s </body></html>";
char* webDoc = (char*) malloc(MAX_PAGE_LEN);
const int len = snprintf(webDoc, MAX_PAGE_LEN, template, "My Title", "My Body");
assert(len > 0 && len < MAX_PAGE_LEN);
// Pass memory in "webDoc" to web server
// webserver.serve(webDoc, len);
free(webDoc);
在更复杂的情况下——例如具有动态大小和内容的 tables——你最终会编写更复杂的代码(例如循环遍历 tables 及其行),但是基本思想保持不变。您必须将整个文档生成到缓冲区中,然后将其传递给 Web 服务器(假设它是这样工作的)。您可能想要创建一个小库来生成常见的 HTML 结构,或者找到一个简单的模板库来帮助代码重用。注意分配足够的内存来存储最终文档。
例如,我会使用 C++ 字符串流。他们严重依赖于从堆中分配和重新分配内存,这在 ESP32 上应该 大多数 OK - 只要您使用常识。不要取太多,预先分配好你预计使用的量等等
#include <iostream>
#include <sstream>
std::ostringstream webDoc;
webDoc << "<html><body>";
for (unsigned table = 0; table < numtables; table++) {
webDoc << "<table>";
for (unsigned row = 0; row < numrows; row++) {
webDoc << "<tr>";
webDoc << "<td>some data</td>";
webDoc << "</tr>";
}
webDoc << "</table>";
}
webDoc << "</body></html>";
// Pass memory in "webDoc" to web server, not optimal as string gets copied
// webserver.serve(webDoc.str().c_str(), webDoc.str().len());
如果您的 Web 服务器不需要预先提供整个文档,那么您可以一次将其中的大块内容提供给它。在这种情况下,您可以减少内存使用量,因为您可以准备一行 table,告诉 Web 服务器发送它;然后准备下一行。
我将 ESP32 配置为网络服务器。我有多个网页,我将其包含为文件
例如index.h
const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
some divs here....
</html>
)=====";
这个页面的内容是div形成了一个table的结构。
在我的程序中,我有 2 个变量 numrows
和 numtables
,它们定义了我必须显示多少 table 以及每个 table 有多少行。那里的所有 ID 都应该相应地调整 ID。例如,第二个 table 的第一个 div 可能是 id="t2d1"
.
问题是:像上面那样在外部文件中声明了网页,如何在向用户显示页面之前动态更改内容?
您应该 post Minimal, Reproducible Example 以获得详细的建议。否则我们只能猜测你的框架、语言、网络服务器等是什么
取决于您的网络服务器的工作方式。如果它很简单并且希望您一次给它整个页面,则必须分配一块 RAM(例如,从堆中动态分配,或者可能在编译时从数据部分分配)并在其中生成网页在将其交给服务器之前。
在极其简单的情况下,您可以 snprintf()
整个页面并将其移交:
const size_t MAX_PAGE_LEN = 128;
const char template[] = "<html><head><title> %s </title></head><body> %s </body></html>";
char* webDoc = (char*) malloc(MAX_PAGE_LEN);
const int len = snprintf(webDoc, MAX_PAGE_LEN, template, "My Title", "My Body");
assert(len > 0 && len < MAX_PAGE_LEN);
// Pass memory in "webDoc" to web server
// webserver.serve(webDoc, len);
free(webDoc);
在更复杂的情况下——例如具有动态大小和内容的 tables——你最终会编写更复杂的代码(例如循环遍历 tables 及其行),但是基本思想保持不变。您必须将整个文档生成到缓冲区中,然后将其传递给 Web 服务器(假设它是这样工作的)。您可能想要创建一个小库来生成常见的 HTML 结构,或者找到一个简单的模板库来帮助代码重用。注意分配足够的内存来存储最终文档。
例如,我会使用 C++ 字符串流。他们严重依赖于从堆中分配和重新分配内存,这在 ESP32 上应该 大多数 OK - 只要您使用常识。不要取太多,预先分配好你预计使用的量等等
#include <iostream>
#include <sstream>
std::ostringstream webDoc;
webDoc << "<html><body>";
for (unsigned table = 0; table < numtables; table++) {
webDoc << "<table>";
for (unsigned row = 0; row < numrows; row++) {
webDoc << "<tr>";
webDoc << "<td>some data</td>";
webDoc << "</tr>";
}
webDoc << "</table>";
}
webDoc << "</body></html>";
// Pass memory in "webDoc" to web server, not optimal as string gets copied
// webserver.serve(webDoc.str().c_str(), webDoc.str().len());
如果您的 Web 服务器不需要预先提供整个文档,那么您可以一次将其中的大块内容提供给它。在这种情况下,您可以减少内存使用量,因为您可以准备一行 table,告诉 Web 服务器发送它;然后准备下一行。