ESP_jakob wrote: ↑Fri Jul 31, 2020 11:45 am
If you can, would you like to share some context about your use case?
Yep sure, all I'm doing is a esp_http_client wrapper, so that I don't have to worry about chunked data, initialization, configuration and error checking in every little project I (or others, if I release it) do - and cause modularization is good
I could've probably used some more generic FreeRTOS functions, but that seemed a little too cumbersome.
In the end the simplest solution I've come up with is just making the post, get, etc, functions blocking, and cut out events completely. I still left all of my event infrastructure in there, so that when I add opening a connection (esp_http_client_open()) as an option, the user can still receive a 'connected' event - so alteast that wasn't for nothing
In the end, this is the actual implementation that I'll go with for now.
Code: Select all
ApiClient::http_message_t ApiClient::sendRequest(std::string path,
std::string payload, esp_http_client_method_t http_method) {
if (state_ == STATE_DEINIT) {
ESP_LOGW(TAG, "[%s]: ApiClient wasn't initialized!", __func__);
return {ERR_NOT_INIT,"",{},0};
}
else if (state_ != STATE_INIT) {
ESP_LOGW(TAG, "[%s]: Unable to send request, " \
"other operations are using the socket", __func__);
return {ERR_CONN,"",{},0};
}
std::string url = api_config_.host + path;
/* Reset rx buffer & rx done flag */
rx_buffer_ = {OK, "", {}, 0};
rx_done_ = false;
ESP_ERROR_CHECK(esp_http_client_set_method(esp_client_handle_, http_method));
ESP_ERROR_CHECK(esp_http_client_set_url(esp_client_handle_, url.c_str()));
ESP_ERROR_CHECK(esp_http_client_set_post_field(esp_client_handle_,
payload.c_str(), payload.length()));
ESP_ERROR_CHECK(esp_http_client_perform(esp_client_handle_));
while (!rx_done_)
vTaskDelay(10);
return rx_buffer_;
} //sendRequest
esp_err_t ApiClient::event_handler(esp_http_client_event_t *evt) {
ApiClient* api_client = static_cast<ApiClient*>(evt->user_data);
http_message_t* rx_buffer = &(api_client->rx_buffer_);
esp_http_client_event_id_t event_id = evt->event_id;
std::string event_data(static_cast<char*>(evt->data), evt->data_len);
ESP_LOGD(TAG, "[%s]: Event id: %u", __func__, event_id);
switch(event_id) {
case HTTP_EVENT_ERROR:
//Todo: find out what errors can happen here & handle them
break;
case HTTP_EVENT_ON_CONNECTED:
esp_event_post_to(api_client->event_handle_,
STATE_EVENT, EVENT_CONNECTED, nullptr, 0, event_block_ticks);
break;
case HTTP_EVENT_ON_HEADER:
rx_buffer->headers.insert(
{evt->header_key, evt->header_value});
break;
case HTTP_EVENT_ON_DATA:
rx_buffer->data += event_data;
break;
case HTTP_EVENT_ON_FINISH:
rx_buffer->status_code =
esp_http_client_get_status_code(api_client->esp_client_handle_);
api_client->rx_done_ = true;
esp_event_post_to(api_client->event_handle_,
STATE_EVENT, EVENT_RECV, nullptr, 0, event_block_ticks);
break;
case HTTP_EVENT_DISCONNECTED:
esp_event_post_to(api_client->event_handle_,
STATE_EVENT, EVENT_DISCONNECTED, nullptr, 0, event_block_ticks);
break;
default:
break;
}
return ESP_OK;
} //ApiClient::event_handler