3 #include "AudioConfig.h"
9 #include <WiFiClientSecure.h>
13 #include "AbstractURLStream.h"
14 #include "HttpRequest.h"
15 #include "AudioTools/CoreAudio/AudioBasic/Str.h"
28 URLStream(
int readBufferSize = DEFAULT_BUFFER_SIZE) {
30 setReadBufferSize(readBufferSize);
33 URLStream(
Client& clientPar,
int readBufferSize = DEFAULT_BUFFER_SIZE) {
35 setReadBufferSize(readBufferSize);
39 URLStream(
const char* network,
const char* password,
40 int readBufferSize = DEFAULT_BUFFER_SIZE) {
42 setReadBufferSize(readBufferSize);
52 #ifdef USE_WIFI_CLIENT_SECURE
53 if (clientSecure !=
nullptr) {
55 clientSecure =
nullptr;
59 if (clientInsecure !=
nullptr) {
60 delete clientInsecure;
61 clientInsecure =
nullptr;
70 void setSSID(
const char* ssid)
override { this->network = ssid; }
73 void setPassword(
const char* password)
override { this->password = password; }
75 void setReadBufferSize(
int readBufferSize) {
76 read_buffer_size = readBufferSize;
80 virtual bool begin(
const char* urlStr,
const char* acceptMime =
nullptr,
81 MethodID action = GET,
const char* reqMime =
"",
82 const char* reqData =
"")
override {
83 LOGI(
"%s: %s", LOG_METHOD, urlStr);
84 if (!preProcess(urlStr, acceptMime)) {
85 LOGE(
"preProcess failed");
88 int result = process<const char*>(action, url, reqMime, reqData);
90 size = request.contentLength();
91 LOGI(
"size: %d", (
int)size);
92 if (size >= 0 && wait_for_data) {
97 active = result == 200;
98 LOGI(
"==> http status: %d", result);
100 custom_log_level.reset();
106 virtual bool begin(
const char* urlStr,
const char* acceptMime,
107 MethodID action,
const char* reqMime,
Stream& reqData,
109 LOGI(
"%s: %s", LOG_METHOD, urlStr);
110 if (!preProcess(urlStr, acceptMime)) {
111 LOGE(
"preProcess failed");
114 int result = process<Stream&>(action, url, reqMime, reqData, len);
116 size = request.contentLength();
117 LOGI(
"size: %d", (
int)size);
118 if (size >= 0 && wait_for_data) {
123 active = result == 200;
124 LOGI(
"==> http status: %d", result);
125 #if USE_AUDIO_LOGGING
126 custom_log_level.reset();
131 virtual void end()
override {
132 if (active) request.stop();
137 virtual int available()
override {
138 if (!active || !request)
return 0;
140 int result = request.available();
141 LOGD(
"available: %d", result);
145 virtual size_t readBytes(uint8_t* data,
size_t len)
override {
146 if (!active || !request)
return 0;
148 int read = request.read((uint8_t*)&data[0], len);
153 LOGD(
"readBytes %d -> %d", (
int)len, read);
157 virtual int read()
override {
158 if (!active)
return -1;
160 read_buffer.resize(read_buffer_size);
164 return isEOS() ? -1 : read_buffer[read_pos++];
167 virtual int peek()
override {
168 if (!active)
return -1;
170 read_buffer.resize(read_buffer_size);
173 return isEOS() ? -1 : read_buffer[read_pos];
176 virtual void flush()
override {}
178 virtual size_t write(uint8_t)
override {
return not_supported(0); }
180 virtual size_t write(
const uint8_t*,
size_t len)
override {
181 return not_supported(0);
187 operator bool() {
return active && request.
isReady(); }
203 httpRequest().setConnection(close ? CON_CLOSE : CON_KEEP_ALIVE);
210 read_buffer.resize(0);
217 request.
header().put(header, value);
226 void setWaitForData(
bool flag) { wait_for_data = flag; }
228 int contentLength() {
return size; }
230 size_t totalRead() {
return total_read; }
235 uint32_t end =
millis() + timeout;
236 if (request.available() == 0) {
237 LOGI(
"Request written ... waiting for reply");
238 while (request.available() == 0) {
239 if (
millis() > end)
break;
241 if (request.reply().statusCode() >= 300) {
242 LOGE(
"Error code recieved ... stop waiting for reply");
248 LOGD(
"available: %d", request.available());
249 return request.available() > 0;
252 #if USE_AUDIO_LOGGING
254 void setLogLevel(AudioLogger::LogLevel level) { custom_log_level.set(level); }
256 const char* urlStr() {
return url_str.
c_str(); }
260 #if USE_AUDIO_LOGGING
261 CustomLogLevel custom_log_level;
268 Vector<uint8_t> read_buffer{0};
269 uint16_t read_buffer_size = DEFAULT_BUFFER_SIZE;
273 bool wait_for_data =
true;
275 const char* network =
nullptr;
276 const char* password =
nullptr;
277 Client* client =
nullptr;
279 WiFiClient* clientInsecure =
nullptr;
281 #ifdef USE_WIFI_CLIENT_SECURE
282 WiFiClientSecure* clientSecure =
nullptr;
284 int clientTimeout = URL_CLIENT_TIMEOUT;
285 unsigned long handshakeTimeout = URL_HANDSHAKE_TIMEOUT;
286 bool is_power_save =
false;
288 bool preProcess(
const char* urlStr,
const char* acceptMime) {
290 #if USE_AUDIO_LOGGING
291 custom_log_level.set();
294 url.setUrl(url_str.c_str());
302 if (client ==
nullptr){
304 LOGE(
"Not connected");
311 if (acceptMime !=
nullptr) {
312 request.setAcceptMime(acceptMime);
316 Client& client =
getClient(url.isSecure());
317 request.setClient(client);
320 client.setTimeout(clientTimeout / 1000);
321 request.setTimeout(clientTimeout);
325 if (clientSecure !=
nullptr) {
326 clientSecure->setHandshakeTimeout(handshakeTimeout);
330 if (!is_power_save) {
331 esp_wifi_set_ps(WIFI_PS_NONE);
338 template <
typename T>
339 int process(MethodID action,
Url& url,
const char* reqMime, T reqData,
343 const char* icy = request.header().get(
"Icy-MetaData");
345 int status_code = request.process(action, url, reqMime, reqData, len);
347 while (request.reply().isRedirectStatus()) {
348 const char* redirect_url = request.reply().get(LOCATION);
349 if (redirect_url !=
nullptr) {
350 LOGW(
"Redirected to: %s", redirect_url);
351 url.setUrl(redirect_url);
354 request.setClient(*p_client);
356 request.header().put(
"Icy-MetaData", icy);
358 status_code = request.process(action, url, reqMime, reqData, len);
360 LOGE(
"Location is null");
369 #ifdef USE_WIFI_CLIENT_SECURE
371 if (clientSecure ==
nullptr) {
372 clientSecure =
new WiFiClientSecure();
373 clientSecure->setInsecure();
375 LOGI(
"WiFiClientSecure");
376 return *clientSecure;
380 if (clientInsecure ==
nullptr) {
381 clientInsecure =
new WiFiClient();
384 return *clientInsecure;
386 if (client ==
nullptr){
387 LOGE(
"Client not set");
394 inline void fillBuffer() {
397 read_size = readBytes(&read_buffer[0], read_buffer_size);
402 inline bool isEOS() {
return read_pos >= read_size; }
406 if (network !=
nullptr && password !=
nullptr &&
407 WiFi.status() != WL_CONNECTED) {
409 WiFi.begin(network, password);
410 while (WiFi.status() != WL_CONNECTED) {
416 return WiFi.status() == WL_CONNECTED;
418 return WiFi.status() == WL_CONNECTED;
void stop()
Public generic methods.
Definition: AudioRuntime.h:27