arduino-audio-tools
Loading...
Searching...
No Matches
URLStream.h
Go to the documentation of this file.
1#pragma once
2
3#include "AudioToolsConfig.h"
4
5#if defined(USE_WIFI)
7#endif
8
13
14namespace audio_tools {
15
27 public:
28 URLStream(int readBufferSize = DEFAULT_BUFFER_SIZE) {
29 TRACED();
30 setReadBufferSize(readBufferSize);
31 }
32
33 URLStream(Client& clientPar, int readBufferSize = DEFAULT_BUFFER_SIZE) {
34 TRACED();
35 setReadBufferSize(readBufferSize);
36 setClient(clientPar);
37 }
38
39 URLStream(const char* network, const char* password,
40 int readBufferSize = DEFAULT_BUFFER_SIZE) {
41 TRACED();
42 setReadBufferSize(readBufferSize);
45 }
46
47 URLStream(const URLStream&) = delete;
48
50 TRACED();
51 end();
52 if (client_secure != nullptr) {
53 delete client_secure;
54 client_secure = nullptr;
55 }
56 if (client_insecure != nullptr) {
57 delete client_insecure;
58 client_insecure = nullptr;
59 }
60 }
61
63 void setClient(Client& clientPar) override { client = &clientPar; }
64
66 void setSSID(const char* ssid) override { this->network = ssid; }
67
69 void setPassword(const char* password) override { this->password = password; }
70
72 void setReadBufferSize(int readBufferSize) {
73 read_buffer_size = readBufferSize;
74 }
75
77 virtual bool begin(const char* urlStr, const char* acceptMime = nullptr,
78 MethodID action = GET, const char* reqMime = "",
79 const char* reqData = "") override {
80 LOGI("%s: %s", LOG_METHOD, urlStr);
81 if (!preProcess(urlStr, acceptMime)) {
82 LOGE("preProcess failed");
83 return false;
84 }
85 int result = process<const char*>(action, url, reqMime, reqData);
86 if (result > 0) {
88 LOGI("contentLength: %d", (int)content_length);
89 if (content_length >= 0 && wait_for_data) {
91 }
92 }
93 total_read = 0;
94 active = result == 200;
95 LOGI("==> http result: %d", result);
96 return active;
97 }
98
100 virtual bool begin(const char* urlStr, const char* acceptMime,
101 MethodID action, const char* reqMime, Stream& reqData,
102 int len = -1) {
103 LOGI("%s: %s", LOG_METHOD, urlStr);
104 if (!preProcess(urlStr, acceptMime)) {
105 LOGE("preProcess failed");
106 return false;
107 }
108 int result = process<Stream&>(action, url, reqMime, reqData, len);
109 if (result > 0) {
111 LOGI("size: %d", (int)content_length);
112 if (content_length >= 0 && wait_for_data) {
114 }
115 }
116 total_read = 0;
117 active = result == 200;
118 LOGI("==> http status: %d", result);
119 return active;
120 }
121
123 virtual void end() override {
124 if (active) request.stop();
125 active = false;
126 clear();
127 }
128
129 virtual int available() override {
130 if (!active) return 0;
131
132 int result = request.available();
133 LOGD("available: %d", result);
134 return result;
135 }
136
137 virtual size_t readBytes(uint8_t* data, size_t len) override {
138 if (!active) return 0;
139
140 int read = request.read(data, len);
141 if (read < 0) {
142 read = 0;
143 }
144 total_read += read;
145 LOGD("readBytes %d -> %d", (int)len, read);
146 return read;
147 }
148
149 virtual int read() override {
150 if (!active) return -1;
151 // lazy allocation since this is rarely used
153
154 fillBuffer();
155 total_read++;
156 return isEOS() ? -1 : read_buffer[read_pos++];
157 }
158
159 virtual int peek() override {
160 if (!active) return -1;
161 // lazy allocation since this is rarely used
163
164 fillBuffer();
165 return isEOS() ? -1 : read_buffer[read_pos];
166 }
167
168 virtual void flush() override {}
169
170 virtual size_t write(uint8_t) override { return not_supported(0); }
171
172 virtual size_t write(const uint8_t*, size_t len) override {
173 return not_supported(0);
174 }
175
177 virtual HttpRequest& httpRequest() override { return request; }
178
179 operator bool() override { return active && request.isReady(); }
180
182 virtual void setTimeout(int ms) { client_timeout = ms; }
183
186 void setPowerSave(bool ps) override { is_power_save = ps; }
187
189 void setAutoCreateLines(bool flag) {
191 }
192
194 void setConnectionClose(bool close) override {
196 }
197
199 void clear() {
200 httpRequest().reply().clear();
203 read_pos = 0;
204 read_size = 0;
205 }
206
208 void addRequestHeader(const char* key, const char* value) override {
209 request.header().put(key, value);
210 }
211
213 const char* getReplyHeader(const char* key) override {
214 return request.reply().get(key);
215 }
216
218 void setOnConnectCallback(void (*callback)(
219 HttpRequest& request, Url& url, HttpRequestHeader& request_header)) {
221 }
222
224 void setWaitForData(bool flag) { wait_for_data = flag; }
225
227 int contentLength() override { return content_length; }
228
230 size_t totalRead() override { return total_read; }
231
233 bool waitForData (int timeout) override{
234 TRACED();
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;
240 // stop waiting if we got an error
241 int rc = request.reply().statusCode();
242 if (rc >= 300) {
243 LOGE("Error code %d recieved: stop waiting for reply", rc);
244 break;
245 }
246 delay(500);
247 }
248 }
249 int avail = request.available();
250 LOGD("available: %d", avail);
251 return avail > 0;
252 }
253
255 const char* urlStr() override { return url_str.c_str(); }
256
258 void setCACert(const char* cert) override{
259 if (client_secure!=nullptr) client_secure->setCACert(cert);
260 }
261
263 size_t size() { return content_length; }
264
265 protected:
270 long total_read = 0;
271 // buffered single byte read
274 uint16_t read_pos = 0;
275 uint16_t read_size = 0;
276 bool active = false;
277 bool wait_for_data = true;
278 Client* client = nullptr; // client defined via setClient
279 WiFiClient* client_insecure = nullptr; // wifi client for http
280 WiFiClientSecure* client_secure = nullptr; // wifi client for https
282 unsigned long handshake_timeout = URL_HANDSHAKE_TIMEOUT; // 120000
283 bool is_power_save = false;
284 // optional
285 const char* network = nullptr;
286 const char* password = nullptr;
287
288 bool preProcess(const char* urlStr, const char* acceptMime) {
289 TRACED();
290 url_str = urlStr;
292 int result = -1;
293
294 // close it - if we have an active connection
295 if (active) end();
296
297 // optional: login if necessary if no external client is defined
298 if (client == nullptr){
299 if (!login()){
300 LOGE("Not connected");
301 return false;
302 }
303 }
304
305 // request.reply().setAutoCreateLines(false);
306 if (acceptMime != nullptr) {
307 request.setAcceptMime(acceptMime);
308 }
309
310 // setup client
314
315#if defined(ESP32)
316 // Performance optimization for ESP32
317 if (!is_power_save) {
318 esp_wifi_set_ps(WIFI_PS_NONE);
319 }
320#endif
321
322 return true;
323 }
324
326 template <typename T>
327 int process(MethodID action, Url& url, const char* reqMime, T reqData,
328 int len = -1) {
329 TRACED();
330 // keep icy across redirect requests ?
331 const char* icy = request.header().get("Icy-MetaData");
332
333 int status_code = request.process(action, url, reqMime, reqData, len);
334 // redirect
335 while (request.reply().isRedirectStatus()) {
336 const char* redirect_url = request.reply().get(LOCATION);
337 if (redirect_url != nullptr) {
338 LOGW("Redirected to: %s", redirect_url);
339 url.setUrl(redirect_url);
340 Client* p_client = &getClient(url.isSecure());
341 p_client->stop();
342 request.setClient(*p_client);
343 if (icy) {
344 request.header().put("Icy-MetaData", icy);
345 }
346 status_code = request.process(action, url, reqMime, reqData, len);
347 } else {
348 LOGE("Location is null");
349 break;
350 }
351 }
352 return status_code;
353 }
354
356 Client& getClient(bool isSecure) {
357 if (isSecure) {
358 if (client_secure == nullptr) {
362#ifdef ESP32
363 #if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3,0,0)
364 client_secure->setConnectionTimeout(client_timeout);
365 #endif
366 client_secure->setHandshakeTimeout(handshake_timeout);
367#endif
368#ifdef RP2040_HOWER
369 client_secure->setTLSConnectTimeout(client_timeout);
370#endif
371 }
372 LOGI("WiFiClientSecure");
373 return *client_secure;
374 }
375 if (client_insecure == nullptr) {
378#ifdef ESP32
379 #if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3,0,0)
380 client_insecure->setConnectionTimeout(client_timeout);
381 #else
383 #endif
384#endif
385 LOGI("WiFiClient");
386 }
387 return *client_insecure;
388 }
389
390 inline void fillBuffer() {
391 if (isEOS()) {
392 // if we consumed all bytes we refill the buffer
394 read_pos = 0;
395 }
396 }
397
398 inline bool isEOS() { return read_pos >= read_size; }
399
400 bool login() {
401 if (network != nullptr && password != nullptr &&
402 WiFi.status() != WL_CONNECTED) {
403 TRACEI();
405 while (WiFi.status() != WL_CONNECTED) {
406 Serial.print(".");
407 delay(500);
408 }
409 Serial.println();
410 delay(10);
411 return WiFi.status() == WL_CONNECTED;
412 }
413 return WiFi.status() == WL_CONNECTED;
414 }
415};
416
417
418#if defined(USE_CONCURRENCY)
421
422#endif
423
424} // namespace audio_tools
static HardwareSerial Serial
Definition Arduino.h:179
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define LOG_METHOD
Definition AudioToolsConfig.h:74
MethodID
supported http methods
Definition HttpTypes.h:3
@ GET
Definition HttpTypes.h:5
#define DEFAULT_BUFFER_SIZE
Definition avr.h:20
Definition Arduino.h:162
void stop()
Definition Arduino.h:164
Definition Arduino.h:136
Abstract Base class for all URLStream implementations.
Definition AbstractURLStream.h:17
virtual int not_supported(int out, const char *msg="")
Definition BaseStream.h:173
HttpHeader & clear()
clears the data
Definition HttpHeader.h:74
int statusCode()
Definition HttpHeader.h:210
HttpHeader & put(const char *key, const char *value)
Definition HttpHeader.h:86
bool isRedirectStatus()
returns true if the status code is >=300 and < 400
Definition HttpHeader.h:303
void setAutoCreateLines(bool is_auto_line)
automatically create new lines
Definition HttpHeader.h:295
const char * get(const char *key)
Definition HttpHeader.h:155
Reading and writing of Http Requests.
Definition HttpHeader.h:400
Simple API to process get, put, post, del http requests I tried to use Arduino HttpClient,...
Definition HttpRequest.h:25
void setTimeout(size_t timeoutMs)
Defines the client timeout in ms.
Definition HttpRequest.h:350
virtual HttpReplyHeader & reply()
Definition HttpRequest.h:163
virtual int process(MethodID action, Url &url, const char *mime, const char *data, int lenData=-1)
Definition HttpRequest.h:207
size_t contentLength()
Definition HttpRequest.h:181
int available() override
Definition HttpRequest.h:54
virtual void setConnection(const char *connection)
Definition HttpRequest.h:171
void setClient(Client &client)
Definition HttpRequest.h:35
void setOnConnectCallback(void(*callback)(HttpRequest &request, Url &url, HttpRequestHeader &request_header))
Callback which allows you to add additional paramters dynamically.
Definition HttpRequest.h:344
virtual int read(uint8_t *str, int len)
Definition HttpRequest.h:128
bool isReady()
Definition HttpRequest.h:194
virtual void stop()
Definition HttpRequest.h:76
virtual HttpRequestHeader & header()
provides access to the request header
Definition HttpRequest.h:166
virtual void setAcceptMime(const char *mime)
Definition HttpRequest.h:179
Str which keeps the data on the heap. We grow the allocated memory only if the copy source is not fit...
Definition Str.h:24
virtual const char * c_str()
provides the string value as const char*
Definition StrView.h:380
URLStream implementation for the ESP32 based on a separate FreeRTOS task: the.
Definition URLStreamBufferedT.h:162
Represents the content of a URL as Stream. We use the WiFi.h API. If you run into performance issues,...
Definition URLStream.h:26
Client * client
Definition URLStream.h:278
bool active
Definition URLStream.h:276
size_t size()
Returns the content length of the request.
Definition URLStream.h:263
size_t totalRead() override
returns the total number of bytes read from the stream
Definition URLStream.h:230
WiFiClient * client_insecure
Definition URLStream.h:279
void fillBuffer()
Definition URLStream.h:390
bool preProcess(const char *urlStr, const char *acceptMime)
Definition URLStream.h:288
bool wait_for_data
Definition URLStream.h:277
virtual int read() override
Definition URLStream.h:149
long total_read
Definition URLStream.h:270
HttpRequest request
Definition URLStream.h:266
bool login()
Definition URLStream.h:400
virtual bool begin(const char *urlStr, const char *acceptMime=nullptr, MethodID action=GET, const char *reqMime="", const char *reqData="") override
Execute http request: by default we use a GET request.
Definition URLStream.h:77
const char * network
Definition URLStream.h:285
uint16_t read_size
Definition URLStream.h:275
virtual void setTimeout(int ms)
Defines the client timeout in ms.
Definition URLStream.h:182
bool waitForData(int timeout) override
Waits for some data - returns false if the request has failed.
Definition URLStream.h:233
void setConnectionClose(bool close) override
Sets if the connection should be close automatically.
Definition URLStream.h:194
~URLStream()
Definition URLStream.h:49
virtual size_t readBytes(uint8_t *data, size_t len) override
Definition URLStream.h:137
uint16_t read_buffer_size
Definition URLStream.h:273
void setReadBufferSize(int readBufferSize)
Defines the buffer that is used by individual read() or peek() calls.
Definition URLStream.h:72
WiFiClientSecure * client_secure
Definition URLStream.h:280
void setPowerSave(bool ps) override
Definition URLStream.h:186
Client & getClient(bool isSecure)
Determines the client.
Definition URLStream.h:356
int client_timeout
Definition URLStream.h:281
void setWaitForData(bool flag)
Defines if the stream should wait for data after the request has been sent.
Definition URLStream.h:224
virtual size_t write(uint8_t) override
Definition URLStream.h:170
int process(MethodID action, Url &url, const char *reqMime, T reqData, int len=-1)
Process the Http request and handle redirects.
Definition URLStream.h:327
Url url
Definition URLStream.h:268
Str url_str
Definition URLStream.h:267
void addRequestHeader(const char *key, const char *value) override
Adds/Updates a request header.
Definition URLStream.h:208
virtual int peek() override
Definition URLStream.h:159
URLStream(int readBufferSize=DEFAULT_BUFFER_SIZE)
Definition URLStream.h:28
URLStream(const URLStream &)=delete
const char * password
Definition URLStream.h:286
void setSSID(const char *ssid) override
Sets the ssid that will be used for logging in (when calling begin)
Definition URLStream.h:66
URLStream(const char *network, const char *password, int readBufferSize=DEFAULT_BUFFER_SIZE)
Definition URLStream.h:39
virtual size_t write(const uint8_t *, size_t len) override
Definition URLStream.h:172
virtual bool begin(const char *urlStr, const char *acceptMime, MethodID action, const char *reqMime, Stream &reqData, int len=-1)
Execute e.g. http POST request which submits the content as a stream.
Definition URLStream.h:100
const char * urlStr() override
returns the url as string
Definition URLStream.h:255
bool isEOS()
Definition URLStream.h:398
void setClient(Client &clientPar) override
(Re-)defines the client
Definition URLStream.h:63
Vector< uint8_t > read_buffer
Definition URLStream.h:272
void setCACert(const char *cert) override
Define the Root PEM Certificate for SSL.
Definition URLStream.h:258
void setOnConnectCallback(void(*callback)(HttpRequest &request, Url &url, HttpRequestHeader &request_header))
Callback which allows you to add additional paramters dynamically.
Definition URLStream.h:218
URLStream(Client &clientPar, int readBufferSize=DEFAULT_BUFFER_SIZE)
Definition URLStream.h:33
void clear()
Releases the memory from the request and reply.
Definition URLStream.h:199
uint16_t read_pos
Definition URLStream.h:274
int contentLength() override
returns the content length
Definition URLStream.h:227
void setAutoCreateLines(bool flag)
If set to true, new undefined reply parameters will be stored.
Definition URLStream.h:189
unsigned long handshake_timeout
Definition URLStream.h:282
void setPassword(const char *password) override
Sets the password that will be used for logging in (when calling begin)
Definition URLStream.h:69
virtual void end() override
Ends the request and releases the memory.
Definition URLStream.h:123
long content_length
Definition URLStream.h:269
virtual HttpRequest & httpRequest() override
provides access to the HttpRequest
Definition URLStream.h:177
bool is_power_save
Definition URLStream.h:283
virtual void flush() override
Definition URLStream.h:168
virtual int available() override
Definition URLStream.h:129
const char * getReplyHeader(const char *key) override
Provides the value of the reply header for the given key.
Definition URLStream.h:213
URL parser which breaks a full url string up into its individual parts.
Definition Url.h:22
bool isSecure()
Definition Url.h:42
void setUrl(const char *url)
Definition Url.h:44
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool resize(size_t newSize, T value)
Definition Vector.h:266
Definition WiFiClientSecureZephyr.h:24
void setInsecure()
Definition WiFiClientSecureZephyr.h:44
bool setCACert(const uint8_t *pem, size_t len)
Definition WiFiClientSecureZephyr.h:37
Definition WiFiClientZephyr.h:44
void setTimeout(uint32_t timeout_ms)
Definition WiFiClientZephyr.h:269
bool begin(const char *ssid, const char *password)
Definition WiFiZephyr.h:51
wifi_status_t status()
Definition WiFiZephyr.h:85
#define URL_CLIENT_TIMEOUT
Definition esp8266.h:23
#define URL_HANDSHAKE_TIMEOUT
Definition esp8266.h:24
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
void delay(uint32_t ms)
Definition Arduino.h:255
@ WL_CONNECTED
Definition WiFiZephyr.h:30
static WiFiZephyr WiFi
Definition WiFiZephyr.h:230
static const char * LOCATION
Definition HttpHeader.h:32
static const char * CON_KEEP_ALIVE
Definition HttpHeader.h:20
static const char * CON_CLOSE
Definition HttpHeader.h:19
uint32_t millis()
Returns the milliseconds since the start.
Definition Arduino.h:256
WiFiClientZephyr WiFiClient
Definition WiFiClientZephyr.h:311
WiFiClientSecureZephyr WiFiClientSecure
Definition WiFiClientSecureZephyr.h:117