草庐IT

ESP32网页控制显示数据原来如此简单

XlinliY.Zhang 2024-05-03 原文

一、写在前头

        本文着重于ESP32与网页的交互,并没有针对网页进行UI优化,也不会对HTM5的组件进行详细介绍,只讲解一些关键的JS函数。

        代码以Arduino框架进行开发,使用ESPAsyncWebServer库实现WebServer,通过JS代码配合库文件的回调函数进行使用,只讲交互部分,文章内容不关注数据的来源以及控制。

二、如何对ESP32进行配置

(1)基础配置

        ESPAsyncTCP库下载

        ESPAsyncWebServer库下载

        首先需要一些基础框架,对库文件的引用,并设置好端口号和网站的首页

#include <ESPAsyncWebServer.h>    // 包含异步Web服务器库文件

AsyncWebServer server(80);        // 创建WebServer对象, 端口号80
// 使用端口号80可以直接输入IP访问,使用其它端口需要输入IP:端口号访问
// 一个储存网页的数组
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
     <h2>ESP32 网页</h2>
</body>
<script>
    
</script>)rawliteral";
void setup()
{
  // 你需要再此处添加WiFi操作代码,开启热点或者连接到热点
  // 添加HTTP主页,当访问的时候会把网页推送给访问者
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
            { request->send_P(200, "text/html", index_html); });
  server.begin();  // 初始化HTTP服务器
}


void loop()
{
}

        当你添加上WiFi操作代码,把这个程序烧录入ESP32,并通过浏览器访问ESP32的IP地址时,浏览器会显示这个画面:

三、 如何在网页上显示数据

(1)打包你需要显示的数据

        以显示温度和湿度为例,需要将温湿度打包为HTML代码块

String Merge_Data(void)
{
  int Humidity = 50;// 此处应为获取温度代码
  int Temperature = 26;// 此处应为获取湿度代码
  // 将温湿度打包为一个HTML显示代码
  String dataBuffer = "<p>";
  dataBuffer += "<h1>传感器数据 </h1>";
  dataBuffer += "<b>温度: </b>";
  dataBuffer += String(Temperature);
  dataBuffer += "<br/>";
  dataBuffer += "<b>湿度: </b>";
  dataBuffer += String(Humidity );
  dataBuffer += "<br /></p>";
  // 最后要将数组返回出去
  return dataBuffer;
}

(2)添加对应的响应

        然后在setup中,server初始化前添加响应代码,把数据返回出去。

void setup()
{
  // 你需要再此处添加WiFi操作代码,开启热点或者连接到热点
  // 添加HTTP主页,当访问的时候会把网页推送给访问者
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
            { request->send_P(200, "text/html", index_html); });
  // 设置反馈的信息,在HTML请求这个Ip/dht这个链接时,返回打包好的传感器数据
  server.on("/dht", HTTP_GET, [](AsyncWebServerRequest *request)
            { request->send_P(200, "text/plain", Merge_Data().c_str()); });
  server.begin();  // 初始化HTTP服务器
}

(3)修改HTML定时请求数据

        数据打包好了,也返回给HTML了,这个时候我们就需要HTML定时去请求数据,所以我们要在HTML中使用JS代码的定时器,来定时采集数据。

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
     <h2>ESP32 网页</h2>
     <!-- 创建一个ID位dht的盒子用于显示获取到的数据 -->
     <div id="dht">
     </div>
</body>
<script>
     // 设置一个定时任务, 1000ms执行一次
     setInterval(function () {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function () {
            if (this.readyState == 4 && this.status == 200) {
                // 此代码会搜索ID为dht的组件,然后使用返回内容替换组件内容
                document.getElementById("dht").innerHTML = this.responseText;
            }
        };
        // 使用GET的方式请求 /dht
        xhttp.open("GET", "/dht", true);
        xhttp.send();
    }, 1000)
</script>

        当代码请求到结果的时候,就会使用结果替换ID为dht的组件内容(此处为DIV盒子)。所以,我们在打包数据的时候就要提前对数据加上HTML代码进行美化,如果不加以美化,返回的就只会是单纯的一串字符串,可读性极差。烧录代码后,显示效果如下:

        

温湿度显示效果

 四、如何下发数据

(1)修改HTML添加必要的组件

        以按钮为例,我们需要在HTML中添加一个按钮

<button onclick="set()"> 发送数据 </button>

        按钮需要绑定onclick运行JS函数

// 按下按钮会运行这个JS函数
	function set() {
		var payload = "ESP32"; // 需要发送的内容
		// 通过get请求给 /set
		var xhr = new XMLHttpRequest();
		xhr.open("GET", "/set?value=" + payload, true);
		xhr.send();
	}

        当我们按下按钮的时候,触发onclick事件,进而运行JS中的函数 set。

        运行JS函数后,会将payload已GET的方式提交到/set。

        

                                                                 

(2)在ESP32添加对应的响应

        上面的HTML发送过来的数据,通用需要添加对应的响应来获取内容z

// 下发处理回调函数
void Config_Callback(AsyncWebServerRequest *request)
{
  if (request->hasParam("value")) // 如果有值下发
  {
    String HTTP_Payload = request->getParam("value")->value();    // 获取下发的数据
    Serial.printf("[%lu]%s\r\n", millis(), HTTP_Payload.c_str()); // 打印调试信息
  }
  request->send(200, "text/plain", "OK"); // 发送接收成功标志符
}
  
void setup()
{
  // 你需要再此处添加WiFi操作代码,开启热点或者连接到热点
  // 添加HTTP主页,当访问的时候会把网页推送给访问者
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
            { request->send_P(200, "text/html", index_html); });
  // 设置反馈的信息,在HTML请求这个Ip/dht这个链接时,返回打包好的传感器数据
  server.on("/dht", HTTP_GET, [](AsyncWebServerRequest *request)
            { request->send_P(200, "text/plain", Merge_Data().c_str()); });
  server.on("/set", HTTP_GET, Config_Callback);   // 绑定配置下发的处理函数
  server.begin();  // 初始化HTTP服务器
}

        这样,数据就从HTML到了ESP32,接下来就是对HTTP_Payload 字符串内的数据进行处理即可,在此不再赘述。

五、最终的代码


#include <ESPAsyncWebServer.h>    // 包含异步Web服务器库文件

AsyncWebServer server(80);        // 创建WebServer对象, 端口号80
// 使用端口号80可以直接输入IP访问,使用其它端口需要输入IP:端口号访问
// 一个储存网页的数组
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML>
<html>

<head>
	<meta charset="utf-8">
</head>

<body>
	<h2>ESP32 网页</h2>
	<!-- 创建一个ID位dht的盒子用于显示获取到的数据 -->
	<div id="dht">
	</div>
	<button onclick="set()"> 发送数据 </button>
</body>

<script>
	// 按下按钮会运行这个JS函数
	function set() {
		var payload = "ESP32"; // 需要发送的内容
		// 通过get请求给 /set
		var xhr = new XMLHttpRequest();
		xhr.open("GET", "/set?value=" + payload, true);
		xhr.send();
	}
	// 设置一个定时任务, 1000ms执行一次
	setInterval(function () {
		var xhttp = new XMLHttpRequest();
		xhttp.onreadystatechange = function () {
			if (this.readyState == 4 && this.status == 200) {
				// 此代码会搜索ID为dht的组件,然后使用返回内容替换组件内容
				document.getElementById("dht").innerHTML = this.responseText;
			}
		};
		// 使用GET的方式请求 /dht
		xhttp.open("GET", "/dht", true);
		xhttp.send();
	}, 1000)

</script>)rawliteral";
String Merge_Data(void)
{
  int Humidity = 50;// 此处应为获取温度代码
  int Temperature = 26;// 此处应为获取湿度代码
  // 将温湿度打包为一个HTML显示代码
  String dataBuffer = "<p>";
  dataBuffer += "<h1>传感器数据 </h1>";
  dataBuffer += "<b>温度: </b>";
  dataBuffer += String(Temperature);
  dataBuffer += "<br/>";
  dataBuffer += "<b>湿度: </b>";
  dataBuffer += String(Humidity );
  dataBuffer += "<br /></p>";
  // 最后要将数组返回出去
  return dataBuffer;
}

// 下发处理回调函数
void Config_Callback(AsyncWebServerRequest *request)
{
  if (request->hasParam("value")) // 如果有值下发
  {
    String HTTP_Payload = request->getParam("value")->value();    // 获取下发的数据
    Serial.printf("[%lu]%s\r\n", millis(), HTTP_Payload.c_str()); // 打印调试信息
  }
  request->send(200, "text/plain", "OK"); // 发送接收成功标志符
}
  
void setup()
{
  // 你需要再此处添加WiFi操作代码,开启热点或者连接到热点
  // 添加HTTP主页,当访问的时候会把网页推送给访问者
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
            { request->send_P(200, "text/html", index_html); });
  // 设置反馈的信息,在HTML请求这个Ip/dht这个链接时,返回打包好的传感器数据
  server.on("/dht", HTTP_GET, [](AsyncWebServerRequest *request)
            { request->send_P(200, "text/plain", Merge_Data().c_str()); });
  server.on("/set", HTTP_GET, Config_Callback);   // 绑定配置下发的处理函数
  server.begin();  // 初始化HTTP服务器
}

有关ESP32网页控制显示数据原来如此简单的更多相关文章

  1. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. Ruby Readline 在向上箭头上使控制台崩溃 - 2

    当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby​​安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少

  4. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  5. ruby-on-rails - 带 Spring 锁的 Rails 4 控制台 - 2

    我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.

  6. ruby-on-rails - openshift 上的 rails 控制台 - 2

    我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新ruby​​gems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems

  7. ruby-on-rails - link_to 不显示任何 rails - 2

    我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article

  8. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  9. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  10. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

随机推荐