esp_http_client: Add support for esp_events

This commit is contained in:
Harshit Malpani 2022-11-16 17:31:07 +05:30
parent 745c06626d
commit 674fd8feb8
No known key found for this signature in database
GPG Key ID: FF1193D150EF75C3
6 changed files with 97 additions and 1 deletions

View File

@ -1,5 +1,7 @@
if(NOT ${IDF_TARGET} STREQUAL "linux")
set(req lwip)
set(req lwip esp_event)
else()
set(req esp_stubs)
endif()
idf_component_register(SRCS "esp_http_client.c"

View File

@ -25,6 +25,8 @@
#include "esp_transport_ssl.h"
#endif
ESP_EVENT_DEFINE_BASE(ESP_HTTP_CLIENT_EVENT);
static const char *TAG = "HTTP_CLIENT";
/**
@ -183,6 +185,14 @@ static esp_err_t http_dispatch_event(esp_http_client_t *client, esp_http_client_
return ESP_OK;
}
static void http_dispatch_event_to_event_loop(int32_t event_id, const void* event_data, size_t event_data_size)
{
esp_err_t err = esp_event_post(ESP_HTTP_CLIENT_EVENT, event_id, event_data, event_data_size, portMAX_DELAY);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to post https_ota event: %"PRId32", error: %s", event_id, esp_err_to_name(err));
}
}
static int http_on_message_begin(http_parser *parser)
{
esp_http_client_t *client = parser->data;
@ -211,6 +221,7 @@ static int http_on_header_event(esp_http_client_handle_t client)
client->event.header_key = client->current_header_key;
client->event.header_value = client->current_header_value;
http_dispatch_event(client, HTTP_EVENT_ON_HEADER, NULL, 0);
http_dispatch_event_to_event_loop(HTTP_EVENT_ON_HEADER, &client, sizeof(esp_http_client_handle_t));
free(client->current_header_key);
free(client->current_header_value);
client->current_header_key = NULL;
@ -293,6 +304,10 @@ static int http_on_body(http_parser *parser, const char *at, size_t length)
client->response->data_process += length;
client->response->buffer->raw_len += length;
http_dispatch_event(client, HTTP_EVENT_ON_DATA, (void *)at, length);
esp_http_client_on_data_t evt_data = {};
evt_data.data_process = client->response->data_process;
evt_data.client = client;
http_dispatch_event_to_event_loop(HTTP_EVENT_ON_DATA, &evt_data, sizeof(esp_http_client_on_data_t));
return 0;
}
@ -891,6 +906,11 @@ static esp_err_t esp_http_check_response(esp_http_client_handle_t client)
return ESP_FAIL;
};
}
esp_http_client_redirect_event_data_t evt_data = {
.status_code = client->response->status_code,
.client = client,
};
http_dispatch_event_to_event_loop(HTTP_EVENT_REDIRECT, &evt_data, sizeof(esp_http_client_redirect_event_data_t));
break;
case HttpStatus_Unauthorized:
esp_http_client_add_auth(client);
@ -1138,6 +1158,7 @@ int esp_http_client_read(esp_http_client_handle_t client, char *buffer, int len)
if (rlen < 0 && ridx == 0 && !esp_http_client_is_complete_data_received(client)) {
http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0);
http_dispatch_event_to_event_loop(HTTP_EVENT_ERROR, &client, sizeof(esp_http_client_handle_t));
return ESP_FAIL;
}
return ridx;
@ -1172,6 +1193,7 @@ esp_err_t esp_http_client_perform(esp_http_client_handle_t client)
return ESP_ERR_HTTP_EAGAIN;
}
http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0);
http_dispatch_event_to_event_loop(HTTP_EVENT_ERROR, &client, sizeof(esp_http_client_handle_t));
return err;
}
/* falls through */
@ -1181,6 +1203,7 @@ esp_err_t esp_http_client_perform(esp_http_client_handle_t client)
return ESP_ERR_HTTP_EAGAIN;
}
http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0);
http_dispatch_event_to_event_loop(HTTP_EVENT_ERROR, &client, sizeof(esp_http_client_handle_t));
return err;
}
/* falls through */
@ -1190,6 +1213,7 @@ esp_err_t esp_http_client_perform(esp_http_client_handle_t client)
return ESP_ERR_HTTP_EAGAIN;
}
http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0);
http_dispatch_event_to_event_loop(HTTP_EVENT_ERROR, &client, sizeof(esp_http_client_handle_t));
return err;
}
/* falls through */
@ -1209,9 +1233,11 @@ esp_err_t esp_http_client_perform(esp_http_client_handle_t client)
ESP_LOGW(TAG, "Close connection due to FIN received");
esp_http_client_close(client);
http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0);
http_dispatch_event_to_event_loop(HTTP_EVENT_ERROR, &client, sizeof(esp_http_client_handle_t));
return ESP_ERR_HTTP_CONNECTION_CLOSED;
}
http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0);
http_dispatch_event_to_event_loop(HTTP_EVENT_ERROR, &client, sizeof(esp_http_client_handle_t));
return ESP_ERR_HTTP_FETCH_HEADER;
}
/* falls through */
@ -1222,6 +1248,7 @@ esp_err_t esp_http_client_perform(esp_http_client_handle_t client)
if ((err = esp_http_check_response(client)) != ESP_OK) {
ESP_LOGE(TAG, "Error response");
http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0);
http_dispatch_event_to_event_loop(HTTP_EVENT_ERROR, &client, sizeof(esp_http_client_handle_t));
return err;
}
while (client->response->is_chunked && !client->is_chunk_complete) {
@ -1243,6 +1270,7 @@ esp_err_t esp_http_client_perform(esp_http_client_handle_t client)
}
}
http_dispatch_event(client, HTTP_EVENT_ON_FINISH, NULL, 0);
http_dispatch_event_to_event_loop(HTTP_EVENT_ON_FINISH, &client, sizeof(esp_http_client_handle_t));
client->response->buffer->raw_len = 0;
if (!http_should_keep_alive(client->parser)) {
@ -1340,6 +1368,7 @@ static esp_err_t esp_http_client_connect(esp_http_client_handle_t client)
}
client->state = HTTP_STATE_CONNECTED;
http_dispatch_event(client, HTTP_EVENT_ON_CONNECTED, NULL, 0);
http_dispatch_event_to_event_loop(HTTP_EVENT_ON_CONNECTED, &client, sizeof(esp_http_client_handle_t));
}
return ESP_OK;
}
@ -1439,6 +1468,7 @@ static esp_err_t esp_http_client_request_send(esp_http_client_handle_t client, i
client->data_written_index = 0;
client->data_write_left = client->post_len;
http_dispatch_event(client, HTTP_EVENT_HEADERS_SENT, NULL, 0);
http_dispatch_event_to_event_loop(HTTP_EVENT_HEADERS_SENT, &client, sizeof(esp_http_client_handle_t));
client->state = HTTP_STATE_REQ_COMPLETE_HEADER;
return ESP_OK;
}
@ -1477,10 +1507,12 @@ esp_err_t esp_http_client_open(esp_http_client_handle_t client, int write_len)
esp_err_t err;
if ((err = esp_http_client_connect(client)) != ESP_OK) {
http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0);
http_dispatch_event_to_event_loop(HTTP_EVENT_ERROR, &client, sizeof(esp_http_client_handle_t));
return err;
}
if ((err = esp_http_client_request_send(client, write_len)) != ESP_OK) {
http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0);
http_dispatch_event_to_event_loop(HTTP_EVENT_ERROR, &client, sizeof(esp_http_client_handle_t));
return err;
}
return ESP_OK;
@ -1510,6 +1542,7 @@ esp_err_t esp_http_client_close(esp_http_client_handle_t client)
{
if (client->state >= HTTP_STATE_INIT) {
http_dispatch_event(client, HTTP_EVENT_DISCONNECTED, esp_transport_get_error_handle(client->transport), 0);
http_dispatch_event_to_event_loop(HTTP_EVENT_DISCONNECTED, &client, sizeof(esp_http_client_handle_t));
client->state = HTTP_STATE_INIT;
return esp_transport_close(client->transport);
}

View File

@ -18,6 +18,9 @@ extern "C" {
#define DEFAULT_HTTP_BUF_SIZE (512)
#include "esp_event.h"
ESP_EVENT_DECLARE_BASE(ESP_HTTP_CLIENT_EVENT);
typedef struct esp_http_client *esp_http_client_handle_t;
typedef struct esp_http_client_event *esp_http_client_event_handle_t;
@ -50,6 +53,21 @@ typedef struct esp_http_client_event {
char *header_value; /*!< For HTTP_EVENT_ON_HEADER event_id, it's store current http header value */
} esp_http_client_event_t;
/**
* @brief Argument structure for HTTP_EVENT_ON_DATA event
*/
typedef struct esp_http_client_on_data {
esp_http_client_handle_t client; /*!< Client handle */
int64_t data_process; /*!< Total data processed */
} esp_http_client_on_data_t;
/**
* @brief Argument structure for HTTP_EVENT_REDIRECT event
*/
typedef struct esp_http_client_redirect_event_data {
esp_http_client_handle_t client; /*!< Client handle */
int status_code; /*!< Status Code */
} esp_http_client_redirect_event_data_t;
/**
* @brief HTTP Client transport

View File

@ -110,6 +110,33 @@ Examples of Authentication Configuration
.auth_type = HTTP_AUTH_TYPE_BASIC,
};
Event Handling
--------------
ESP HTTP Client supports event handling by triggering an event handler corresponding to the event which took place.
:cpp:enum:`esp_http_client_event_id_t` contains all the events which could occur while performing an HTTP request using the ESP HTTP Client.
To enable event handling, you just need to set a callback function using the :cpp:member:`esp_http_client_config_t::event_handler` member.
ESP HTTP Client Diagnostic Information
--------------------------------------
Diagnostic information could be helpful to gain insights into a problem. In the case of ESP HTTP Client, this diagnostic information can be collected by registering an event handler with :doc:`the Event Loop library <../system/esp_event>`.
This feature has been added by keeping in mind the `ESP Insights <https://github.com/espressif/esp-insights>`_ framework which collects the diagnostic information. However, this feature can also be used without any dependency on ESP Insights framework for the diagnostic purpose.
Event handler can be registered to the event loop using the :cpp:func:`esp_event_handler_register` function.
Expected data types for different HTTP Client events in the event loop:
- HTTP_EVENT_ERROR : ``esp_http_client_handle_t``
- HTTP_EVENT_ON_CONNECTED : ``esp_http_client_handle_t``
- HTTP_EVENT_HEADERS_SENT : ``esp_http_client_handle_t``
- HTTP_EVENT_ON_HEADER : ``esp_http_client_handle_t``
- HTTP_EVENT_ON_DATA : ``esp_http_client_on_data_t``
- HTTP_EVENT_ON_FINISH : ``esp_http_client_handle_t``
- HTTP_EVENT_DISCONNECTED : ``esp_http_client_handle_t``
- HTTP_EVENT_REDIRECT : ``esp_http_client_redirect_event_data_t``
The :cpp:type:`esp_http_client_handle_t` received along with the event data will be valid until :cpp:enumerator:`HTTP_EVENT_DISCONNECTED <esp_http_client_event_id_t::HTTP_EVENT_DISCONNECTED>` is not received. This handle has been sent primarily to differentiate between different client
connections and must not be used for any other purpose (as it may change based on client connection state).
API Reference
-------------

View File

@ -6,6 +6,7 @@
#include <stdlib.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_event.h"
extern void app_main(void);
@ -14,6 +15,12 @@ esp_err_t esp_event_loop_create_default(void)
return ESP_OK;
}
esp_err_t esp_event_post(esp_event_base_t event_base, int32_t event_id,
const void* event_data, size_t event_data_size, TickType_t ticks_to_wait)
{
return ESP_OK;
}
esp_err_t esp_netif_init(void)
{
return ESP_OK;

View File

@ -5,4 +5,13 @@
*/
#include "esp_err.h"
typedef const char* esp_event_base_t; /**< unique pointer to a subsystem that exposes events */
typedef unsigned long TickType_t;
#define ESP_EVENT_DECLARE_BASE(id) extern esp_event_base_t id
#define ESP_EVENT_DEFINE_BASE(id) esp_event_base_t id = #id
esp_err_t esp_event_loop_create_default(void);
esp_err_t esp_event_post(esp_event_base_t event_base, int32_t event_id,
const void* event_data, size_t event_data_size, TickType_t ticks_to_wait);