You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+41-25Lines changed: 41 additions & 25 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -35,6 +35,10 @@ Read on to see how StreamUtils can help you!
35
35
How to add buffering to a Stream?
36
36
---------------------------------
37
37
38
+
> [!WARNING]
39
+
> Adding a buffer only makes sense for **unbuffered** streams.
40
+
> For example, there is **no benefit to adding a buffer to serial ports** because they already include an internal buffer.
41
+
38
42
### Buffering read operations
39
43
40
44
Sometimes, you can significantly improve performance by reading many bytes at once.
@@ -57,16 +61,16 @@ ReadBufferingStream bufferedFile{file, 64}; // <- HERE
57
61
deserializeJson(doc, bufferedFile);
58
62
```
59
63
60
-
Unfortunately, this optimization is only possible if:
61
-
62
-
1.`Stream.readBytes()` is declared `virtual` in your Arduino Code (as it's the case for ESP8266), and
63
-
2. the derived class has an optimized implementation of `readBytes()` (as it's the case for SPIFFS' `File`).
64
-
65
-
When possible, prefer `ReadBufferingClient` to `ReadBufferingStream` because `Client` defines a `read()` method similar to `readBytes()`, except this one is `virtual` on all platforms.
66
-
67
-
If memory allocation fails, `ReadBufferingStream` behaves as if no buffer was used: it forwards all calls to the upstream `Stream`.
64
+
> [!IMPORTANT]
65
+
> This optimization only works when:
66
+
>
67
+
> 1.`Stream::readBytes()` is declared `virtual` in the Arduino Core (as it's the case for ESP8266), and
68
+
> 2. the derived class has an optimized implementation of `readBytes()` (as it's the case for SPIFFS' `File`).
69
+
>
70
+
> For this reason, **prefer `ReadBufferingClient` to `ReadBufferingStream`** because `Client::read()` is `virtual` on all platforms.
68
71
69
-
Adding a buffer only makes sense for **unbuffered** streams. For example, there is **no benefit to adding a buffer to serial ports** because they already include an internal buffer.
72
+
> [!NOTE]
73
+
> If memory allocation fails, `ReadBufferingStream` behaves as if no buffer was used: it forwards all calls to the upstream `Stream`.
`flush()` sends the remaining data; if you forget to call it, the end of the message will be missing. The destructor of `WriteBufferingStream` calls `flush()`, so you can remove this line if you destroy the decorator immediately.
96
+
> [!CAUTION]
97
+
> `flush()` sends the remaining data; if you forget to call it, the end of the message will be missing.
93
98
94
-
If memory allocation fails, `WriteBufferingStream` behaves as if no buffer was used: it forwards all calls to the upstream `Stream`.
99
+
> [!TIP]
100
+
> The destructor of `WriteBufferingStream` calls `flush()`, so you can remove this line if you destroy the decorator immediately.
95
101
96
-
Adding a buffer only makes sense for **unbuffered** streams. For example, there is **no benefit to adding a buffer to serial ports** because they already include an internal buffer.
102
+
> [!NOTE]
103
+
> If memory allocation fails, `WriteBufferingStream` behaves as if no buffer was used: it forwards all calls to the upstream `Stream`.
97
104
98
105
How to add logging to a stream?
99
106
-------------------------------
100
107
101
108
### Logging write operations
102
109
103
-
When debugging a program that makes HTTP requests, you first want to check whether the request is correct. With this library, you can decorate the `EthernetClient` or the `WiFiClient` to log everything to the serial.
110
+
When debugging a program that makes HTTP requests, you first want to check whether the request is correct. With this library, you can decorate `EthernetClient` or `WiFiClient` to log everything to the serial port.
@@ -126,7 +133,7 @@ Everything you write to `loggingClient` is written to `client` and logged to `Se
126
133
127
134
### Logging read operations
128
135
129
-
Similarly, you often want to see what the HTTP server sent back. With this library, you can decorate the `EthernetClient` or the `WiFiClient` to log everything to the serial.
136
+
Similarly, you often want to see what the HTTP server sent back. With this library, you can decorate `EthernetClient` or `WiFiClient` to log everything to the serial port.
`loggingClient` forwards all operations to `client` and logs read operations to `Serial`.
150
157
151
-
⚠ **WARNING** ⚠
152
-
If your program receives data from one serial port and logs to another, **ensure the latter runs at a much higher baud rate**. Logging must be at least ten times faster, or it will slow down the receiving port, which may drop incoming bytes.
158
+
> [!CAUTION]
159
+
> If your program receives data from one serial port and logs to another, **ensure the latter runs at a much higher baud rate**.
160
+
> Logging must be at least 10 times faster, or it will slow down the receiving port, which may drop incoming bytes.
153
161
154
162
### Logging read and write operations
155
163
@@ -185,7 +193,7 @@ How to use error-correction codes (ECC)?
185
193
StreamUtils supports the [Hamming(7, 4)](https://en.wikipedia.org/wiki/Hamming(7,4)) error-correction code, which encodes 4 bits of data into 7 bits by adding three parity bits.
186
194
These extra bits increase the amount of traffic but allow correcting any one-bit error within the 7 bits.
187
195
188
-
If you use this encoding on an 8-bit channel, it effectively doubles the amount of traffic. However, if you use an [`HardwareSerial`](https://www.arduino.cc/reference/en/language/functions/communication/serial/) instance (like `Serial`, `Serial1`...), you can slightly reduce the overhead by configuring the ports as a 7-bit channel, like so:
196
+
If you use this encoding on an 8-bit channel, it effectively doubles the amount of traffic. However, if you use a [`HardwareSerial`](https://www.arduino.cc/reference/en/language/functions/communication/serial/) instance (like `Serial`, `Serial1`...), you can slightly reduce the overhead by configuring the ports as a 7-bit channel, like so:
189
197
190
198
```c++
191
199
// Initialize serial port with 9600 bauds, 7 bits of data, no parity, and one stop bit
@@ -269,7 +277,9 @@ wireStream.print("This is a very very long message that I'm sending!");
269
277
Wire.endTransmission();
270
278
```
271
279
272
-
As you can see, we use the `wait()` function as a hook to flush the Wire transmission buffer. Notice that we pass `false` to [`endTransmission()`](https://www.arduino.cc/en/Reference/WireEndTransmission) so that it sends the data but doesn't actually stop the transmission.
280
+
> [!NOTE]
281
+
> We use the `wait()` function as a hook to flush the Wire transmission buffer.
282
+
> Notice that we pass `false` to [`endTransmission()`](https://www.arduino.cc/en/Reference/WireEndTransmission) so that it sends the data but doesn't actually stop the transmission.
273
283
274
284
275
285
How to use a `String` as a stream?
@@ -302,7 +312,7 @@ Temperature = 22.30 °C
302
312
303
313
### Reading from a `String`
304
314
305
-
Similarly, there are cases where you have a `String`, but you need to pass a `Stream` to some other piece of code. In that case, use `StringStream`; it's similar to `StrintPrint`, except you can also read from it.
315
+
Similarly, there are cases where you have a `String`, but you need to pass a `Stream` to some other piece of code. In that case, use `StringStream`; it's similar to `StringPrint`, except you can also read from it.
HTTP servers can send their response in multiple parts using [Chunked Transfer Encoding](https://en.wikipedia.org/wiki/Chunked_transfer_encoding). Clients using HTTP 1.1 must support this encoding as it's not optional and is dictated by the server.
363
+
HTTP servers can send responses in multiple parts using [Chunked Transfer Encoding](https://en.wikipedia.org/wiki/Chunked_transfer_encoding). Clients using HTTP 1.1 must support this encoding as it's not optional and is dictated by the server.
354
364
355
365
`ChunkDecodingStream` and `ChunkDecodingClient` are decorators that decode the chunks and make the response available as a regular stream.
Note that `HTTPClient` already performs chunk decoding **if** you use `getString()`, but you might want to use `getStream()` to avoid buffering the entire response in memory.
400
+
> [!WARNING]
401
+
> `HTTPClient` already performs chunk decoding when you use `getString()`.
402
+
> Only use `ChunkDecodingStream` if you use `getStream()` as in the example above.
391
403
392
-
Also, you can avoid chunked transfer encoding by downgrading the HTTP version to 1.0. `HTTPClient` allows you to do that by calling `useHTTP10(true)` before sending the request.
404
+
> [!TIP]
405
+
> You can avoid chunked transfer encoding by downgrading the HTTP version to 1.0.
406
+
> `HTTPClient` does this if you call `useHTTP10(true)` before sending the request.
393
407
394
408
Summary
395
409
-------
@@ -413,7 +427,8 @@ See the equivalence table below.
Prefer `XxxClient` to `XxxStream` because, unlike `Stream::readBytes()`, `Client::read()` is virtual on all cores and therefore allows optimized implementations.
430
+
> [!TIP]
431
+
> Prefer `XxxClient` to `XxxStream` because, unlike `Stream::readBytes()`, `Client::read()` is virtual on all cores and therefore allows optimized implementations.
417
432
418
433
419
434
Portability
@@ -436,5 +451,6 @@ It has been tested on the following cores:
436
451
*[STM32 Roger's Core](https://github.com/rogerclarkmelbourne/Arduino_STM32) (no EEPROM support)
0 commit comments