将 C++ 字符串放入 HTML 代码中以在网络服务器上显示值

Putting C++ string in HTML code to show value on webserver

我已经在目前托管 7 个站点的 ESP8266 上设置了一个网络服务器 运行ning。这些站点在 arduino ide 的每个不同选项卡中以普通 HTML 编写。我已经安装了库 Pagebuilder 来帮助让一切看起来都很好 运行。

除了一件事。我有一个按钮连接到我的 ESP8266,它正在模仿传感器输入。基本上,当按下按钮时,我的整数 "x" 递增 1。我还设法制作了一个复制 "x" 并以相同值递增的字符串。

我在打印服务器的 IP 地址时也遇到了问题,但这没有另一个重要。

然后我的计划是将字符串 "score"(包含 x)写入应该输出的 HTML 选项卡。这显然不起作用。

我尝试过的事情:

在我想要打印字符串的地方拆分 HTML 代码并使用 client.println(""); 这没有用,因为这两个库不合作,WiFiClient 找不到 Pagebuilders 服务器。 (基本上,当我将它与 Pagebuilder 一起使用时,client.println 什么都不做)。

将 HTML 页面重建为一个非常长的字符串,并像这样在字符串中添加 x:"html"+score+"html" 并将其添加到 [= 的位置53=] page const char 名。 (基本上用变量中的文本替换变量)。 这确实更有效,因为来自 Pagebuilder 的参数 "PageElement" 确实只需要一个字符串,并且会出错,因为 ide HTML 字符串

中还有一个额外的字符串

我试过将其作为 post 请求发送。但这也没有输出值。

我有 运行 个想法可以尝试。


//root page

#if defined(ARDUINO_ARCH_ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiClient.h>
#elif defined(ARDUINO_ARCH_ESP32)
#include <WiFi.h>
#include <WebServer.h>
#endif
#include "PageBuilder.h"


#include "currentGame.h" //tab 1

#if defined(ARDUINO_ARCH_ESP8266)
ESP8266WebServer Server;
ESP8266WebServer  server;
#endif

int sensorPin = 2;    // button input
int sensorValue = 0;  
int x = 0;            // the int  x 
String score="";      //the string x will be in




PageElement CURRENT_GAME_ELEMENT(htmlPage1);
PageBuilder CURRENT_GAME("/current-game", {CURRENT_GAME_ELEMENT}); // this //only showes on href /current-game

void button() {
  sensorValue = analogRead(sensorPin); //read the voltage
  score="Team 1: "+String((int)x+1);   //"make" x a string
  if (sensorValue <= 10) {             // check if button is pressed
    x++;                               // increment x
    Serial.println(x);
    Serial.println(score);
    delay(100);
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(2, INPUT);
  WiFi.softAP("SSID", "PASS");
  delay(100);         
  CURRENT_GAME.insert(Server);     

  Server.begin();
}

void loop() {
Server.handleClient();
button();
}

// tab 1 

const char htmlPage1[] PROGMEM = R"=====(

/*
alot of HTML, basicly the whole website...

..............................................

*/

<div class="jumbotron">
            <div align="center">
            <h1 class="display-4">     score      </h1> //  <--- this is where 
                                                        //I want to print the 
                                                        //string:
            </div>
            </div>

            )====="; 

我想做的是获取网站上显示的字符串分数的值。如果我把"score"直接放到HTML中,就会显示score这个词,而不是数值。我要显示值。

编辑:

我已经想出了如何在HTML代码中打印字符串(分数),因此,我只需要将HTML代码字符串转换回char。解释在下面的评论中。

编辑 2:(------------------------解决方案---------------- ----------)

非常感谢我得到的帮助,很抱歉我太无知了,离得太近太难了,而且那东西不起作用。但无论如何,我所做的是遵循 Pagebuilders 示例,并制作另一个元素以在当前游戏中打印..


String test(PageArgument& args) { 
  return score;
}

const char html[] = "<div class=\"jumbotron\"><div align=\"center\"><h1 class=\"display-4\">{{NAME}}</h1></div></div>";

PageElement FRAMEWORK_PAGE_ELEMENT(htmlPage0);
PageBuilder FRAMEWORK_PAGE("/", {FRAMEWORK_PAGE_ELEMENT});

PageElement body_elem(html, { {"NAME", test} });
PageElement CURRENT_GAME_ELEMENT(htmlPage1);
PageBuilder CURRENT_GAME("/current-game", { CURRENT_GAME_ELEMENT, body_elem});

当我第一次理解它时非常简单。再次感谢。

您可以尝试先构建字符串,然后将其转换为 const char 像这样:const char * c = str.c_str(); 如果你不能使用指针,你可以试试这个:

string s = "yourHTML" + score + "moreHTML"; 
int n = s.length(); 
char char_array[n + 1]; 
strcpy(char_array, s.c_str());

另外你可以试试 stringstream standard library

这种事情通常是在你的标记中使用魔术标签来完成的,这些标签在服务于 HTML 之前被服务器代码检测到,并通过执行某种回调或填充变量来填充,或者任何。

因此,考虑到这一点并希望最好,我快速浏览到:PageBuilder on github 并查看这里是否有类似的内容。好消息!在其中一个示例中:

const char html[] = "hello <b>{{NAME}}</b>, <br>Good {{DAYTIME}}.";
 ...
PageElement body_elem(html, { {"NAME", AsName}, {"DAYTIME", AsDayTime} });

其中 {{NAME}}{{DAYTIME}} 是魔法标记。 AsNameAsDayTime 是在提供页面时遇到相应标记时要调用的函数。

编辑:为了响应不同解释的请求,我不相信我能比图书馆自己的 github 页面上的示例更好地解释代码,所以我会尝试改为冗长的描述:

当您想向客户端提供网页时,代码需要知道您要提供的内容。在最简单的情况下,它是一个静态页面:每次都一样。你可以只写 HTML,把它放在一个字符串中就可以了。

whole_page = "<html>My fixed content</html>";
webserver.serve(whole_page);

但是您需要一些动态元素。如前所述,您可以通过几种方式来实现,例如提供一些静态 HTML,然后是动态位,然后是更多静态 HTML。看来您没有像这样的运气,而且它还是很笨拙。

或者您可以从这三个位中预先构建一个新字符串并在一个块中提供它,但这也很笨重。

(另外:获取大字符串并将它们加在一起可能会很慢并且会占用大量内存,这是您真正不想要的两件事 CPU,例如 ESP8266)。

因此,您允许在 HTML 中使用 'magic' 标记,使用标记代替动态内容,并改为提供该内容。

whole_page = "<html>My dynamic content.  Value is {{my_value}}</html>";
webserver.serve(whole_page, ...);

聪明的一点是,在提供页面时,网络服务器会观察文本经过,当它看到一个魔术标签时,它会停下来要求您填写空白,然后像以前一样继续.

显然,监视标签会产生一些处理开销,告诉它要监视哪些标签以及如何向您询问它需要的数据会产生一些编程开销。

我从一个朋友那里得到了建议,他告诉我应该在我想要字符串 (x) 的地方创建一个独特的参数,然后使用一些语法来替换它。我也从你那里得到了灵感 Jelle..

我所做的是制作一个独特的参数"VAR_CURRENT_SCORE" 将其放入我想要分数输出的 HTML 中,然后将 htmlPage1 从字符转换为字符串,使用 string.replace () 并将 "VAR_CURRENT_SCORE" 替换为字符串 (x) 分数。正如我在串行监视器输出中看到的那样,这是有效的。 这就是我所做的:

//root page
String HTMLstring(htmlstringPage);
delay(100);
HTMLstring.replace("VAR_CURRENT_SCORE", score);
delay(50);
Serial.println("string:");
Serial.println(HTMLstring);

//tab 1 char htmlstringPage[] PROGMEM = R"=====(
        <div class="jumbotron">
        <div align="center">
        <h1 class="display-4">VAR_CURRENT_SCORE</h1>
        </div>
        </div>
        )====="; 

但是,我还有一个小问题,就是将字符串转换回 char 以 post 将其发送到网站。

要将字符串转换回:

request->send_P(200, "text/html", HTMLstring.c_str());