ESP32 IDF开发 应用篇⑱ esp_http_client实例分析


别迷路-导航栏
快速导航找到你想要的(文章目录)

此篇文章如果对你有用,请点赞收藏,您的支持就是博主坚持的动力。

1、博主写这篇技术文章的目的:

(1)、esp_http_client api的使用方法;

2、概述

在上一篇已经介绍了http的基本概念,这章主要介绍esp_http_client.c文件中封装好的api函数的使用。

3、esp_http_client相关API的介绍

这里介绍大部分esp_http_client库的使用更详细的请参考:更多API 参考esp-idf\components\esp_http_client\include\esp_http_client.h

(1)、esp_http_client的初始化
先来看看初始化API

/**
  * @brief 启动HTTP会话
  *此函数必须是第一个要调用的函数,它返回一个esp_http_client_handle_t,您必须将其用作接口中其他函数的输入。
  *操作完成后,此调用必须对esp_http_client_cleanup进行相应的调用。
  * @param [in] config配置,请参见`http_client_config_t`
  * @return
  *-`esp_http_client_handle_t`
  *-如果有任何错误,则为NULL
  */
esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *config);

再来解说初始化的内容有哪些
为结构体esp_http_client_config_t的参数分配内存,初始化数据

esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *config)
{

    _success = (
                   (client                         = calloc(1, sizeof(esp_http_client_t)))           &&
                   (client->parser                 = calloc(1, sizeof(struct http_parser)))          &&
                   (client->parser_settings        = calloc(1, sizeof(struct http_parser_settings))) &&
                   (client->auth_data              = calloc(1, sizeof(esp_http_auth_data_t)))        &&
                   (client->request                = calloc(1, sizeof(esp_http_data_t)))             &&
                   (client->request->headers       = http_header_init())                             &&
                   (client->request->buffer        = calloc(1, sizeof(esp_http_buffer_t)))           &&
                   (client->response               = calloc(1, sizeof(esp_http_data_t)))             &&
                   (client->response->headers      = http_header_init())                             &&
                   (client->response->buffer       = calloc(1, sizeof(esp_http_buffer_t)))
               );
			。。。。。
    _success = (
                   (client->transport_list = esp_transport_list_init()) &&
                   (tcp = esp_transport_tcp_init()) &&
                   (esp_transport_set_default_port(tcp, DEFAULT_HTTP_PORT) == ESP_OK) &&
                   (esp_transport_list_add(client->transport_list, tcp, "http") == ESP_OK)
}

在esp_transport_tcp_init中注册了tcp的回调函数

tcp_connect, tcp_read, tcp_write, tcp_close, tcp_poll_read, tcp_poll_write, tcp_destroy
esp_transport_handle_t esp_transport_tcp_init(void)
{
esp_transport_set_func(t, tcp_connect, tcp_read, tcp_write, tcp_close, tcp_poll_read, tcp_poll_write, tcp_destroy);
}

(2)、设置url连接API

/**
  * @brief 为客户端设置URL,执行此行为时,URL中的选项将替换旧的
  *
  * @param [in]客户端esp_http_client句柄
  * @param [in] url URL
  *
  * @return
  *-ESP_OK
  *-ESP_FAIL
  */
esp_err_t esp_http_client_set_url(esp_http_client_handle_t client, const char *url);

解析esp_http_client_set_url主要是对对client->connection_info结构体的操作,将url分解到connection_info各个参数中
结构体connection_info_t

typedef struct {
    char                         *url;
    char                         *scheme;
    char                         *host;
    int                          port;
    char                         *username;
    char                         *password;
    char                         *path;
    char                         *query;
    char                         *cert_pem;
    esp_http_client_method_t     method;
    esp_http_client_auth_type_t  auth_type;
    esp_http_client_transport_t  transport_type;
    int                          max_store_header_size;
} connection_info_t;

(3)、设置请求方法

/**
  * @brief设置http请求方法
  *
  * @param [in]客户端esp_http_client句柄
  * @param [in]方法方法
  *
  * @return
  *-ESP_OK
  *-ESP_ERR_INVALID_ARG
  */
esp_err_t esp_http_client_set_method(esp_http_client_handle_t client, esp_http_client_method_t method);
请求方法:
/**
 * @brief HTTP method
 */
typedef enum {
    HTTP_METHOD_GET = 0,    /*!< HTTP GET Method */
    HTTP_METHOD_POST,       /*!< HTTP POST Method */
    HTTP_METHOD_PUT,        /*!< HTTP PUT Method */
    HTTP_METHOD_PATCH,      /*!< HTTP PATCH Method */
    HTTP_METHOD_DELETE,     /*!< HTTP DELETE Method */
    HTTP_METHOD_HEAD,       /*!< HTTP HEAD Method */
    HTTP_METHOD_NOTIFY,     /*!< HTTP NOTIFY Method */
    HTTP_METHOD_SUBSCRIBE,  /*!< HTTP SUBSCRIBE Method */
    HTTP_METHOD_UNSUBSCRIBE,/*!< HTTP UNSUBSCRIBE Method */
    HTTP_METHOD_OPTIONS,    /*!< HTTP OPTIONS Method */
    HTTP_METHOD_MAX,
} esp_http_client_method_t;

(4)、设置post数据

/**
  * @brief设置发布数据,必须在`esp_http_client_perform`之前调用此函数。
  *注意:传递给此函数的data参数是一个指针,该函数不会复制数据
  *
  * @param [in]客户端esp_http_client句柄
  * @param [in]数据发布数据指针
  * @param [in] len帖子长度
  *
  * @return
  *-ESP_OK
  *-ESP_FAIL
  */
esp_err_t esp_http_client_set_post_field(esp_http_client_handle_t client, const char *data, int len);

(5)、esp_http_perform获得请求,完成TCP发送和接收

/*
 esp_http_client_perform以阻塞或非阻塞方式执行整个请求。
默认情况下,API以阻塞方式执行请求,并在完成后返回,
*/
esp_err_t esp_http_client_perform(esp_http_client_handle_t client);
/**
  * @brief 此函数将打开连接,写入所有标头字符串并返回
  *
  * @param [in]客户端esp_http_client句柄
  * @param [in] write_len HTTP内容长度需要写入服务器
  *
  * @return
  *-ESP_OK
  *-ESP_FAIL
  */
esp_err_t esp_http_client_open(esp_http_client_handle_t client, int write_len);
/**
  * @brief 该函数需要在esp_http_client_open之后调用,它将从http流中读取,处理所有接收头
  *
  * @param [in]客户端esp_http_client句柄
  *
  * @return
  *-(0)如果流不包含内容长度标头或分块编码(由`esp_http_client_is_chunked`响应检查)
  *-(-1:ESP_FAIL)如果有任何错误
  */
int esp_http_client_fetch_headers(esp_http_client_handle_t client);

4、软件设计

(1)、在连接好wifi之后首先就是填充结构体,结构体的内容如下:

/**
 * @brief HTTP configuration
 */
typedef struct {
    const char                  *url;      /*!< HTTP URL,URL上的信息最重要,它将覆盖下面的其他字段*/
    const char                  *host;      /*!< 域名或IP作为字符串 */
    int                         port;        /*!< 用于连接的端口,默认取决于esp_http_client_transport_t(80或443)*/
    const char                  *username;   /*!< 用于Http身份验证 */
    const char                  *password;   /*!< 用于Http身份验证 */
    esp_http_client_auth_type_t auth_type;   /*!< Http身份验证类型,请参见`esp_http_client_auth_type_t` */
    const char                  *path;       /*!< HTTP路径(如果未设置),默认为`/`*/
    const char                  *query;      /*!< HTTP 查询 */
    const char                  *cert_pem;   /*!< SSL服务器认证,PEM格式为字符串(如果客户端要求验证服务器) */
    const char                  *client_cert_pem; /*!< SSL客户端认证,PEM格式为字符串(如果服务器要求验证客户端) */
    const char                  *client_key_pem;  /*!< SSL客户端密钥,PEM格式为字符串(如果服务器要求验证客户端) */
    esp_http_client_method_t    method;       /*!< HTTP方法 */
    int                         timeout_ms;   /*!< 网络超时(以毫秒为单位) */
    bool                        disable_auto_redirect; /*!< 禁用HTTP自动重定向 */
    int                         max_redirection_count;/*!< 最大重定向数,如果为零,则使用默认值*/
    http_event_handle_cb        event_handler; /*!< HTTP事件处理 */
    esp_http_client_transport_t transport_type; /*!< HTTP传输类型,请参见`esp_http_client_transport_t` */
    int                         buffer_size;    /*!< HTTP接收缓冲区大小 */
    int                         buffer_size_tx; /*!< HTTP传输缓冲区大小 */
    void                        *user_data;    /*!< HTTP user_data上下文 */
    bool                        is_async;      /*!< 设置异步模式,目前仅支持HTTPS*/
    bool                        use_global_ca_store;/*!< Use a global ca_store for all the connections in which this bool is set. */
    bool                        skip_cert_common_name_check;/*!< 跳过对服务器证书CN字段的任何验证 */
} esp_http_client_config_t;

给结构体赋值,并且注册回调函数检测状态

esp_http_client_config_t config = {
.url = “http://httpbin.org/get”,
.event_handler = _http_event_handler,
};

初始化结构体,注册tcp读写连接函数

esp_http_client_handle_t client = esp_http_client_init(&config);

esp_http_client默认就是GET方法,其他方法如下

/**
 * @brief HTTP method
 */
typedef enum {
    HTTP_METHOD_GET = 0,    /*!< HTTP GET Method */
    HTTP_METHOD_POST,       /*!< HTTP POST Method */
    HTTP_METHOD_PUT,        /*!< HTTP PUT Method */
    HTTP_METHOD_PATCH,      /*!< HTTP PATCH Method */
    HTTP_METHOD_DELETE,     /*!< HTTP DELETE Method */
    HTTP_METHOD_HEAD,       /*!< HTTP HEAD Method */
    HTTP_METHOD_NOTIFY,     /*!< HTTP NOTIFY Method */
    HTTP_METHOD_SUBSCRIBE,  /*!< HTTP SUBSCRIBE Method */
    HTTP_METHOD_UNSUBSCRIBE,/*!< HTTP UNSUBSCRIBE Method */
    HTTP_METHOD_OPTIONS,    /*!< HTTP OPTIONS Method */
    HTTP_METHOD_MAX,
} esp_http_client_method_t;

GET获取数据使用esp_http_client_perform函数
在使用其他方法或重新设置url使用函数:

esp_http_client_set_url(client, "http://httpbin.org/post");
esp_http_client_set_method(client, HTTP_METHOD_POST);

5、实例

static void vTaskHttpGet(void *pvParameters)
{
    //等待连接成功,或已经连接有断开连接,此函数会一直阻塞,只有有连接
   xEventGroupWaitBits(xCreatedEventGroup_WifiConnect,// 事件标志组句柄 
        WIFI_CONNECTED_BIT, // 等待bit0和bit1被设置 
        pdFALSE,             //TRUE退出时bit0和bit1被清除,pdFALSE退出时bit0和bit1不清除
        pdTRUE,             //设置为pdTRUE表示等待bit1和bit0都被设置,pdFALSE表示等待bit1或bit0其中一个被设置
        portMAX_DELAY);      //等待延迟时间,一直等待 
    http_url_test();
    http_hostname_path_test();

    ESP_LOGI(TAG, "Finish http Test");
    vTaskDelete(NULL);
}

在任务vTaskHttpGet中测试

static void http_url_test(void)
{
    esp_http_client_config_t config = {
        .url = "http://httpbin.org/get",
        .event_handler = _http_event_handler,
    };
    //esp_http_client_config_t的参数分配内存,初始化数据,注册tcp的读写连接回调函数
    esp_http_client_handle_t client = esp_http_client_init(&config);

    // GET,默认方法
    //发送接收数据
    esp_err_t err = esp_http_client_perform(client);
    if (err == ESP_OK) {
        ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d",
                esp_http_client_get_status_code(client),
                esp_http_client_get_content_length(client));
    } else {
        ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
    }

    // POST
    const char *post_data = "field1=value1&field2=value2";
    esp_http_client_set_url(client, "http://httpbin.org/post");
    esp_http_client_set_method(client, HTTP_METHOD_POST);
    esp_http_client_set_post_field(client, post_data, strlen(post_data));
    err = esp_http_client_perform(client);
    if (err == ESP_OK) {
        ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %d",
                esp_http_client_get_status_code(client),
                esp_http_client_get_content_length(client));
    } else {
        ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err));
    }

    //PUT
    esp_http_client_set_url(client, "http://httpbin.org/put");
    esp_http_client_set_method(client, HTTP_METHOD_PUT);
    err = esp_http_client_perform(client);
    if (err == ESP_OK) {
        ESP_LOGI(TAG, "HTTP PUT Status = %d, content_length = %d",
                esp_http_client_get_status_code(client),
                esp_http_client_get_content_length(client));
    } else {
        ESP_LOGE(TAG, "HTTP PUT request failed: %s", esp_err_to_name(err));
    }

    //PATCH
    esp_http_client_set_url(client, "http://httpbin.org/patch");
    esp_http_client_set_method(client, HTTP_METHOD_PATCH);
    esp_http_client_set_post_field(client, NULL, 0);
    err = esp_http_client_perform(client);
    if (err == ESP_OK) {
        ESP_LOGI(TAG, "HTTP PATCH Status = %d, content_length = %d",
                esp_http_client_get_status_code(client),
                esp_http_client_get_content_length(client));
    } else {
        ESP_LOGE(TAG, "HTTP PATCH request failed: %s", esp_err_to_name(err));
    }

    //DELETE
    esp_http_client_set_url(client, "http://httpbin.org/delete");
    esp_http_client_set_method(client, HTTP_METHOD_DELETE);
    err = esp_http_client_perform(client);
    if (err == ESP_OK) {
        ESP_LOGI(TAG, "HTTP DELETE Status = %d, content_length = %d",
                esp_http_client_get_status_code(client),
                esp_http_client_get_content_length(client));
    } else {
        ESP_LOGE(TAG, "HTTP DELETE request failed: %s", esp_err_to_name(err));
    }

    //HEAD
    esp_http_client_set_url(client, "http://httpbin.org/get");
    esp_http_client_set_method(client, HTTP_METHOD_HEAD);
    err = esp_http_client_perform(client);
    if (err == ESP_OK) {
        ESP_LOGI(TAG, "HTTP HEAD Status = %d, content_length = %d",
                esp_http_client_get_status_code(client),
                esp_http_client_get_content_length(client));
    } else {
        ESP_LOGE(TAG, "HTTP HEAD request failed: %s", esp_err_to_name(err));
    }
    //释放内存
    esp_http_client_cleanup(client);

}

6、调试结果

在这里插入图片描述

所有文章源代码:https://download.csdn.net/download/lu330274924/88518092

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

物联网程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值