10#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
11#include "esp_crt_bundle.h"
16static const uint32_t READ_WRITE_TIMEOUT_MS = 20;
18static const uint32_t CONNECTION_TIMEOUT_MS = 5000;
19static const uint8_t MAX_FETCHING_HEADER_ATTEMPTS = 6;
21static const size_t HTTP_STREAM_BUFFER_SIZE = 2048;
23static const uint8_t MAX_REDIRECTIONS = 5;
25static const char *
const TAG =
"audio_reader";
62 return ESP_ERR_INVALID_STATE;
72 return ESP_ERR_INVALID_STATE;
92 return ESP_ERR_INVALID_ARG;
95 esp_http_client_config_t client_config = {};
97 client_config.url = uri.c_str();
98 client_config.cert_pem =
nullptr;
99 client_config.disable_auto_redirect =
false;
100 client_config.max_redirection_count = MAX_REDIRECTIONS;
102 client_config.user_data =
this;
103 client_config.buffer_size = HTTP_STREAM_BUFFER_SIZE;
104 client_config.keep_alive_enable =
true;
105 client_config.timeout_ms = CONNECTION_TIMEOUT_MS;
107#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
108 if (uri.find(
"https:") != std::string::npos) {
109 client_config.crt_bundle_attach = esp_crt_bundle_attach;
113 this->
client_ = esp_http_client_init(&client_config);
115 if (this->
client_ ==
nullptr) {
119 esp_err_t err = esp_http_client_open(this->
client_, 0);
122 ESP_LOGE(TAG,
"Failed to open URL");
127 int64_t header_length = esp_http_client_fetch_headers(this->
client_);
128 uint8_t reattempt_count = 0;
129 while ((header_length < 0) && (reattempt_count < MAX_FETCHING_HEADER_ATTEMPTS)) {
131 if (header_length != -ESP_ERR_HTTP_EAGAIN) {
136 this->
client_ = esp_http_client_init(&client_config);
137 esp_http_client_open(this->
client_, 0);
138 header_length = esp_http_client_fetch_headers(this->
client_);
143 if (header_length < 0) {
144 ESP_LOGE(TAG,
"Failed to fetch headers");
149 int status_code = esp_http_client_get_status_code(this->
client_);
158 while ((esp_http_client_set_redirection(this->
client_) == ESP_OK) && (redirect_count < MAX_REDIRECTIONS)) {
159 err = esp_http_client_open(this->
client_, 0);
165 header_length = esp_http_client_fetch_headers(this->
client_);
166 if (header_length < 0) {
171 status_code = esp_http_client_get_status_code(this->
client_);
184 err = esp_http_client_get_url(this->
client_, url, 500);
193 return ESP_ERR_NOT_SUPPORTED;
203 return ESP_ERR_NO_MEM;
210 if (this->
client_ !=
nullptr) {
223 switch (evt->event_id) {
224 case HTTP_EVENT_ON_HEADER:
225 if (strcasecmp(evt->header_key,
"Content-Type") == 0) {
237 if (remaining_bytes > 0) {
239 pdMS_TO_TICKS(READ_WRITE_TIMEOUT_MS));
251 if (esp_http_client_is_complete_data_received(this->
client_)) {
258 this->output_transfer_buffer_->free());
260 if (received_len > 0) {
264 }
else if (received_len <= 0) {
266 if (received_len == -1) {
274 ESP_LOGE(TAG,
"Timed out");
279 delay(READ_WRITE_TIMEOUT_MS);
287 if (this->
client_ !=
nullptr) {
288 esp_http_client_close(this->
client_);
289 esp_http_client_cleanup(this->
client_);
uint32_t last_data_read_ms_
AudioReaderState http_read_()
void cleanup_connection_()
AudioReaderState file_read_()
std::unique_ptr< AudioSinkTransferBuffer > output_transfer_buffer_
const uint8_t * file_current_
esp_err_t add_sink(const std::weak_ptr< ring_buffer::RingBuffer > &output_ring_buffer)
Adds a sink ring buffer for audio data.
AudioReaderState read()
Reads new file data from the source and sends to the ring buffer sink.
AudioFileType audio_file_type_
static esp_err_t http_event_handler(esp_http_client_event_t *evt)
Monitors the http client events to attempt determining the file type from the Content-Type header.
std::shared_ptr< ring_buffer::RingBuffer > file_ring_buffer_
esp_http_client_handle_t client_
AudioFile * current_audio_file_
esp_err_t start(const std::string &uri, AudioFileType &file_type)
Starts reading an audio file from an http source.
static std::unique_ptr< AudioSinkTransferBuffer > create(size_t buffer_size)
Creates a new sink transfer buffer.
@ HTTP_STATUS_INTERNAL_ERROR
@ HTTP_STATUS_MULTIPLE_CHOICES
@ HTTP_STATUS_MOVED_PERMANENTLY
@ HTTP_STATUS_BAD_REQUEST
@ HTTP_STATUS_TEMPORARY_REDIRECT
@ HTTP_STATUS_PERMANENT_REDIRECT
@ HTTP_STATUS_METHOD_NOT_ALLOWED
@ HTTP_STATUS_PARTIAL_CONTENT
@ HTTP_STATUS_NOT_MODIFIED
@ HTTP_STATUS_LENGTH_REQUIRED
@ HTTP_STATUS_UNAUTHORIZED
@ HTTP_STATUS_NOT_ACCEPTABLE
AudioFileType detect_audio_file_type(const char *content_type, const char *url)
Detect audio file type from a Content-Type header value and/or URL extension.
void HOT delay(uint32_t ms)
uint32_t IRAM_ATTR HOT millis()