3#include "AudioTools/CoreAudio/AudioHttp/AbstractURLStream.h"
4#include "AudioTools/CoreAudio/AudioHttp/HttpRequest.h"
5#include "AudioTools/CoreAudio/AudioHttp/ICYStreamT.h"
6#include "AudioTools/CoreAudio/AudioHttp/URLStreamBufferedT.h"
7#include "esp_http_client.h"
8#include "esp_idf_version.h"
24 bool begin(
const char* ssid,
const char* password) {
26 if (is_open)
return true;
27 if (!setupWIFI(ssid, password)) {
28 LOGE(
"setupWIFI failed");
45 void setPowerSave(wifi_ps_type_t powerSave) { power_save = powerSave; }
47 bool isConnected() {
return is_open; }
50 volatile bool is_open =
false;
51 esp_ip4_addr_t ip = {0};
52 wifi_ps_type_t power_save = WIFI_PS_NONE;
54 bool setupWIFI(
const char* ssid,
const char* password) {
55 assert(ssid !=
nullptr);
56 assert(password !=
nullptr);
57 LOGI(
"setupWIFI: %s", ssid);
58 esp_err_t ret = nvs_flash_init();
59 if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
60 ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
62 ret = nvs_flash_init();
65 if (esp_netif_init() != ESP_OK) {
66 LOGE(
"esp_netif_init");
70 if (esp_event_loop_create_default() != ESP_OK) {
71 LOGE(
"esp_event_loop_create_default");
75 esp_netif_t* itf = esp_netif_create_default_wifi_sta();
77 LOGE(
"esp_netif_create_default_wifi_sta");
81 esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID,
82 &wifi_sta_event_handler,
this, NULL);
83 esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP,
84 &wifi_sta_event_handler,
this, NULL);
85 wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
86 if (esp_wifi_init(&cfg) != ESP_OK) {
87 LOGE(
"esp_wifi_init");
91 esp_wifi_set_mode(WIFI_MODE_STA);
92 esp_wifi_set_ps(power_save);
94 wifi_config_t sta_config;
95 memset(&sta_config, 0,
sizeof(wifi_config_t));
96 strncpy((
char*)sta_config.sta.ssid, ssid, 32);
97 strncpy((
char*)sta_config.sta.password, password, 32);
98 sta_config.sta.threshold.authmode = WIFI_AUTH_WPA_WPA2_PSK;
99 esp_wifi_set_config(WIFI_IF_STA, &sta_config);
102 bool rc = esp_wifi_start() == ESP_OK;
104 LOGE(
"esp_wifi_start");
109 static void wifi_sta_event_handler(
void* arg, esp_event_base_t event_base,
110 int32_t event_id,
void* event_data) {
113 if (event_base == WIFI_EVENT) {
115 case WIFI_EVENT_STA_START:
116 LOGI(
"WIFI_EVENT_STA_START");
119 case WIFI_EVENT_STA_DISCONNECTED:
120 LOGI(
"WIFI_EVENT_STA_DISCONNECTED");
124 }
else if (event_base == IP_EVENT) {
126 case IP_EVENT_STA_GOT_IP: {
127 ip_event_got_ip_t*
event = (ip_event_got_ip_t*)event_data;
128 self->ip =
event->ip_info.ip;
129 self->is_open =
true;
130 LOGI(
"==> Station connected with IP: " IPSTR
", GW: " IPSTR
131 ", Mask: " IPSTR
".",
132 IP2STR(&event->ip_info.ip), IP2STR(&event->ip_info.gw),
133 IP2STR(&event->ip_info.netmask));
173 virtual bool begin(
const char*
urlStr,
const char* acceptMime =
"",
174 MethodID action = GET,
const char* reqMime =
"",
175 const char* reqData =
"") {
181 if (ssid !=
nullptr) {
182 if (!IDF_WIFI.begin(ssid, password)) {
186 if (!IDF_WIFI.isConnected()) {
188 Serial.print(
"Waiting for connection ");
189 while (!IDF_WIFI.isConnected()) {
198 actualURLStreamESP32 =
this;
201 wifi_country_t cntry;
202 memset(&cntry, 0,
sizeof(wifi_country_t));
203 esp_wifi_get_country(&cntry);
205 strncpy(text, cntry.cc, 3);
206 LOGI(
"wifi country: %s", text);
209 esp_http_client_config_t http_config;
210 memset(&http_config, 0,
sizeof(http_config));
212 http_config.user_agent = DEFAULT_AGENT;
213 http_config.event_handler = http_event_handler;
214 http_config.buffer_size = buffer_size;
215 http_config.timeout_ms = _timeout;
216 http_config.user_data =
this;
218 if (pem_cert !=
nullptr) {
219 http_config.cert_pem = (
const char*)pem_cert;
220 http_config.cert_len = pem_cert_len;
223 if (crt_bundle_attach !=
nullptr) {
224 http_config.crt_bundle_attach = crt_bundle_attach;
229 http_config.method = HTTP_METHOD_GET;
232 http_config.method = HTTP_METHOD_POST;
235 http_config.method = HTTP_METHOD_PUT;
238 http_config.method = HTTP_METHOD_DELETE;
241 LOGE(
"Unsupported action: %d", action);
246 if (client_handle ==
nullptr) {
247 client_handle = esp_http_client_init(&http_config);
254 for (
auto it = lines.begin(); it != lines.end(); ++it) {
256 esp_http_client_set_header(client_handle, (*it)->key.c_str(),
257 (*it)->value.c_str());
262 if (esp_http_client_open(client_handle, 0) != ESP_OK) {
263 LOGE(
"esp_http_client_open");
268 content_length = esp_http_client_fetch_headers(client_handle);
269 int status_code = esp_http_client_get_status_code(client_handle);
270 LOGI(
"status_code: %d / content_length: %d", status_code, content_length);
275 write((
const uint8_t*)reqData, data.
length());
278 return status_code == 200;
281 virtual void end()
override {
282 esp_http_client_close(client_handle);
283 esp_http_client_cleanup(client_handle);
290 virtual void setSSID(
const char* ssid) { this->ssid = ssid; }
293 virtual void setPassword(
const char* password) { this->password = password; }
297 IDF_WIFI.setPowerSave(ps ? WIFI_PS_MAX_MODEM : WIFI_PS_NONE);
300 size_t write(
const uint8_t* data,
size_t len)
override {
302 return esp_http_client_write(client_handle, (
const char*)data, len);
305 size_t readBytes(uint8_t* data,
size_t len)
override {
307 size_t read = esp_http_client_read(client_handle, (
char*)data, len);
319 return request.getReplyHeader(key);
325 int len = strlen(cert);
326 setCACert((
const uint8_t*)cert, len + 1);
331 void setCACert(esp_err_t (*cb)(
void* conf)) { crt_bundle_attach = cb; }
343 const char*
urlStr()
override {
return (
char*)url_str; }
359 esp_http_client_handle_t client_handle =
nullptr;
360 bool is_power_save =
false;
361 const char* ssid =
nullptr;
362 const char* password =
nullptr;
363 int buffer_size = DEFAULT_BUFFER_SIZE;
364 const uint8_t* pem_cert =
nullptr;
365 int pem_cert_len = 0;
366 esp_err_t (*crt_bundle_attach)(
void* conf) =
nullptr;
367 size_t total_read = 0;
368 const char* url_str =
nullptr;
369 int content_length = 0;
377 assert(cert[len - 1] == 0);
380 static esp_err_t http_event_handler(esp_http_client_event_t* evt) {
381 switch (evt->event_id) {
382 case HTTP_EVENT_ERROR:
383 LOGI(
"HTTP_EVENT_ERROR");
385 case HTTP_EVENT_ON_CONNECTED:
386 LOGD(
"HTTP_EVENT_ON_CONNECTED");
388 case HTTP_EVENT_HEADER_SENT:
389 LOGD(
"HTTP_EVENT_HEADER_SENT");
391 case HTTP_EVENT_ON_HEADER:
392 LOGI(
"HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key,
395 actualURLStreamESP32->request.reply().put(evt->header_key,
398 case HTTP_EVENT_ON_DATA:
399 LOGD(
"HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
401 case HTTP_EVENT_ON_FINISH:
402 LOGI(
"HTTP_EVENT_ON_FINISH");
404 case HTTP_EVENT_DISCONNECTED:
405 LOGI(
"HTTP_EVENT_DISCONNECTED");
407#if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(5, 3, 7)
408 case HTTP_EVENT_REDIRECT:
409 LOGI(
"HTTP_EVENT_REDIRECT");