1、背景
在ESP32中存在很多的回调,并且实现的都比较优美,因此有必要在这方面向她好好学习,向代码开发者致敬。
我下面开始我的胡扯,有问题请大家指出,谢谢。
2、结构
接下去我们学习一下它的逻辑结构以及内含的面向对象的编程思想。(当然这纯属我在写的时候瞎扯的)。
以HTTP数据流为例分析,这个选择是因为目前刚好对这一段熟悉,贪方便而已。
2.1 看看句柄相关的结构体以及初始化
言归正传,看下面一段代码,首先入眼的是定义了一个esp_http_client_config_t 的变量,接下去就利用这个变量初始化HTTP客户端,且返回esp_http_client_handle_t的句柄。
esp_http_client_config_t config = {
.url = "https://www.ozizz.cn/yyz/device/1/uploadWifi",
.event_handler = SM_http_event_handler,
.is_async = true,
.buffer_size = 1536,
.timeout_ms = 5000,
};
esp_http_client_handle_t client = esp_http_client_init(&config);
在这一段中应该是最能看出代码研发者的编程技能。首先看看esp_http_client_handle_t 这个句柄的结构体的组成
/**
* HTTP client class
*/
struct esp_http_client {
int redirect_counter; //重定向次数
int max_redirection_count; //最大重定向次数
int process_again;
struct http_parser *parser; //HTTP解析器
struct http_parser_settings *parser_settings; //HTTP解析器配置
esp_transport_list_handle_t transport_list; //transport链表
esp_transport_handle_t transport; //要用的transport
esp_http_data_t *request; //请求数据
esp_http_data_t *response; //应答数据
void *user_data; //用户数据
esp_http_auth_data_t *auth_data; //认证数据
char *post_data;
char *location; //位置
char *auth_header;
char *current_header_key;
char *current_header_value;
int post_len;
connection_info_t connection_info; //连接信息
bool is_chunk_complete; //分块是否完成
esp_http_state_t state; //状态
http_event_handle_cb event_handler; //事件处理函数
int timeout_ms; //超时
int buffer_size; //buffer的大小
bool disable_auto_redirect; //除能自动重定向
esp_http_client_event_t event; //事件ID
int data_written_index;
int data_write_left;
bool first_line_prepared;
int header_index;
bool is_async; //是否阻塞
};
这些都是变量涵盖了一个HTTP/s客户端在各个阶段时所需要使用的。在实际编程中,将使用到的与客户端操作有关的函数放到这个结构体内,最终形成一个体系。
初始化函数esp_http_client_init就是针对一个结构体对其中的成员变量该分配空间的分配空间,该按配置的赋值的赋值,否则就给一个默认值。
2.2 实际中对该结构体的使用以及触发事件处理的调用
esp_err_t err;
esp_http_client_set_method(client, HTTP_METHOD_POST);
esp_http_client_set_post_field(client, data, len);
while(1)
{
err = esp_http_client_perform(client);
if (err != ESP_ERR_HTTP_EAGAIN) { //非阻塞,直接跳出
break;
}
}
事件分派函数如下所示,只要句柄的事件处理函数设置后才有效。
static esp_err_t http_dispatch_event(esp_http_client_t *client, esp_http_client_event_id_t event_id, void *data, int len)
{
esp_http_client_event_t *event = &client->event;
if (client->event_handler) {
event->event_id = event_id;
event->user_data = client->user_data;
event->data = data;
event->data_len = len;
return client->event_handler(event);
}
return ESP_OK;
}
如
http_dispatch_event(client, HTTP_EVENT_ON_DATA, (void *)at, length);
举例来说
event->event_id = HTTP_EVENT_ON_DATA;
event->user_data = client->user_data;
event->data = at;
event->data_len = length;
其中user_data追本溯源
client->user_data = config->user_data; //这是用户数据上下文
3、实践