ESP-C3入门11. 创建最基本的HTTP请求
- 一、menuconfig配置
- 二、配置 CMakeLists
- 1. 设置项目的额外组件目录
- 2. 设置头文件搜索目录
- 三、在 ESP32 上执行 HTTP 请求的基本步骤
- 1. 创建 TCP 连接
- 2. 设置 HTTP 请求
- 3. 发送 HTTP 请求
- 4. 接收 HTTP 响应
- 5. 处理 HTTP 响应
- 6. 关闭 TCP 连接
- 三、示例
- 1. http_request.h
- 2. http_request.c
- http_request_send
- esp_http_client_config_t 结构体
- esp_http_client_init() 函数
- esp_http_client_perform() 函数
- esp_http_client_cleanup() 函数
官网文档:
https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/protocols/esp_http_client.html
一、menuconfig配置
打开ESP-IDF 4.4 CMD命令窗口,进入项目,运行: idf.py menuconfig
,打开配置窗口:
选择 Component config- ESP HTTP client菜单:
钩选:
保存设置到自己项目:
二、配置 CMakeLists
1. 设置项目的额外组件目录
# 设置项目的额外组件目录,允许使用ESP-IDF示例中的公共组件。
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/components)
2. 设置头文件搜索目录
CMakeLists.h 中要包含 esp_http_client的头文件位置:
# 设置项目的包含目录,这些是要搜索头文件的目录
set(INCLUDE_DIRS
${INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}
${IDF_PATH}/components/esp_http_client/include
)
include_directories(${INCLUDE_DIRS})
这样就能使用 esp_http_client
了。
三、在 ESP32 上执行 HTTP 请求的基本步骤
在 ESP32 上进行 HTTP 请求需要使用 TCP/IP 套接字和 HTTP 库来实现。
ESP32 IDF的esp_http_client 库提供了一组易于使用的 API,可以自动处理 HTTP 头和响应内容。
1. 创建 TCP 连接
使用 tcpip_adapter 和 lwip 库创建一个 TCP 连接。可以使用 lwip 库提供的函数(如 tcp_new() 和 tcp_connect())来创建和连接套接字。
2. 设置 HTTP 请求
使用 HTTP 协议创建一个请求消息。请求消息包括 HTTP 方法(如 GET、POST 等)和请求的 URL,以及一些 HTTP 头部(如 Content-Type、Content-Length 等)和负载数据(如果有的话)。
3. 发送 HTTP 请求
使用 lwip 库提供的 tcp_write() 函数将请求消息发送到服务器。
4. 接收 HTTP 响应
使用 lwip 库提供的 tcp_recv() 函数从服务器接收响应消息。通常,响应消息由一个或多个 TCP 数据包组成,因此需要在接收数据时进行缓冲区处理。
5. 处理 HTTP 响应
对响应消息进行处理,例如解析响应头、解码响应正文、处理错误码等。
6. 关闭 TCP 连接
使用 lwip 库提供的 tcp_close() 函数关闭 TCP 连接。
三、示例
1. http_request.h
#ifndef HTTP_REQUEST_H
#define HTTP_REQUEST_H
#include "esp_http_client.h"
#define HTTP_URL "http://www.example.com"
esp_err_t http_event_handler(esp_http_client_event_t *evt);
void request(const char* url);
#endif
2. http_request.c
#include <esp_err.h>
#include <esp_log.h>
#include "network/include/http_request.h"
static const char *TAG = "HTTP_REQUEST";
#define MAX_HTTP_OUTPUT_BUFFER 2048
// HTTP 请求的处理函数
esp_err_t http_event_handler(esp_http_client_event_t *evt)
{
// 缓存http响应的buffer
static char *output_buffer;
// 已经读取的字节数
static int output_len;
switch(evt->event_id) {
case HTTP_EVENT_ERROR:
ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
break;
case HTTP_EVENT_ON_CONNECTED:
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
break;
case HTTP_EVENT_HEADER_SENT:
ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
break;
case HTTP_EVENT_ON_HEADER:
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
break;
case HTTP_EVENT_ON_DATA:
ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
if (!esp_http_client_is_chunked_response(evt->client)) {
// 如果配置了user_data buffer,则把响应复制到该buffer中
if (evt->user_data) {
memcpy(evt->user_data + output_len, evt->data, evt->data_len);
} else {
if (output_buffer == NULL) {
output_buffer = (char *) malloc(esp_http_client_get_content_length(evt->client));
output_len = 0;
if (output_buffer == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory for output buffer");
return ESP_FAIL;
}
}
memcpy(output_buffer + output_len, evt->data, evt->data_len);
}
output_len += evt->data_len;
}
break;
case HTTP_EVENT_ON_FINISH:
ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
if (output_buffer != NULL) {
// Response is accumulated in output_buffer. Uncomment the below line to print the accumulated response
// ESP_LOG_BUFFER_HEX(TAG, output_buffer, output_len);
free(output_buffer);
output_buffer = NULL;
}
output_len = 0;
break;
case HTTP_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
if (output_buffer != NULL) {
free(output_buffer);
output_buffer = NULL;
}
output_len = 0;
break;
}
return ESP_OK;
}
void request(const char *url) {
// 响应结果放在这里
char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};
// 创建一个 HTTP 客户端配置
esp_http_client_config_t config = {
.method = HTTP_METHOD_GET,
.url = url,
.event_handler = http_event_handler,
.user_data = local_response_buffer,
.disable_auto_redirect = true,
};
// 创建一个 HTTP 客户端并执行 GET 请求
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_err_t err = esp_http_client_perform(client);
// 检查请求是否成功
if (err == ESP_OK) {
int len = esp_http_client_get_content_length(client);
ESP_LOGI(TAG, "Status = %d, content_length = %d",
esp_http_client_get_status_code(client),//状态码
len);//数据长度
} else {
printf("HTTP GET request failed: %s\n", esp_err_to_name(err));
}
printf("Response: %.*s\n", strlen(local_response_buffer), local_response_buffer);
//断开并释放资源
esp_http_client_cleanup(client);
}
主要函数说明:
http_request_send
用于发送 HTTP 请求的函数 ,该函数接受一个 http_request_t 类型的指针作为参数,其中包含了 HTTP 请求的 URL、请求方法、请求头以及 POST 数据。在
esp_http_client_config_t 结构体
用于配置 HTTP 客户端的参数,包括 URL、请求方法和事件处理函数。然后,根据请求中是否包含请求头和 POST 数据来设置 HTTP 客户端的相应参数。
esp_http_client_init() 函数
用来创建一个 HTTP 客户端句柄。
esp_http_client_perform() 函数
发送 HTTP 请求。
esp_http_client_cleanup() 函数
释放 HTTP 客户端句柄。