简介
本文旨在解释如何在ESP32开发板运行的Arduino核心上配置异步HTTP Web服务器。
本ESP32教程的测试是使用集成在ESP32 FireBeetle板中的DFRobot的ESP-WROOM-32设备进行的。
例如,我们将开发一个非常简单的“hello world”应用程序,它将向连接到它的客户端返回一条消息。作为客户端,我们将使用Web浏览器。
库
为了设置网络服务器,我们需要两个库。第一个是ESPAsyncWebServer,我们将在代码中使用到它。
该库允许设置异步HTTP(和Websocket)服务器,这意味着它可以同时处理多个连接[1]。
此外,正如我们将在代码中看到,一旦我们设置了服务器回调函数,我们就无需在主循环上定期调用任何客户端处理函数,就像我们在ESP8266HTTP网络服务器原始实现上所做的那样。
所需的第二个库是AsyncTCP,它依赖于前一个库。因此,我们不会在代码中直接与其交互,只需包含该库即可。
该库是ESP32开发板的异步TCP库,它是ESPAsyncWebServer库实现的基础[2]。当然,这是一个较低级别的库,并且使用起来更为复杂。
在撰写本文时,Arduino IDE库管理器上并没有任何库,因此我们必须从GitHub页面下载它们,并将其放在我们的Arduino库文件夹中。
如需下载这两个库,只需单击GitHub页面顶部的“克隆或下载(Clone or download)”按钮,如图1高亮显示部分所示。
图1 - 从GitHub下载库代码。
然后,选择“下载ZIP”选项,将该文件下载到您的计算机。只需打开.zip文件,并将文件夹解压缩到Arduino库文件夹即可。
通常,Arduino安装的libraries文件夹位于C:\Users\UserName\Documents\Arduino\libraries文件夹中。
请注意,解压缩的文件夹名称末尾带一个-master。只需删除此附加的-master并保留其余部分名称即可。
随后,这些库应该可以在Arduino环境中使用。此过程适用于安装两个库。
代码
对于此示例,我们需要加入一些库。首先,我们需要加入WiFi.h库,该库用于将ESP32连接到无线网络。
我们还需要包含FS.h库,它是ESP32的文件系统库。虽然我们没有在本教程中使用任何与文件系统相关的函数,但如果我们不包含它,则代码将无法编译。
最后,我们将加入两个先前安装的库,即AsyncTCP.h和ESPAsyncWebServer.h。
#include <WiFi.h>
#include <FS.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
完成这些后,我们将声明两个全局变量以保存WiFi网络凭证,方便我们以后使用其执行连接。
const char* ssid = "yourNetworkName";
const char* password = "yourNetworkPassword";
最后,我们将声明一个AsyncWebServer类型变量,我们将使用它设置我们的异步ESP32 HTTP服务器。
AsyncWebServer server(80);
作为构造函数输入,我们将传递服务器即将侦听的端口。我们将使用端口80,这是默认的HTTP端口。
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println(WiFi.localIP());
转到设置函数,我们将首先打开一个串行连接。然后,我们将使用先前声明的凭据将ESP32开发板连接到WiFi网络。如果您需要关于如何将ESP32连接到WiFi网络的详细说明,请参阅上一篇文章。
请注意,连接完成后,我们将打印分配给ESP32开发板的本地IP,以便稍后我们可以使用其向我们的服务器发出请求。
现在我们将配置服务器将侦听传入HTTP请求的路由以及在该路由上收到请求时将执行的函数。
我们通过调用服务器对象的on方法对其进行指定。作为第一个输入,此方法接收一个字符串,其中包含将要侦听的路径。我们将其设置为侦听“/hello”路由上的请求。
作为第二个参数,它接收一个类型为WebRequestMethod(此处定义)的枚举,它指定在该路由上允许哪种类型的HTTP请求。我们将定义仅接收HTTP GET请求,因此我们使用值HTTP_GET。
作为第三个参数,它接收一个函数,签名由ArRequestHandlerFunction类型定义,如这里所述。
因此,我们将指定该处理函数必须返回void,并作为参数接收指向AsyncWebServerRequest类型对象的指针。每个传入的客户端将被封装在此类对象中,并且两者都处于活动状态,直到连接断开[3]。
为了保证语法的紧凑性,我们将此处理函数声明为C++ lambda函数。因此,我们可以指定一个未命名的本地声明函数。对于包含诸多路由的服务器,这比必须针对每个路由专门声明命名函数更加清晰和紧凑。您可以在这里阅读更多关于lambda语法的内容:
[captures](params){body}
在我们的示例中,我们不会使用任何捕获,所以我们只使用空方括号[]。对于参数,我们需要尊重前面提及的处理函数定义的签名,该定义由ArRequestHandlerFunction类型指定。因此,我们的lambda将接收一个参数,该参数指向AsyncWebServerRequest类型对象的指针。
server.on("/hello", HTTP_GET, [](AsyncWebServerRequest *request){
// Lambda body implementation
});
对于我们的处理函数实现,我们希望向客户端返回一个简单的“hello world”消息。如前所述,每个客户端都与一个AsyncWebServerRequest对象相关联,该对象包含一个允许我们指定要返回的HTTP响应的send方法。
此方法接收HTTP响应代码作为第一个输入,在我们的示例中将其指定为200。这是“确定”的HTTP响应代码。
作为第二个输入,send方法接收响应回答的内容类型。我们将使用值“text / plain”,因为我们只想返回“hello world”消息。
最后,作为第三个参数,我们将传递实际内容,这将是我们的“hello world”消息。
请注意,由于我们使用的是指向对象而非对象本身指针,因此我们需要使用箭头操作符,调用AsyncWebServerRequest对象的send方法。
server.on("/hello", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/plain", "Hello World");
});
如需完成设置函数,我们需要在服务器对象上调用begin方法。此方法调用将启动服务器。
server.begin();
由于我们的服务器是异步的,因此我们无需在主循环上调用任何客户端处理函数,如前所述。因此,我们刚刚定义的路由处理函数将在接收来自客户端的请求时异步调用和执行。最终代码如下所示。
#include <WiFi.h>
#include <FS.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
const char* ssid = "yourNetworkName";
const char* password = "yourNetworkPassword";
AsyncWebServer server(80);
void setup(){
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println(WiFi.localIP());
server.on("/hello", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/plain", "Hello World");
});
server.begin();
}
void loop(){
}
测试代码
如需测试代码,只需编译它,并使用Arduino IDE将其上传到ESP32开发板。该过程完成后,打开串行监视器,并复制ESP32连接到WiFi网络后打印的IP。
然后,打开Web浏览器,并在地址栏中键入以下内容,通过刚刚复制的IP对{yourEspIp}进行更改。
http://{yourEspIp}/hello
您应该会得到一个类似于图2的输出,它显示了我们在正在打印的代码上定义的“hello world”消息。
图2 - ESP32 HTTP网络服务器hello world。
注:本文作者是Nuno Santos,他是一位和蔼可亲的电子和计算机工程师,住在葡萄牙里斯本 (Lisbon)。
他写了200多篇有关ESP32、ESP8266的有用的教程和项目。
查看更多ESP32/ESP8266教程和项目,请点击:DF创客社区 - 分享创造的喜悦
⬇原文点击