跳到主要内容

【HTTP】获取网络请求

本节实例我们将学习如何使用 ESP32 获取网络请求

实验原理

ESP32 支持 2.4G 网络,那我们可以通过发送 HTTP 请求来获取实时天气数据。一般来说,天气数据是由一些公共 API 接口提供的,这些接口需要向它们发送 HTTP 请求以获取数据

HTTP 请求与 API

当我们在浏览器中输入网址或者使用应用程序时,我们实际上是向服务器发出请求。HTTP 请求是客户端(如浏览器)与服务器之间通信的方式,用于获取或发送 Web 资源。 这些资源可以是文本文件、图像、脚本等,客户端通过 HTTP 协议发起请求,服务器返回相应的响应

HTTP 请求通常由以下几个部分组成:

请求行:包含请求方法、请求 ULR 和 HTTP 协议版本,例如

GET https://www.baidu.com/content-search.xml HTTP/1.1

GET 是请求方法,https://www.baidu com/ 是 URL 地址,HTTP/1.1 指定了协议版本

HTTP 协议版本一般都是 HTTP/1.1,URL 是你要访问的地址,而请求方法除了 GET 还有 POST、PUT、DELETE 经常使用的 4 个请求方式,以及一些其他的请求方法

请求头:包含与请求相关的信息,例如浏览器类型、请求时间等

请求体:包含请求所需的数据

我们虽然可以对任意网址发送网络请求,但是这样毫无意义,比如,我想要获取某个地区的天气状况,就需要调用相对应的接口,也就是 API

API(Application Programming Interface)是指应用程序编程接口,它定义了应用程序之间进行通信的方式和规范。 API 允许不同的应用程序之间进行数据交换,使得应用程序可以共享资源和信息,从而提高应用程序的效率和可用性

API 通常使用 HTTP 请求来提供服务,客户端通过发送 HTTP 请求访问 API,服务器则通过 HTTP 响应返回所需的数据。API 可以提供许多不同的服务,例如访问数据库、获取实时数据、处理图像等

当我们使用别人提供的 API 的时候就需要遵守别人制定的规则,使用对应的链接、请求方法等等,我们需要查看 API 文档来获取这些信息。比如,我们今天使用聚合数据的 API 接口

1

总之,HTTP 请求是客户端与服务器之间通信的方式,API 则是应用程序之间通信的方式。通过 HTTP 请求访问 API,我们可以实现不同应用程序之间的数据交换和共享

JSON数据

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,常用于 Web 应用程序之间的数据传输。它是一种文本格式,易于阅读和编写,并且可以被各种编程语言支持

JSON 数据由键值对组成,其中键是字符串,值可以是字符串、数字、布尔值、数组、对象等数据类型。一个基本的 JSON 对象看起来像这样:

{
"name": "罗大富",
"age": 29,
"isStudent": false,
"hobbies": ["睡觉", "打游戏"],
"address": {
"city": "菏泽",
"state": "山东"
}
}

其中,nameageisStudenthobbiesaddress 都是键,而对应的值分别是字符串 "罗大富"、数字 29、布尔值 false、 字符串数组 ["睡觉", "打游戏"] 和一个嵌套的 JSON 对象 {"city": "菏泽", "state": "山东"}

JSON 数据通常用于 Web 应用程序中,例如从后端服务器获取数据或向后端服务器发送数据。在前端 JavaScript 中, 可以使用内置的 JSON 对象将 JSON 字符串转换为 JavaScript 对象,或将 JavaScript 对象转换为 JSON 字符串

软件程序设计

想要发送 HTTP 请求,我们就需要用到 HTTPClient

HTTPClient 库是一个用于 Arduino 的 HTTP 客户端库,它提供了一组函数来轻松地发送 HTTP 请求并处理服务器响应。HTTPClient 库基于 ESP-IDF 的 HTTP 客户端实现,并在 Arduino 框架下进行了封装,使其易于使用。

以下是 HTTPClient 库的一些常用功能和函数:

  • HTTPClient http;:创建 HTTPClient 对象
  • http.begin(url):指定要发送请求的 URL
  • http.addHeader(name, value):添加 HTTP 头部
  • http.setAuthorization(username, password):设置 HTTP 基本身份验证的用户名和密码
  • http.setTimeout(timeout):设置请求超时时间(以毫秒为单位)
  • http.GET():发送 GET 请求,并返回一个 HTTP 状态码
  • http.POST(payload):发送 POST 请求,并将 payload 作为请求正文
  • http.responseStatusCode():获取响应的状态码
  • http.responseHeaders():获取响应的头部
  • http.responseBody():获取响应的正文
  • http.getString():获取响应正文作为字符串
  • http.getStream():获取响应正文作为流对象
  • http.end():关闭连接并释放资源

我们从 Web 服务获取的是 JSON 数据,要想解析 JSON 数据,可以使用 Arduino 的 ArduinoJSON 库。ArduinoJSON 库使您能够解析和生成 JSON 数据,以及在 Arduino 上处理 JSON 格式的数据

下面是使用 ArduinoJSON 库解析 JSON 数据的基本步骤:

1️⃣ 引入 ArduinoJson.h 头文件

2️⃣ 创建一个 DynamicJsonDocument 对象来存储和处理 JSON 数据

DynamicJsonDocument doc(1024);  // 指定 JSON 文档的大小

3️⃣ 使用 deserializeJson() 函数将 JSON 数据解析到 DynamicJsonDocument 对象中:

deserializeJson(doc, json);
  • doc:DynamicJsonDocument 对象,用于存储解析后的 JSON 数据
  • json:包含 JSON 数据的字符串或字符数组

4️⃣ 通过使用 .as<type>() 方法从解析后的 JSON 文档中获取值:

int value = doc["key"].as<int>();
  • key:JSON 对象的键
  • as<type>():将值转换为指定的类型,例如 int、float、String 等

因此,我们的获取实时天气网络数据的代码可以这么写:

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char* ssid = "GeeksMan";
const char* password = "123456qq.";

// 定义
String url = "http://apis.juhe.cn/simpleWeather/query";
String city = "城市名";
String key = "你的请求Key";

void setup() {
Serial.begin(9600);

// 连接 WiFi
WiFi.begin(ssid, password);

Serial.print("正在连接 Wi-Fi");

// 检测是否连接成功
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

Serial.println("连接成功");
Serial.print("IP 地址:");
Serial.println(WiFi.localIP());

// 创建 HTTPClient 对象
HTTPClient http;

// 发送GET请求
http.begin(url+"?city="+city+"&key="+key);

int httpCode = http.GET();

// 获取响应状态码
Serial.printf("HTTP 状态码: %d", httpCode);

// 获取响应正文
String response = http.getString();
Serial.println("响应数据");
Serial.println(response);

http.end();

// 创建 DynamicJsonDocument 对象
DynamicJsonDocument doc(1024);

// 解析 JSON 数据
deserializeJson(doc, response);

// 从解析后的 JSON 文档中获取值
unsigned int temp = doc["result"]["realtime"]["temperature"].as<unsigned int>();
String info = doc["result"]["realtime"]["info"].as<String>();
int aqi = doc["result"]["realtime"]["aqi"].as<int>();

Serial.printf("温度: %d\n", temp);
Serial.printf("天气: %s\n", info);
Serial.printf("空气指数: %d\n", aqi);

}


void loop() {

}