在本教程中,您将学习如何使用带有 Arduino IDE 的 ESP8266 NodeMCU 板发出 HTTP GET 和 HTTP POST 请求。我们将介绍有关如何获取值、发布 JSON 对象、URL 编码请求等的示例。
推荐:ESP32 HTTP GET 和 HTTP POST,带 Arduino IDE(JSON、URL 编码、文本)
目录
HTTP 请求方法:GET 与 POST
超文本传输协议 (HTTP) 用作客户端和服务器之间的请求-响应协议。下面是一个示例:
- ESP8266(客户端)向运行 Node-RED(服务器)的 Raspberry Pi 提交 HTTP 请求;
- 服务器向ESP8266(客户端)返回响应;
- 最后,响应包含有关请求的状态信息,也可能包含请求的内容。
HTTP 获取
GET 用于从指定资源请求数据。它通常用于从 API 获取值。
例如,您可以拥有:
GET /update-sensor?temperature=value1
请注意,查询字符串(name = temperature 和 value = value1)在 HTTP GET 请求的 URL 中发送。
或者,您可以使用简单的请求来返回值或 JSON 对象,例如:
GET /get-sensor
(使用 HTTP GET,数据对 URL 请求中的每个人都可见。
HTTP POST
POST 用于将数据发送到服务器以创建/更新资源。例如,将传感器读数发布到服务器。
使用 POST 发送到服务器的数据存储在 HTTP 请求的请求正文中:
POST /update-sensor HTTP/1.1
Host: example.com
api_key=api&sensor_name=name&temperature=value1&humidity=value2&pressure=value3
Content-Type: application/x-www-form-urlencoded
在正文请求中,还可以发送 JSON 对象:
POST /update-sensor HTTP/1.1
Host: example.com
{api_key: "api", sensor_name: "name", temperature: value1, humidity: value2, pressure: value3}
Content-Type: application/json
(使用 HTTP POST 时,数据在 URL 请求中不可见。但是,如果它未加密,它仍然在请求正文中可见。
带有ESP8266的 HTTP GET/POST
在本教程中,我们将探讨以下方案:
- ESP8266 HTTP GET:URL 中的值或查询
- ESP8266 HTTP GET:JSON 数据对象或纯文本
- ESP8266 HTTP POST:URL 编码、JSON 数据对象、纯文本
先决条件
在继续学习本教程之前,请确保完成以下先决条件。
Arduino集成开发环境
我们将使用 Arduino IDE 对 ESP8266 NodeMCU 板进行编程,因此请确保您已安装 ESP8266 插件。
Arduino_JSON库
您还需要安装 Arduino_JSON 库。您可以在 Arduino IDE 库管理器中安装此库。只需转到“程序”>“包含库”>“管理库”,然后搜索库名称,如下所示:
所需零件
在本教程中,您需要以下部分:
- ESP8266
- Raspberry Pi 板
- MicroSD 卡 – 16GB Class10
- Raspberry Pi 电源 (5V 2.5A)
- 连接线
- 面包板
准备 Node-RED(可选)
例如,我们将使用 Raspberry Pi 和 Node-RED 创建一个 Web 服务,以充当 Web 服务(如 API)。基本上,您将向 Raspberry Pi 发出 HTTP GET 和 HTTP POST 请求以获取值或更新它们。您可以使用任何其他 Web 服务。
如果您尚未安装 Node-RED,请按照以下教程操作:
- Raspberry Pi 上的 Node-RED 入门
- Node-RED Dashboard 的安装和入门
在 Raspberry Pi 上运行 Node-RED,转到 Raspberry Pi IP 地址,然后转到 :1880。
http://raspberry-pi-ip-address:1880
Node-RED 接口应打开。您可以简单地导入最终流程:
转到“导入”>菜单,并将以下内容复制到剪贴板以创建 Node-RED 流程。
[{"id":"599740b7.efde9","type":"http response","z":"b01416d3.f69f38","name":"","statusCode":"200","headers":{},"x":420,"y":689,"wires":[]},{"id":"1618a829.76f638","type":"json","z":"b01416d3.f69f38","name":"","property":"payload","action":"obj","pretty":true,"x":410,"y":809,"wires":[["d0089cc7.d25ac"]]},{"id":"c7410fa2.1c2fa","type":"debug","z":"b01416d3.f69f38","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":850,"y":709,"wires":[]},{"id":"75a22f74.f1aba","type":"ui_text","z":"b01416d3.f69f38","group":"2b7ac01b.fc984","order":1,"width":0,"height":0,"name":"","label":"Sensor Name","format":"msg.payload","layout":"row-spread","x":860,"y":769,"wires":[]},{"id":"1c8f9093.8bc2bf","type":"ui_gauge","z":"b01416d3.f69f38","name":"","group":"2b7ac01b.fc984","order":2,"width":0,"height":0,"gtype":"gage","title":"Temperature","label":"ºC","format":"value","min":0,"max":"38","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":850,"y":829,"wires":[]},{"id":"a5bd2706.54e108","type":"ui_gauge","z":"b01416d3.f69f38","name":"","group":"2b7ac01b.fc984","order":3,"width":0,"height":0,"gtype":"gage","title":"Humidity","label":"%","format":"value","min":0,"max":"100","colors":["#0080ff","#0062c4","#002f5e"],"seg1":"","seg2":"","x":840,"y":889,"wires":[]},{"id":"105ac2cc.7b3cfd","type":"ui_gauge","z":"b01416d3.f69f38","name":"","group":"2b7ac01b.fc984","order":4,"width":0,"height":0,"gtype":"gage","title":"Pressure","label":"hPa","format":"value","min":0,"max":"1200","colors":["#b366ff","#8000ff","#440088"],"seg1":"","seg2":"","x":840,"y":949,"wires":[]},{"id":"d0089cc7.d25ac","type":"function","z":"b01416d3.f69f38","name":"JSON or URL Encoded","func":"var msg0 = { payload: msg.payload.api_key };nvar msg1 = { payload: msg.payload.sensor };nvar msg2 = { payload: msg.payload.value1 };nvar msg3 = { payload: msg.payload.value2 };nvar msg4 = { payload: msg.payload.value3 };nnreturn [msg0, msg1, msg2, msg3, msg4];","outputs":5,"noerr":0,"x":610,"y":809,"wires":[["c7410fa2.1c2fa"],["75a22f74.f1aba"],["1c8f9093.8bc2bf"],["a5bd2706.54e108"],["105ac2cc.7b3cfd"]]},{"id":"5d9ab0d2.66b92","type":"http in","z":"b01416d3.f69f38","name":"","url":"update-sensor","method":"post","upload":false,"swaggerDoc":"","x":200,"y":740,"wires":[["599740b7.efde9","c7410fa2.1c2fa","1618a829.76f638"]]},{"id":"7f5cf345.63f56c","type":"http response","z":"b01416d3.f69f38","name":"","statusCode":"200","headers":{},"x":540,"y":420,"wires":[]},{"id":"6530621.95b429c","type":"http in","z":"b01416d3.f69f38","name":"","url":"/get-sensor","method":"get","upload":false,"swaggerDoc":"","x":180,"y":600,"wires":[["9471d1a0.68588"]]},{"id":"5ddc9f47.4b555","type":"http response","z":"b01416d3.f69f38","name":"","statusCode":"200","headers":{},"x":540,"y":560,"wires":[]},{"id":"9471d1a0.68588","type":"function","z":"b01416d3.f69f38","name":"","func":"msg.payload = {"value1":24.25, "value2":49.54, "value3":1005.14};nreturn msg;","outputs":1,"noerr":0,"x":350,"y":600,"wires":[["5ddc9f47.4b555","13aea59.7430e5a"]]},{"id":"13aea59.7430e5a","type":"debug","z":"b01416d3.f69f38","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":550,"y":628,"wires":[]},{"id":"e71c7a7d.e7c598","type":"debug","z":"b01416d3.f69f38","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":550,"y":500,"wires":[]},{"id":"c7807102.3f433","type":"http in","z":"b01416d3.f69f38","name":"","url":"/update-sensor","method":"get","upload":false,"swaggerDoc":"","x":190,"y":460,"wires":[["60410cde.562a34"]]},{"id":"60410cde.562a34","type":"function","z":"b01416d3.f69f38","name":"","func":"msg.payload = msg.payload.temperature;nreturn msg;","outputs":1,"noerr":0,"x":390,"y":460,"wires":[["e71c7a7d.e7c598","7f5cf345.63f56c"]]},{"id":"2b7ac01b.fc984","type":"ui_group","z":"","name":"SENSORS","tab":"99ab8dc5.f435c","disp":true,"width":"6","collapse":false},{"id":"99ab8dc5.f435c","type":"ui_tab","z":"","name":"HTTP","icon":"dashboard","order":1,"disabled":false,"hidden":false}]
其他 Web 服务或 API
在本教程中,ESP8266 对 Node-RED 执行 HTTP 请求,但您可以将这些示例与其他服务一起使用,例如 ThingSpeak、IFTTT.com(Web Hooks 服务)、OpenWeatherMap.org、PHP 服务器等……本教程中提供的所有示例也适用于其他 API。
总之,要使本教程与任何服务兼容,您需要搜索服务 API 文档。然后,您需要服务器名称(URL 或 IP 地址)和要在请求中发送的参数(URL 路径或请求正文)。最后,修改我们的示例以与您要使用的任何 API 集成。
1. ESP8266 HTTP GET:URL 中的值或查询
在第一个示例中,ESP8266将发出 HTTP GET 请求以更新服务中的读数。这种类型的请求还可用于筛选值、请求值或返回 JSON 对象。
使用 Arduino IDE ESP8266 HTTP GET 的代码
安装必要的板附加组件和库后,将以下代码复制到 Arduino IDE,但不要上传。您需要进行一些更改才能使其适合您。
/*
更多Arduino/ESP8266/ESP32等教程请访问: https://www.qutaojiao.com
(see in Tools > Boards > Boards Manager > ESP8266)
*/
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
//Your Domain name with URL path or IP address with path
String serverName = "http://192.168.1.106:1880/update-sensor";
// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastTime = 0;
// Timer set to 10 minutes (600000)
//unsigned long timerDelay = 600000;
// Set timer to 5 seconds (5000)
unsigned long timerDelay = 5000;
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("Connecting");
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());
Serial.println("Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading.");
}
void loop() {
// Send an HTTP POST request depending on timerDelay
if ((millis() - lastTime) > timerDelay) {
//Check WiFi connection status
if(WiFi.status()== WL_CONNECTED){
WiFiClient client;
HTTPClient http;
String serverPath = serverName + "?temperature=24.37";
// Your Domain name with URL path or IP address with path
http.begin(client, serverPath.c_str());
// If you need Node-RED/server authentication, insert user and password below
//http.setAuthorization("REPLACE_WITH_SERVER_USERNAME", "REPLACE_WITH_SERVER_PASSWORD");
// Send HTTP GET request
int httpResponseCode = http.GET();
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
String payload = http.getString();
Serial.println(payload);
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// Free resources
http.end();
}
else {
Serial.println("WiFi Disconnected");
}
lastTime = millis();
}
}
设置网络凭据
使用您的网络凭据修改下一行:SSID 和密码。该代码对您应该在何处进行更改进行了很好的注释。
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
设置 serverName
您还需要键入您的域名或 Node-RED IP 地址,以便 ESP 将读数发布到您自己的服务器。
String serverName = "http://192.168.1.106:1880/update-sensor";
现在,将代码上传到您的开发板,它应该可以立即工作。
如果您想了解如何发出 HTTP GET 请求,请阅读下一节。
HTTP GET 请求
在 loop() 中,您实际上每 5 秒使用示例数据发出一次 HTTP GET 请求:
String serverPath = serverName + "?temperature=24.37";
// Your Domain name with URL path or IP address with path
http.begin(client, serverPath.c_str());
// If you need Node-RED/server authentication, insert user and password below
//http.setAuthorization("REPLACE_WITH_SERVER_USERNAME", "REPLACE_WITH_SERVER_PASSWORD");
// Send HTTP GET request
int httpResponseCode = http.GET();
注意:如果 Node-RED 需要身份验证,请取消注释以下行并插入 Node-RED 用户名和密码。
// If you need Node-RED/server authentication, insert user and password below
//http.setAuthorization("REPLACE_WITH_SERVER_USERNAME", "REPLACE_WITH_SERVER_PASSWORD");
ESP8266在以下 URL 中发出新请求,以使用新温度更新传感器字段。
http://192.168.1.106:1880/update-sensor?temperature=24.37
然后,以下代码行保存来自服务器的 HTTP 响应。
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
String payload = http.getString();
Serial.println(payload);
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
示范
在开发板运行新程序的情况下,打开 Node-RED 调试窗口。您将看到示例值已成功打印 (24.37)。
2. ESP8266 HTTP GET:JSON 数据对象或纯文本
下一个示例演示如何发出 HTTP GET 请求以获取 JSON 对象并使用 ESP8266对其进行解码。许多 API 以 JSON 格式返回数据。
将下一个程序复制到Arduino IDE(键入SSID和密码):
设置 serverName
输入您的域名或 Node-RED IP 地址,以便 ESP 请求将在 JSON 对象中检索的传感器读数。
String serverName = "http://192.168.1.106:1880/get-sensor";
现在,将代码上传到您的看板。
HTTP GET 请求(JSON 对象)
在 loop() 中,调用 httpGETRequest() 函数以发出 HTTP GET 请求:
sensorReadings = httpGETRequest(serverName);
httpGETRequest() 函数向 Node-RED 地址 http://192.168.1.106:1880/get-sensor 发出请求,并检索带有 JSON 对象的字符串。
String httpGETRequest(const char* serverName) {
WiFiClient client;
HTTPClient http;
// Your IP address with path or Domain name with URL path
http.begin(client, serverName);
// If you need Node-RED/server authentication, insert user and password below
//http.setAuthorization("REPLACE_WITH_SERVER_USERNAME", "REPLACE_WITH_SERVER_PASSWORD");
// Send HTTP POST request
int httpResponseCode = http.GET();
String payload = "{}";
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
payload = http.getString();
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// Free resources
http.end();
return payload;
}
注意:如果 Node-RED 需要身份验证,请取消注释以下行并插入 Node-RED 用户名和密码。
// If you need Node-RED/server authentication, insert user and password below
//http.setAuthorization("REPLACE_WITH_SERVER_USERNAME", "REPLACE_WITH_SERVER_PASSWORD");
解码 JSON 对象
若要访问这些值,请解码 JSON 对象并将所有值存储在 sensorReadingsArr 数组中。
JSONVar myObject = JSON.parse(sensorReadings);
// JSON.typeof(jsonVar) can be used to get the type of the var
if (JSON.typeof(myObject) == "undefined") {
Serial.println("Parsing input failed!");
return;
}
Serial.print("JSON object = ");
Serial.println(myObject);
// myObject.keys() can be used to get an array of all the keys in the object
JSONVar keys = myObject.keys();
for (int i = 0; i < keys.length(); i++) {
JSONVar value = myObject[keys[i]];
Serial.print(keys[i]);
Serial.print(" = ");
Serial.println(value);
sensorReadingsArr[i] = double(value);
}
Serial.print("1 = ");
Serial.println(sensorReadingsArr[0]);
Serial.print("2 = ");
Serial.println(sensorReadingsArr[1]);
Serial.print("3 = ");
Serial.println(sensorReadingsArr[2]);
HTTP GET 演示
上传代码后,打开 Arduino IDE,您将看到它正在接收以下 JSON 数据:
{"value1":24.25,"value2":49.54,"value3":1005.14}
然后,在 Arduino IDE 串行监视器中打印解码的 JSON 对象。
出于调试目的,请求的信息也会打印在 Node-RED 调试窗口中。
3. ESP8266 HTTP POST:URL 编码、JSON 数据对象、纯文本
最后,您将学习如何使用ESP8266发出 HTTP POST 请求。
在此示例中,ESP8266可以使用三种不同类型的正文请求发出 HTTP POST 请求:URL 编码、JSON 对象或纯文本。这些是最常见的方法,应与大多数 API 或 Web 服务集成。
将下一个程序复制到Arduino IDE(键入SSID和密码):
设置 serverName
输入您的域名或 Node-RED IP 地址,以便 ESP 发布示例传感器读数。
String serverName = "http://192.168.1.106:1880/update-sensor";
现在,将代码上传到您的看板。
HTTP POST URL 编码
发出 URL 编码类型的 HTTP POST 请求,如下所示
POST /update-sensor HTTP/1.1
Host: 192.168.1.106:1880
api_key=tPmAT5Ab3j7F9&sensor=BME280&value1=24.25&value2=49.54&value3=1005.14
Content-Type: application/x-www-form-urlencoded
您需要在Arduino代码中运行以下内容:
// Your Domain name with URL path or IP address with path
http.begin(client, serverName);
// If you need Node-RED/server authentication, insert user and password below
//http.setAuthorization("REPLACE_WITH_SERVER_USERNAME", "REPLACE_WITH_SERVER_PASSWORD");
// Specify content-type header
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
// Data to send with HTTP POST
String httpRequestData = "api_key=tPmAT5Ab3j7F9&sensor=BME280&value1=24.25&value2=49.54&value3=1005.14";
// Send HTTP POST request
int httpResponseCode = http.POST(httpRequestData);
注意:如果 Node-RED 需要身份验证,请取消注释以下行并插入 Node-RED 用户名和密码。
// If you need Node-RED/server authentication, insert user and password below
//http.setAuthorization("REPLACE_WITH_SERVER_USERNAME", "REPLACE_WITH_SERVER_PASSWORD");
HTTP POST JSON 对象
或者,如果您更喜欢使用 JSON 对象发出 HTTP POST 请求:
POST /update-sensor HTTP/1.1
Host: example.com
{api_key: "tPmAT5Ab3j7F9", sensor_name: "BME280", temperature: 24.25; humidity: 49.54; pressure: 1005.14}
Content-Type: application/json
使用下一个代码片段:
http.addHeader("Content-Type", "application/json");
int httpResponseCode = http.POST("{"api_key":"tPmAT5Ab3j7F9","sensor":"BME280","value1":"24.25","value2":"49.54","value3":"1005.14"}");
HTTP 纯文本
如果要发送纯文本或值,请使用以下命令:
http.addHeader("Content-Type", "text/plain");
int httpResponseCode = http.POST("Hello, World!");
注意:我们使用的 Node-RED 流程(Web 服务)未设置为接收纯文本,但如果您计划集成的 API 仅接受纯文本或值,则可以使用前面的代码段。
HTTP POST 演示
在 Node-RED 调试窗口中,您可以查看 ESP 每 5 秒发出一次 HTTP POST 请求。
在此示例中,这些值也会发送到 3 个仪表,并显示在 Node-RED 仪表板中:
http://raspberry-pi-ip-address:1880/ui
总结
在本教程中,你学习了如何使用 HTTP GET 和 HTTP POST 请求将 ESP8266 与联机服务集成。
HTTP GET 和 HTTP POST 通常用于大多数 Web 服务和 API。这些在您的项目中很有用:将您的传感器读数发布到 IFTTT、ThingSpeak 等 Web 服务;到 ESP8266 或 Raspberry Pi Web 服务器或您自己的服务器;从 Internet 或数据库请求数据,等等。