- 物联网ESP32教程
- 首页
- 物联网简要概述
- ESP32介绍
- 在Arduino IDE中安装ESP32开发板
- 设置RTOS用于双核和多线程操作
- ESP32与MPU6050接口
- ESP32与模拟传感器接口
- ESP32参数设置
- ESP32 SPIFFS存储(芯片自带的迷你SD卡)
- ESP32与OLED显示屏接口
- ESP32上的WiFi
- 使用HTTP通过WiFi传输数据
- 使用HTTPS通过WiFi传输数据
- 使用MQTT通过WiFi传输数据
- 通过蓝牙传输数据
- 使用NTP客户端获取当前时间
- 执行ESP32固件的(OTA)更新
- ESP32的应用
- 您作为开发人员的下一步
- ESP32物联网实用资源
- 快速指南
- 实用资源
- 讨论
使用HTTP通过WiFi传输数据
HTTP(超文本传输协议)是最常见的通信形式之一,使用ESP32,我们可以使用HTTP请求与任何Web服务器交互。让我们在本节中了解如何操作。
关于HTTP请求的简要说明
HTTP请求发生在客户端和服务器之间。顾名思义,服务器根据请求向客户端“提供”信息。Web服务器通常提供网页。例如,当您在互联网浏览器中输入https://www.linkedin.com/login时,您的PC或笔记本电脑充当客户端,并向托管linkedin.com的服务器请求与/login地址对应的页面。您将收到一个HTML页面作为返回,然后由您的浏览器显示。
HTTP遵循请求-响应模型,这意味着通信始终由客户端发起。服务器不能无缘无故地与任何客户端对话,也不能与任何客户端启动通信。通信必须始终由客户端以请求的形式发起,服务器只能响应该请求。服务器的响应包含状态代码(记得404吗?这是一个状态代码),以及(如果适用)请求的内容。所有状态代码的列表可以在这里找到 这里。
那么,服务器如何识别HTTP请求呢?通过请求的结构。HTTP请求遵循一个固定的结构,该结构包含三个部分
请求行后跟回车换行符(CRLF = \r\n)
零个或多个标题行,后跟CRLF和一个空行,再次后跟CRLF
可选正文
典型的HTTP请求如下所示
POST / HTTP/1.1 //Request line, containing request method (POST in this case)
Host: www.example.com //Headers
//Empty line between headers
key1=value1&key2=value2 //Body
服务器响应如下所示:
HTTP/1.1 200 OK //Response line; 200 is the status code
Date: Mon, 23 May 2005 22:38:34 GMT //Headers
Content-Type: text/html; charset=UTF-8
Content-Length: 155
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
ETag: "3f80f−1b6−3e1cb03b"
Accept-Ranges: bytes
Connection: close
//Empty line between headers and body
<html>
<head>
<title>An Example Page</title>
</head>
<body>
<p>Hello World, this is a very simple HTML document.</p>
</body>
</html>
事实上,TutorialsPoint本身上有一个关于HTTP请求结构的非常好的教程。它还向您介绍了各种请求方法(GET、POST、PUT等)。在本节中,我们将关注GET和POST方法。
GET请求将所有参数都以请求URL中键值对的形式包含在内。例如,如果使用GET而不是POST发送上面的相同示例请求,它将如下所示:
GET /test/demo_form.php?key1=value1&key2=value2 HTTP/1.1 //Request line
Host: www.example.com //Headers
//No need for a body
POST请求(正如您现在可能已经猜到的那样)将参数包含在正文中,而不是URL中。GET和POST之间还有其他一些区别,您可以在这里阅读。但关键是,您将使用POST与服务器共享敏感信息,例如密码。
代码演练
在本节中,我们将从头开始编写我们的HTTP请求。有一些库(如httpClient)专门用于处理ESP32 HTTP请求,这些库负责构建HTTP请求,但我们将自己构建请求。这给我们带来了更大的灵活性。在本教程中,我们将限制使用ESP32客户端模式。ESP32也可以使用HTTP服务器模式,但这留给您去探索。
我们将使用httpbin.org作为我们的服务器。它基本上是为测试您的HTTP请求而构建的。您可以使用此服务器测试GET、POST和各种其他方法。参见 这里。
代码可以在 GitHub 上找到
我们首先包含WiFi库。
#include <WiFi.h>
接下来,我们将定义一些常量。对于HTTP,使用的端口是80。这是标准的。类似地,我们对HTTPS使用443,对FTP使用21,对DNS使用53,等等。这些是保留的端口号。
const char* ssid = "YOUR_SSID"; const char* password = "YOUR_PASSWORD"; const char* server = "httpbin.org"; const int port = 80;
最后,我们创建我们的WiFiClient对象。
WiFiClient client
在setup中,我们只需使用提供的凭据以station模式连接到WiFi。
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA); //The WiFi is in station mode. The other is the softAP mode
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(""); Serial.print("WiFi connected to: "); Serial.println(ssid); Serial.println("IP address: "); Serial.println(WiFi.localIP());
delay(2000);
}
loop在这里变得很重要。HTTP请求就在那里执行。我们首先读取ESP32的芯片ID。我们将把它作为参数与我们的姓名一起发送给服务器。我们将使用这些参数构建HTTP请求的主体。
void loop() {
int conn;
int chip_id = ESP.getEfuseMac();;
Serial.printf(" Flash Chip id = %08X\t", chip_id);
Serial.println();
Serial.println();
String body = "ChipId=" + String(chip_id) + "&SentBy=" + "your_name";
int body_len = body.length();
注意SentBy字段之前的&。&在HTTP请求中用作不同键值对的分隔符。接下来,我们连接到服务器。
Serial.println(".....");
Serial.println(); Serial.print("For sending parameters, connecting to "); Serial.println(server);
conn = client.connect(server, port);
POST请求
如果我们的连接成功,client.connect()将返回1。我们在发出请求之前检查这一点。
if (conn == 1) {
Serial.println(); Serial.print("Sending Parameters...");
//Request
client.println("POST /post HTTP/1.1");
//Headers
client.print("Host: "); client.println(server);
client.println("Content-Type: application/x−www−form−urlencoded");
client.print("Content-Length: "); client.println(body_len);
client.println("Connection: Close");
client.println();
//Body
client.println(body);
client.println();
//Wait for server response
while (client.available() == 0);
//Print Server Response
while (client.available()) {
char c = client.read();
Serial.write(c);
}
} else {
client.stop();
Serial.println("Connection Failed");
}
如您所见,我们使用client.print()或client.println()发送我们的请求行。请求、标头和正文通过注释清楚地表明。在请求行中,POST /post HTTP/1.1等效于POST http://httpbin.org/post HTTP/1.1。由于我们已经在client.connect(server,port)中提到了服务器,因此/post指的是服务器/post URL。
特别是对于POST请求,Content-Length标头非常重要。如果没有它,许多服务器会假设内容长度为0,这意味着没有正文。Content-Type已保留为application/x−www−form−urlencoded,因为我们的正文表示表单数据。在典型的表单提交中,您将拥有像Name、Address等键以及相应的值。您可以拥有其他几种内容类型。有关完整列表,请参阅 这里。
Connection: Close标头告诉服务器在处理请求后关闭连接。如果您希望在请求处理后保持连接,则可以替代地发送Connection: Keep-Alive。
这些只是我们可以包含的一些标头。HTTP标头的完整列表可以在 这里 找到。
现在,httpbin.org/post URL通常只是回显我们的正文。一个示例响应如下所示:
HTTP/1.1 200 OK
Date: Sat, 21 Nov 2020 16:25:47 GMT
Content−Type: application/json
Content−Length: 402
Connection: close
Server: gunicorn/19.9.0
Access−Control−Allow−Origin: *
Access−Control−Allow−Credentials: true
{
"args": {},
"data": "",
"files": {},
"form": {
"ChipId": "1780326616",
"SentBy": "Yash"
},
"headers": {
"Content−Length": "34",
"Content−Type": "application/x−www−form−urlencoded",
"Host": "httpbin.org",
"X-Amzn−Trace−Id": "Root=1−5fb93f8b−574bfb57002c108a1d7958bb"
},
"json": null,
"origin": "183.87.63.113",
"url": "http://httpbin.org/post"
}
如您所见,“form”字段中回显了POST正文的内容。您应该在串口监视器上看到类似于上面的内容。另请注意URL字段。它清楚地表明请求行中的/post地址被解释为http://httpbin.org/post。
最后,我们将等待5秒钟,然后结束循环,从而再次发出请求。
delay(5000); }
GET请求
此时,您可能想知道,将此POST请求转换为GET请求需要进行哪些更改。实际上,这很简单。首先,您将调用/get地址而不是/post。然后,您将在问号(?)后将正文的内容附加到URL。最后,您将方法替换为GET。此外,不再需要Content-Length和Content−Type标头,因为您的正文为空。因此,您的请求块将如下所示:
if (conn == 1) {
String path = String("/get") + String("?") +body;
Serial.println(); Serial.print("Sending Parameters...");
//Request
client.println("GET "+path+" HTTP/1.1");
//Headers
client.print("Host: "); client.println(server);
client.println("Connection: Close");
client.println();
//No Body
//Wait for server response
while (client.available() == 0);
//Print Server Response
while (client.available()) {
char c = client.read();
Serial.write(c);
}
} else {
client.stop();
Serial.println("Connection Failed");
}
相应的响应将如下所示:
HTTP/1.1 200 OK
Date: Tue, 17 Nov 2020 18:05:34 GMT
Content-Type: application/json
Content-Length: 497
Connection: close
Server: gunicorn/19.9.0
Access-Control−Allow−Origin: *
Access-Control-Allow-Credentials: true
{
"args": {
"ChipID": "3F:A0:A1:77:0D:84",
"SentBy": "Yash"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "deflate, gzip",
"Host": "httpbin.org",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36",
"X−Amzn−Trace−Id": "Root=1−5fb410ee−3630963b0b7980c959c34038"
},
"origin": "206.189.180.4",
"url": "https://httpbin.org/get?ChipID=3F:A0:A1:77:0D:84&SentBy=Yash"
}
如您所见,发送到服务器的参数现在返回在args字段中,因为它们作为URL中的参数发送。
恭喜!!您已成功使用ESP32发送HTTP请求。