first
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
lib/libraies-master
|
||||
|
||||
7
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
}
|
||||
5
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"C_Cpp.clang_format_fallbackStyle": "{BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 0}",
|
||||
"C_Cpp.formatting": "clangFormat",
|
||||
"C_Cpp.default.forcedInclude": []
|
||||
}
|
||||
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Dmitry Borisenko
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
6
README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# IoTManager
|
||||
Это модульная система беспроводной автоматизации на базе ESP32/ESP8266 микроконтроллеров и приложения IoT Manager.
|
||||
Телеграм канал обсуждения приложения и системы автоматизации https://t.me/IoTmanager
|
||||
# [Инструкция](https://github.com/IoTManagerProject/IoTManager/wiki)
|
||||
|
||||

|
||||
14
data_svelte/build/bundle.css
Normal file
2
data_svelte/build/bundle.js
Normal file
0
data_svelte/check.json
Normal file
37
data_svelte/config.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "IoTmanager",
|
||||
"chipID": "",
|
||||
"apssid": "IoTmanager",
|
||||
"appass": "",
|
||||
"routerssid": "dlink",
|
||||
"routerpass": "",
|
||||
"timezone": 1,
|
||||
"ntp": "pool.ntp.org",
|
||||
"mqttServer": "91.204.228.124",
|
||||
"mqttPort": 1883,
|
||||
"mqttPrefix": "/iotTest3",
|
||||
"mqttUser": "rise",
|
||||
"mqttPass": "23ri22se32",
|
||||
"mqttServer2": "M2.WQTT.RU",
|
||||
"mqttPort2": 8021,
|
||||
"mqttPrefix2": "/iotTest3",
|
||||
"mqttUser2": "rise",
|
||||
"mqttPass2": "hostel3333",
|
||||
"scen": "1",
|
||||
"telegramApi": "1416711569:AAEI0j83GmXqwzb_gnK1B0Am0gDwZoJt5xo",
|
||||
"telegonof": "0",
|
||||
"teleginput": "0",
|
||||
"autos": "1",
|
||||
"weblogin": "admin",
|
||||
"webpass": "admin",
|
||||
"MqttIn": "0",
|
||||
"MqttOut": "0",
|
||||
"blink": "0",
|
||||
"oneWirePin": "2",
|
||||
"serverip": "http://206.189.49.244",
|
||||
"uart": "0",
|
||||
"uartS": "9600",
|
||||
"uartTX": "12",
|
||||
"uartRX": "13",
|
||||
"grafmax": "0"
|
||||
}
|
||||
BIN
data_svelte/favicon.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
17
data_svelte/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
||||
|
||||
<title>Svelte app</title>
|
||||
|
||||
<link rel='icon' type='image/png' href='/favicon.png'>
|
||||
<link rel='stylesheet' href='/build/bundle.css'>
|
||||
|
||||
<script defer src='/build/bundle.js'></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
542
data_svelte/setup.json
Normal file
@@ -0,0 +1,542 @@
|
||||
[
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 1,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 2,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 3,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 4,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 5,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 6,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 7,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 8,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 9,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 10,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 11,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 12,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 13,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 14,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 15,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 16,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 17,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 18,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 19,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 20,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 21,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 22,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 23,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 24,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 25,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 26,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 27,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 28,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 29,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 30,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 31,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 32,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 33,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 34,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 1,
|
||||
"topic": "/prefix/123456-123456/btn1"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn1",
|
||||
"gpio": 35,
|
||||
"inv": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button-out",
|
||||
"web": {
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "Освещение",
|
||||
"order": 2,
|
||||
"topic": "/prefix/123456-123456/btn2"
|
||||
},
|
||||
"set": {
|
||||
"id": "btn2",
|
||||
"gpio": 36,
|
||||
"inv": false
|
||||
}
|
||||
}
|
||||
]
|
||||
BIN
data_svelte/sync.ffs_db
Normal file
14
include/main.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <Arduino.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <FS.h>
|
||||
#include <StreamUtils.h>
|
||||
|
||||
#include "LittleFS.h"
|
||||
|
||||
extern FS LittleFS;
|
||||
using littlefs_impl::LittleFSConfig;
|
||||
extern FS* filesystem;
|
||||
#define FileFS LittleFS
|
||||
#define FS_NAME "LittleFS"
|
||||
|
||||
void setupESP();
|
||||
9
include/rest.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "main.h"
|
||||
|
||||
File seekFile(const String& filename, size_t position = 0);
|
||||
const String writeFile(const String& filename, const String& str);
|
||||
const String readFile(const String& filename, size_t max_size);
|
||||
const String filepath(const String& filename);
|
||||
bool fileSystemInit();
|
||||
String prettyBytes(size_t size);
|
||||
bool cutFile(const String& src, const String& dst);
|
||||
5
lib/ArduinoStreamUtils/.clang-format
Normal file
@@ -0,0 +1,5 @@
|
||||
BasedOnStyle: Google
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
IncludeBlocks: Preserve
|
||||
4
lib/ArduinoStreamUtils/.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
github: bblanchon
|
||||
custom:
|
||||
- https://arduinojson.org/book/
|
||||
- https://donate.benoitblanchon.fr/
|
||||
121
lib/ArduinoStreamUtils/.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
name: Continuous Integration
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Unit Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install
|
||||
run: sudo apt-get install -y lcov
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Configure
|
||||
run: cmake -DCOVERAGE=true .
|
||||
- name: Build
|
||||
run: cmake --build .
|
||||
- name: Run tests
|
||||
run: ctest --output-on-failure .
|
||||
- name: Capture coverage data
|
||||
run: lcov --capture --no-external --directory . --output-file coverage.info
|
||||
- name: Filter coverage data
|
||||
run: lcov --remove coverage.info "$(pwd)/extras/*" --output-file coverage_filtered.info
|
||||
- name: Generate coverage report
|
||||
run: mkdir coverage && genhtml coverage_filtered.info -o coverage -t ArduinoJson
|
||||
- name: Upload coverage report
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: coverage
|
||||
path: coverage
|
||||
- name: Upload to Coveralls
|
||||
uses: coverallsapp/github-action@master
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
path-to-lcov: coverage_filtered.info
|
||||
|
||||
platformio:
|
||||
name: PlatformIO
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: atmelavr
|
||||
board: leonardo
|
||||
eeprom: true
|
||||
softwareserial: true
|
||||
- platform: espressif8266
|
||||
board: huzzah
|
||||
eeprom: true
|
||||
softwareserial: true
|
||||
- platform: espressif32
|
||||
board: esp32dev
|
||||
eeprom: true
|
||||
softwareserial: false
|
||||
- platform: atmelsam
|
||||
board: mkr1000USB
|
||||
eeprom: false
|
||||
softwareserial: false
|
||||
- platform: teensy
|
||||
board: teensy31
|
||||
eeprom: true
|
||||
softwareserial: true
|
||||
- platform: ststm32
|
||||
board: nucleo_f031k6
|
||||
eeprom: true
|
||||
softwareserial: true
|
||||
- platform: nordicnrf52
|
||||
board: adafruit_feather_nrf52840
|
||||
eeprom: false
|
||||
softwareserial: true
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.platformio
|
||||
~/.cache/pip
|
||||
key: ${{ runner.os }}-platformio
|
||||
- name: Set up Python 3.x
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install PlatformIO
|
||||
run: pip install platformio
|
||||
- name: Install platform "${{ matrix.platform }}"
|
||||
run: platformio platform install ${{ matrix.platform }}
|
||||
- name: Install adafruit-nrfutil
|
||||
if: ${{ matrix.platform == 'nordicnrf52' }}
|
||||
run: pip3 install adafruit-nrfutil
|
||||
- name: Include Adafruit_TinyUSB.h # https://github.com/adafruit/Adafruit_nRF52_Arduino/issues/653
|
||||
if: ${{ matrix.platform == 'nordicnrf52' }}
|
||||
run: find examples/ -name '*.ino' -exec sed -i 's/\(#include <StreamUtils.h>\)/\1\n#include <Adafruit_TinyUSB.h>/' {} +
|
||||
- name: Build EepromRead
|
||||
if: ${{ matrix.eeprom }}
|
||||
run: platformio ci "examples/EepromRead/EepromRead.ino" -l '.' -b ${{ matrix.board }}
|
||||
- name: Build EepromWrite
|
||||
if: ${{ matrix.eeprom }}
|
||||
run: platformio ci "examples/EepromWrite/EepromWrite.ino" -l '.' -b ${{ matrix.board }}
|
||||
- name: Build HammingSerial1
|
||||
run: platformio ci "examples/HammingSerial1/HammingSerial1.ino" -l '.' -b ${{ matrix.board }}
|
||||
- name: Build HammingSoftwareSerial
|
||||
if: ${{ matrix.softwareserial }}
|
||||
run: platformio ci "examples/HammingSoftwareSerial/HammingSoftwareSerial.ino" -l '.' -b ${{ matrix.board }}
|
||||
- name: Build Logger
|
||||
run: platformio ci "examples/Logger/Logger.ino" -l '.' -b ${{ matrix.board }}
|
||||
- name: Build ReadBuffer
|
||||
run: platformio ci "examples/ReadBuffer/ReadBuffer.ino" -l '.' -b ${{ matrix.board }}
|
||||
- name: Build ReadLogger
|
||||
run: platformio ci "examples/ReadLogger/ReadLogger.ino" -l '.' -b ${{ matrix.board }}
|
||||
- name: Build StringPrint
|
||||
run: platformio ci "examples/StringPrint/StringPrint.ino" -l '.' -b ${{ matrix.board }}
|
||||
- name: Build StringStream
|
||||
run: platformio ci "examples/StringStream/StringStream.ino" -l '.' -b ${{ matrix.board }}
|
||||
- name: Build WriteBuffer
|
||||
run: platformio ci "examples/WriteBuffer/WriteBuffer.ino" -l '.' -b ${{ matrix.board }}
|
||||
- name: Build WriteLogger
|
||||
run: platformio ci "examples/WriteLogger/WriteLogger.ino" -l '.' -b ${{ matrix.board }}
|
||||
2
lib/ArduinoStreamUtils/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/build
|
||||
|
||||
79
lib/ArduinoStreamUtils/CHANGELOG.md
Normal file
@@ -0,0 +1,79 @@
|
||||
StreamUtils - Change log
|
||||
========================
|
||||
|
||||
HEAD
|
||||
----
|
||||
|
||||
* Support `Print::flush()` on AVR
|
||||
|
||||
1.6.1 (2021/94/05)
|
||||
-----
|
||||
|
||||
* Add example `HammingSerial1.ino`
|
||||
* Add support for STM32 (issue #11)
|
||||
|
||||
|
||||
1.6.0 (2020/11/20)
|
||||
-----
|
||||
|
||||
* Add `HammingPrint<7, 4>`
|
||||
* Add `HammingStream<7, 4>`, `HammingEncodingStream<7, 4>`, and `HammingDecodingStream<7, 4>`
|
||||
* Add `HammingClient<7, 4>`, `HammingEncodingClient<7, 4>`, and `HammingDecodingClient<7, 4>`
|
||||
|
||||
1.5.0 (2020/08/04)
|
||||
-----
|
||||
|
||||
* Add `WaitingPrint`, `WriteWaitingClient`, and `WriteWaitingStream`.
|
||||
|
||||
1.4.1 (2020/07/01)
|
||||
-----
|
||||
|
||||
* Fix unwanted waits in `ReadBufferingClient` and `ReadBufferingStream`.
|
||||
* Stop calling `Client::read()` in place of `Stream::readBytes()`,
|
||||
because it doesn't honor the timeout.
|
||||
|
||||
1.4.0 (2020/03/30)
|
||||
-----
|
||||
|
||||
* Add `EepromStream`
|
||||
* Add support for ESP32
|
||||
* Add support for Teensy
|
||||
|
||||
1.3.0 (2020/01/20)
|
||||
-----
|
||||
|
||||
* Move auxiliary content to `extras/` to comply with new library layout
|
||||
* Add `StringPrint` and `StringStream`
|
||||
* Extract `StreamUtils.hpp`, same as `StreamUtils.h` except it keeps everything in the `StreamUtils` namespace.
|
||||
|
||||
1.2.2 (2019/07/18)
|
||||
-----
|
||||
|
||||
* Fix `BufferingPrint` taking `Stream` instead of `Print` (issue #3)
|
||||
* Fix `LoggingPrint` not forwarding call to `Print::flush()`
|
||||
* Fix missing `override` specifiers
|
||||
|
||||
1.2.1 (2019/06/05)
|
||||
-----
|
||||
|
||||
* Remove workaround for ESP8266 core 2.5.0
|
||||
* Fix compatibility with ESP8266 core 2.5.1+ (issue #2)
|
||||
|
||||
1.2.0 (2019/05/01)
|
||||
-----
|
||||
|
||||
* Add `LoggingPrint`
|
||||
* Add `BufferingPrint`
|
||||
* Add `WriteLoggingClient`, `ReadLoggingClient`, and `LoggingClient`
|
||||
* Add `WriteBufferingClient` and `ReadBufferingClient`
|
||||
|
||||
1.1.0 (2019/04/20)
|
||||
-----
|
||||
|
||||
* Add `LoggingStream` (=`ReadLoggingStream` + `WriteLoggingStream`)
|
||||
|
||||
1.0.0 (2019/04/14)
|
||||
-----
|
||||
|
||||
* Add `ReadBufferingStream` and `WriteBufferingStream`
|
||||
* Add `ReadLoggingStream` and `WriteLoggingStream`
|
||||
18
lib/ArduinoStreamUtils/CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
# StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
# Copyright Benoit Blanchon 2019-2021
|
||||
# MIT License
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(StreamUtils)
|
||||
|
||||
enable_testing()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if(${COVERAGE})
|
||||
set(CMAKE_CXX_FLAGS "-fprofile-arcs -ftest-coverage -g -O0")
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
||||
add_subdirectory(extras/test)
|
||||
10
lib/ArduinoStreamUtils/LICENSE.md
Normal file
@@ -0,0 +1,10 @@
|
||||
The MIT License (MIT)
|
||||
---------------------
|
||||
|
||||
Copyright © 2019 Benoit BLANCHON
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
369
lib/ArduinoStreamUtils/README.md
Normal file
@@ -0,0 +1,369 @@
|
||||
StreamUtils: Power-ups for Arduino Streams
|
||||
==========================================
|
||||
|
||||
[](https://www.ardu-badge.com/StreamUtils/1.6.1)
|
||||
[](https://github.com/bblanchon/ArduinoStreamUtils/actions/workflows/ci.yml)
|
||||
[](https://coveralls.io/github/bblanchon/ArduinoStreamUtils)
|
||||
|
||||
The *stream* is an essential abstraction in Arduino; we find it in many places:
|
||||
|
||||
* [`HardwareSerial`](https://www.arduino.cc/reference/en/language/functions/communication/serial/)
|
||||
* [`SoftwareSerial`](https://www.arduino.cc/en/Reference/SoftwareSerial)
|
||||
* [`File`](https://www.arduino.cc/en/Reference/SD)
|
||||
* [`EthernetClient`](https://www.arduino.cc/en/Reference/EthernetClient)
|
||||
* [`WiFiClient`](https://www.arduino.cc/en/Reference/WiFiClient)
|
||||
* [`Wire`](https://www.arduino.cc/en/reference/wire)
|
||||
* and many others...
|
||||
|
||||
This library provides some helper classes and functions for dealing with streams.
|
||||
|
||||
For example, with this library, you can:
|
||||
|
||||
* speed of your program by buffering the data it reads from a file
|
||||
* reduce the number of packets sent over WiFi by buffering the data you send
|
||||
* improve the reliability of a serial connection by adding error correction codes
|
||||
* debug your program more easily by logging what it sends to a Web service
|
||||
* send large data with the [Wire library](https://www.arduino.cc/en/reference/wire)
|
||||
* use a `String` or EEPROM with a stream interface
|
||||
|
||||
Read on to see how StreamUtils can help you!
|
||||
|
||||
|
||||
How to add buffering to a Stream?
|
||||
---------------------------------
|
||||
|
||||
### Buffering read operations
|
||||
|
||||
Sometimes, you can significantly improve performance by reading many bytes at once.
|
||||
For example, [according to SPIFFS's wiki](https://github.com/pellepl/spiffs/wiki/Performance-and-Optimizing#reading-files), it's much faster to read files in chunks of 64 bytes than reading them one byte at a time.
|
||||
|
||||

|
||||
|
||||
To buffer the input, simply decorate the original `Stream` with `ReadBufferingStream`. For example, suppose your program reads a JSON document from SPIFFS, like that:
|
||||
|
||||
```c++
|
||||
File file = SPIFFS.open("example.json", "r");
|
||||
deserializeJson(doc, file);
|
||||
```
|
||||
|
||||
Then you simply need to insert one line to greatly improve the reading speed:
|
||||
|
||||
```c++
|
||||
File file = SPIFFS.open("example.json", "r");
|
||||
ReadBufferingStream bufferedFile{file, 64}; // <- HERE
|
||||
deserializeJson(doc, bufferedFile);
|
||||
```
|
||||
|
||||
Unfortunately, this optimization is only possible if:
|
||||
|
||||
1. `Stream.readBytes()` is declared `virtual` in your Arduino Code (as it's the case for ESP8266), and
|
||||
2. the derived class has an optimized implementation of `readBytes()` (as it's the case for SPIFFS' `File`).
|
||||
|
||||
When possible, prefer `ReadBufferingClient` to `ReadBufferingStream` because `Client` defines a `read()` method similar to `readBytes()`, except that this one is `virtual` on all platforms.
|
||||
|
||||
If memory allocation fails, `ReadBufferingStream` behaves as if no buffer was used: it forwards all calls to the upstream `Stream`.
|
||||
|
||||
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.
|
||||
|
||||
### Buffering write operations
|
||||
|
||||
Similarly, you can improve performance significantly by writing many bytes at once.
|
||||
For example, if you write to `WiFiClient` one bytes at a time, it will be very slow; it's much faster if you send large chunks.
|
||||
|
||||

|
||||
|
||||
To add a buffer, decorate the original `Stream` with `WriteBufferingStream`. For example, if your program sends a JSON document via `WiFiClient`, like that:
|
||||
|
||||
```c++
|
||||
serializeJson(doc, wifiClient);
|
||||
```
|
||||
|
||||
Then, you just need to add two lines:
|
||||
|
||||
```c++
|
||||
WriteBufferingStream bufferedWifiClient{wifiClient, 64};
|
||||
serializeJson(doc, bufferedWifiClient);
|
||||
bufferedWifiClient.flush();
|
||||
```
|
||||
|
||||
`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.
|
||||
|
||||
If memory allocation fails, `WriteBufferingStream` behaves as if no buffer was used: it forwards all calls to the upstream `Stream`.
|
||||
|
||||
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.
|
||||
|
||||
How to add logging to a stream?
|
||||
-------------------------------
|
||||
|
||||
### Logging write operations
|
||||
|
||||
When debugging a program that makes HTTP requests, the first thing you want to check is that the request is correct. With this library, you can decorate the `EthernetClient` or the `WiFiClient` to log everything to the serial.
|
||||
|
||||

|
||||
|
||||
For example, if you program is:
|
||||
|
||||
```c++
|
||||
client.println("GET / HTTP/1.1");
|
||||
client.println("User-Agent: Arduino");
|
||||
// ...
|
||||
```
|
||||
|
||||
Then, you just need to create the decorator, and update the calls to `println()`:
|
||||
|
||||
```c++
|
||||
WriteLoggingStream loggingClient(client, Serial);
|
||||
loggingClient.println("GET / HTTP/1.1");
|
||||
loggingClient.println("User-Agent: Arduino");
|
||||
// ...
|
||||
```
|
||||
|
||||
Everything you write to `loggingClient` is written to `client` and logged to `Serial`.
|
||||
|
||||
|
||||
### Logging read operations
|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
For example, if you program is:
|
||||
|
||||
```c++
|
||||
char response[256];
|
||||
client.readBytes(response, 256);
|
||||
```
|
||||
|
||||
Then, you just need to create the decorator, and update the calls to `readBytes()`:
|
||||
|
||||
```c++
|
||||
ReadLoggingStream loggingClient(client, Serial);
|
||||
char response[256];
|
||||
loggingClient.readBytes(response, 256);
|
||||
// ...
|
||||
```
|
||||
|
||||
`loggingClient` forwards all operations to `client` and logs read operation to `Serial`.
|
||||
|
||||
⚠ **WARNING** ⚠
|
||||
If your program receives data from one serial port and logs to another one, **make sure the latter runs at a much higher speed**. Logging must be at least ten times faster, or it will slow down the receiving port, which may drop incoming bytes.
|
||||
|
||||
### Logging read and write operations
|
||||
|
||||
Of course, you could log read and write operations by combining `ReadLoggingStream` and `WriteLoggingStream`, but there is a simpler solution: `LoggingStream`.
|
||||
|
||||

|
||||
|
||||
As usual, if your program is:
|
||||
|
||||
```c++
|
||||
client.println("GET / HTTP/1.1");
|
||||
client.println("User-Agent: Arduino");
|
||||
|
||||
char response[256];
|
||||
client.readBytes(response, 256);
|
||||
```
|
||||
|
||||
Then decorate `client` and replace the calls:
|
||||
|
||||
```c++
|
||||
LoggingStream loggingClient(client, Serial);
|
||||
|
||||
loggingClient.println("GET / HTTP/1.1");
|
||||
loggingClient.println("User-Agent: Arduino");
|
||||
|
||||
char response[256];
|
||||
loggingClient.readBytes(response, 256);
|
||||
```
|
||||
|
||||
How to use error-correction codes (ECC)?
|
||||
----------------------------------------
|
||||
|
||||
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.
|
||||
These extra bits increase the amount of traffic but allow correcting any one-bit error within the 7 bits.
|
||||
|
||||
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:
|
||||
|
||||
```c++
|
||||
// Initialize serial port with 9600 bauds, 7-bits of data, no parity, and one stop bit
|
||||
Serial1.begin(9600, SERIAL_7N1);
|
||||
```
|
||||
|
||||
### Adding parity bits
|
||||
|
||||
The class `HammingEncodingStream<7, 4>` decorates an existing `Stream` to include parity bits in every write operation.
|
||||
|
||||

|
||||
|
||||
You can use this class like so:
|
||||
|
||||
```c++
|
||||
HammingEncodingStream<7, 4> eccSerial(Serial1);
|
||||
|
||||
eccSerial.println("Hello world!");
|
||||
```
|
||||
|
||||
Like every `Stream` decorator in this library, `HammingEncodingStream<7, 4>` supports all `Stream` methods (like `print()`, `println()`, `read()`, `readBytes()`, and `available()`).
|
||||
|
||||
### Correcting errors
|
||||
|
||||
The class `HammingDecodingStream<7, 4>` decorates an existing `Stream` to decode parity bits in every read operation.
|
||||
|
||||

|
||||
|
||||
You can use this class like so:
|
||||
|
||||
```c++
|
||||
HammingDecodingStream<7, 4> eccSerial(Serial1);
|
||||
|
||||
char buffer[256];
|
||||
size_t n = eccSerial.readBytes(buffer, n);
|
||||
```
|
||||
|
||||
Like every `Stream` decorator in this library, `HammingDecodingStream<7, 4>` supports all `Stream` methods (like `print()`, `println()`, `read()`, `readBytes()`, and `available()`).
|
||||
|
||||
### Encoding and decoding in both directions
|
||||
|
||||
The class `HammingStream<7, 4>` combines the features of `HammingEncodingStream<7, 4>` and `HammingDecodingStream<7, 4>`, which is very useful when you do a two-way communication.
|
||||
|
||||

|
||||
|
||||
You can use this class like so:
|
||||
|
||||
```c++
|
||||
HammingStream<7, 4> eccSerial(Serial1);
|
||||
|
||||
eccSerial.println("Hello world!");
|
||||
|
||||
char buffer[256];
|
||||
size_t n = eccSerial.readBytes(buffer, n);
|
||||
```
|
||||
|
||||
Like every `Stream` decorator in this library, `HammingStream<7, 4>` supports all `Stream` methods (like `print()`, `println()`, `read()`, `readBytes()`, and `available()`).
|
||||
|
||||
|
||||
How to retry write operations?
|
||||
------------------------------
|
||||
|
||||
Sometimes, a stream is limited to the capacity of its internal buffer. In that case, you must wait before sending more data.
|
||||
To solve this problem, StreamUtils provides the `WriteWaitingStream` decorator:
|
||||
|
||||

|
||||
|
||||
This function repeatedly waits and retries until it times out.
|
||||
You can customize the `wait()` function; by default, it's [`yield()`](https://www.arduino.cc/en/Reference/SchedulerYield).
|
||||
|
||||
For example, if you want to send more than 32 bytes with the [Wire library](https://www.arduino.cc/en/reference/wire), you can do:
|
||||
|
||||
```c++
|
||||
WriteWaitingStream wireStream(Wire, [](){
|
||||
Wire.endTransmission(false); // <- don't forget this argument
|
||||
Wire.beginTransmission(address);
|
||||
});
|
||||
|
||||
Wire.beginTransmission(address);
|
||||
wireStream.print("This is a very very long message that I'm sending!");
|
||||
Wire.endTransmission();
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
|
||||
How to use a `String` as a stream?
|
||||
---------------------
|
||||
|
||||
### Writing to a `String`
|
||||
|
||||
Sometimes, you use a piece of code that expects a `Print` instance (like `ReadLoggingStream`), but you want the output in a `String` instead of a regular `Stream`.
|
||||
In that case, use the `StringPrint` class. It wraps a `String` within a `Print` implementation.
|
||||
|
||||

|
||||
|
||||
Here is how you can use it:
|
||||
|
||||
```c++
|
||||
StringPrint stream;
|
||||
|
||||
stream.print("Temperature = ");
|
||||
stream.print(22.3);
|
||||
stream.print(" °C");
|
||||
|
||||
String result = stream.str();
|
||||
```
|
||||
|
||||
At the end of this snippet, the string `result` contains:
|
||||
|
||||
```
|
||||
Temperature = 22.30 °C
|
||||
```
|
||||
|
||||
### Reading from a `String`
|
||||
|
||||
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 read as well.
|
||||
|
||||

|
||||
|
||||
|
||||
How to use EEPROM as a stream?
|
||||
------------------------------
|
||||
|
||||
SteamUtils also allows using EEPROM as a stream. Simply create an instance of `EepromStream` and specify the start address and the size of the region you want to expose.
|
||||
|
||||

|
||||
|
||||
For example, it allows you to save a JSON document in EEPROM:
|
||||
|
||||
```c++
|
||||
EepromStream eepromStream(0, 128);
|
||||
serializeJson(doc, eepromStream);
|
||||
eepromStream.flush(); // <- calls EEPROM.commit() on ESP (optional)
|
||||
```
|
||||
|
||||
In the same way, you can read a JSON document from EEPROM:
|
||||
|
||||
```c++
|
||||
EepromStream eepromStream(0, 128);
|
||||
deserializeJson(doc, eepromStream);
|
||||
```
|
||||
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
Some of the decorators are also available for the `Print` and `Client` classes.
|
||||
See the equivalence table below.
|
||||
|
||||
| Purpose | `Client` | `Stream` | `Print` |
|
||||
|:-----------------------------------|:------------------------|:------------------------|:-----------------|
|
||||
| Log *write* operations | `WriteLoggingClient` | `WriteLoggingStream` | `LoggingPrint` |
|
||||
| Log *read* operations | `ReadLoggingClient` | `ReadLoggingStream` | |
|
||||
| Log *read* and *write* op. | `LoggingClient` | `LoggingStream` | |
|
||||
| Buffer *write* operations | `WriteBufferingClient` | `WriteBufferingStream` | `BufferingPrint` |
|
||||
| Buffer *read* operations | `ReadBufferingClient` | `ReadBufferingStream` | |
|
||||
| Repeat *write* operations | `WriteWaitingClient` | `WriteWaitingStream` | `WaitingPrint` |
|
||||
| Use `String` as a stream | | `StringStream` | `StringPrint` |
|
||||
| Use EEPROM as a stream | | `EepromStream` | |
|
||||
| Error correction (decode only) | `HammingDecodingClient` | `HammingDecodingStream` | |
|
||||
| Error correction (encode only) | `HammingEncodingClient` | `HammingEncodingStream` | `HammingPrint` |
|
||||
| Error correction (encode & decode) | `HammingClient` | `HammingStream` | |
|
||||
|
||||
When possible, prefer `ReadBufferingClient` to `ReadBufferingStream` because `Client::read()` often provides an optimized implementation.
|
||||
|
||||
|
||||
Portability
|
||||
-----------
|
||||
|
||||
This library relies on the definitions of `Client`, `Print`, and `Stream`, which unfortunately differ from one core to another.
|
||||
|
||||
It has been tested on the following cores:
|
||||
|
||||
* [AVR](https://github.com/arduino/ArduinoCore-avr)
|
||||
* [ESP32](https://github.com/espressif/arduino-esp32)
|
||||
* [ESP8266](https://github.com/esp8266/Arduino)
|
||||
* [nRF52](https://github.com/adafruit/Adafruit_nRF52_Arduino)
|
||||
* [SAMD](https://github.com/arduino/ArduinoCore-samd)
|
||||
* [STM32](https://github.com/stm32duino/Arduino_Core_STM32)
|
||||
* [Teensy](https://github.com/PaulStoffregen/cores)
|
||||
|
||||
If your core is not supported, please [open an issue](https://github.com/bblanchon/ArduinoStreamUtils/issues/new).
|
||||
Thank you for your understanding.
|
||||
63
lib/ArduinoStreamUtils/examples/EepromRead/EepromRead.ino
Normal file
@@ -0,0 +1,63 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to read from EEPROM
|
||||
|
||||
#include <StreamUtils.h>
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial)
|
||||
continue;
|
||||
|
||||
#if STREAMUTILS_ENABLE_EEPROM
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||
Serial.println("Initializing EEPROM...");
|
||||
EEPROM.begin(512);
|
||||
#endif
|
||||
|
||||
Serial.println("Make sure to run the EepromWrite example first!");
|
||||
|
||||
Serial.println("Reading EEPROM... ");
|
||||
EepromStream s(0, 12);
|
||||
Serial.print(s.readString());
|
||||
|
||||
#else
|
||||
Serial.println("EepromStream is not supported on this platform. Sorry");
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* *
|
||||
* Love this project? *
|
||||
* Star it on GitHub! *
|
||||
* *
|
||||
* .,,. *
|
||||
* ,,:1. *
|
||||
* ,.,:;1 *
|
||||
* .,,,::;: *
|
||||
* ,,,,::;;. *
|
||||
* .,,,:::;;; *
|
||||
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
|
||||
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
|
||||
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
|
||||
* .;;;:::,,,,,,,,::::::;:::;;1t: *
|
||||
* :;;:,,,,,,::::::;;;;;;l1 *
|
||||
* ,,,,:::::::;;;;;;l *
|
||||
* .,,,,::::;;;;;;;:::: *
|
||||
* ,,,,,:::;;;;;::,:::1 *
|
||||
* ,,,,,::;;;t1:,,:::::;l *
|
||||
* .,,,,:;;ll ;::::::;;, *
|
||||
* ,,,:;ll. .1:::;;l *
|
||||
* .,:lt, .1;;l: *
|
||||
* *
|
||||
* https://github.com/bblanchon/ArduinoStreamUtils *
|
||||
* *
|
||||
*****************************************************/
|
||||
69
lib/ArduinoStreamUtils/examples/EepromWrite/EepromWrite.ino
Normal file
@@ -0,0 +1,69 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to read from EEPROM
|
||||
|
||||
#include <StreamUtils.h>
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial)
|
||||
continue;
|
||||
|
||||
#if STREAMUTILS_ENABLE_EEPROM
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||
Serial.println("Initializing EEPROM...");
|
||||
EEPROM.begin(512);
|
||||
#endif
|
||||
|
||||
Serial.println("Writing to EEPROM...");
|
||||
EepromStream s(0, 12);
|
||||
s.print("Hello World!");
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||
Serial.println("Saving...");
|
||||
s.flush(); // only required on ESP
|
||||
#endif
|
||||
|
||||
Serial.println("Done!");
|
||||
Serial.println("Now, run the EepromRead example.");
|
||||
|
||||
#else
|
||||
Serial.println("EepromStream is not supported on this platform. Sorry");
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* *
|
||||
* Love this project? *
|
||||
* Star it on GitHub! *
|
||||
* *
|
||||
* .,,. *
|
||||
* ,,:1. *
|
||||
* ,.,:;1 *
|
||||
* .,,,::;: *
|
||||
* ,,,,::;;. *
|
||||
* .,,,:::;;; *
|
||||
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
|
||||
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
|
||||
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
|
||||
* .;;;:::,,,,,,,,::::::;:::;;1t: *
|
||||
* :;;:,,,,,,::::::;;;;;;l1 *
|
||||
* ,,,,:::::::;;;;;;l *
|
||||
* .,,,,::::;;;;;;;:::: *
|
||||
* ,,,,,:::;;;;;::,:::1 *
|
||||
* ,,,,,::;;;t1:,,:::::;l *
|
||||
* .,,,,:;;ll ;::::::;;, *
|
||||
* ,,,:;ll. .1:::;;l *
|
||||
* .,:lt, .1;;l: *
|
||||
* *
|
||||
* https://github.com/bblanchon/ArduinoStreamUtils *
|
||||
* *
|
||||
*****************************************************/
|
||||
@@ -0,0 +1,68 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to use Hamming codes for error correction
|
||||
//
|
||||
// To run this program, you need two boards that support Serial1 with the same
|
||||
// voltage. For example: Arduino Mega, Leonardo, or Nano Every (all 5V boards)
|
||||
//
|
||||
// Connect the TX pin of one board to the RX pin of the other and vice-versa.
|
||||
|
||||
#include <StreamUtils.h>
|
||||
|
||||
HammingStream<7, 4> eccSerial1(Serial1);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
continue;
|
||||
|
||||
Serial1.begin(9600);
|
||||
while (!Serial)
|
||||
continue;
|
||||
|
||||
// Discard any remaining data in the input buffer
|
||||
while (Serial1.available())
|
||||
Serial1.read();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Did we receive something?
|
||||
if (eccSerial1.available())
|
||||
// Print it
|
||||
Serial.write(eccSerial1.read());
|
||||
|
||||
// Do we have something to send?
|
||||
if (Serial.available())
|
||||
// Sent it
|
||||
eccSerial1.write(Serial.read());
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* *
|
||||
* Love this project? *
|
||||
* Star it on GitHub! *
|
||||
* *
|
||||
* .,,. *
|
||||
* ,,:1. *
|
||||
* ,.,:;1 *
|
||||
* .,,,::;: *
|
||||
* ,,,,::;;. *
|
||||
* .,,,:::;;; *
|
||||
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
|
||||
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
|
||||
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
|
||||
* .;;;:::,,,,,,,,::::::;:::;;1t: *
|
||||
* :;;:,,,,,,::::::;;;;;;l1 *
|
||||
* ,,,,:::::::;;;;;;l *
|
||||
* .,,,,::::;;;;;;;:::: *
|
||||
* ,,,,,:::;;;;;::,:::1 *
|
||||
* ,,,,,::;;;t1:,,:::::;l *
|
||||
* .,,,,:;;ll ;::::::;;, *
|
||||
* ,,,:;ll. .1:::;;l *
|
||||
* .,:lt, .1;;l: *
|
||||
* *
|
||||
* https://github.com/bblanchon/ArduinoStreamUtils *
|
||||
* *
|
||||
*****************************************************/
|
||||
@@ -0,0 +1,67 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to use Hamming codes for error correction
|
||||
//
|
||||
// To run this program, you need two boards connected like so:
|
||||
// BOARD 1 - BOARD 2
|
||||
// pin 10 - pin 11
|
||||
// pin 11 - pin 10
|
||||
//
|
||||
// SoftwareSerial is here for demonstration purposes; please don't use it in
|
||||
// production, as it is notoriously unreliable.
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
#include <StreamUtils.h>
|
||||
|
||||
SoftwareSerial linkSerial(10, 11); // RX, TX
|
||||
HammingStream<7, 4> eccLinkSerial(linkSerial);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
continue;
|
||||
|
||||
linkSerial.begin(4800);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Did we receive something?
|
||||
if (eccLinkSerial.available())
|
||||
// Print it
|
||||
Serial.write(eccLinkSerial.read());
|
||||
|
||||
// Do we have something to send?
|
||||
if (Serial.available())
|
||||
// Sent it
|
||||
eccLinkSerial.write(Serial.read());
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* *
|
||||
* Love this project? *
|
||||
* Star it on GitHub! *
|
||||
* *
|
||||
* .,,. *
|
||||
* ,,:1. *
|
||||
* ,.,:;1 *
|
||||
* .,,,::;: *
|
||||
* ,,,,::;;. *
|
||||
* .,,,:::;;; *
|
||||
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
|
||||
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
|
||||
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
|
||||
* .;;;:::,,,,,,,,::::::;:::;;1t: *
|
||||
* :;;:,,,,,,::::::;;;;;;l1 *
|
||||
* ,,,,:::::::;;;;;;l *
|
||||
* .,,,,::::;;;;;;;:::: *
|
||||
* ,,,,,:::;;;;;::,:::1 *
|
||||
* ,,,,,::;;;t1:,,:::::;l *
|
||||
* .,,,,:;;ll ;::::::;;, *
|
||||
* ,,,:;ll. .1:::;;l *
|
||||
* .,:lt, .1;;l: *
|
||||
* *
|
||||
* https://github.com/bblanchon/ArduinoStreamUtils *
|
||||
* *
|
||||
*****************************************************/
|
||||
61
lib/ArduinoStreamUtils/examples/Logger/Logger.ino
Normal file
@@ -0,0 +1,61 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to log what goes through a Stream, both reads and
|
||||
// writes operations.
|
||||
|
||||
#include <StreamUtils.h>
|
||||
|
||||
// Create a new stream that will forward all calls to Serial, and log to Serial.
|
||||
// Everything will be written twice to the Serial!
|
||||
LoggingStream loggingStream(Serial, Serial);
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial)
|
||||
continue;
|
||||
|
||||
// Write to the serial port.
|
||||
// Because loggingStream logs each write operation, the string will we written
|
||||
// twice
|
||||
loggingStream.println("Hello World!");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Read from the serial port.
|
||||
// Because loggingStream logs each read operation, everything we read is
|
||||
// printed back to the serial port.
|
||||
while (loggingStream.available()) {
|
||||
loggingStream.read();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* *
|
||||
* Love this project? *
|
||||
* Star it on GitHub! *
|
||||
* *
|
||||
* .,,. *
|
||||
* ,,:1. *
|
||||
* ,.,:;1 *
|
||||
* .,,,::;: *
|
||||
* ,,,,::;;. *
|
||||
* .,,,:::;;; *
|
||||
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
|
||||
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
|
||||
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
|
||||
* .;;;:::,,,,,,,,::::::;:::;;1t: *
|
||||
* :;;:,,,,,,::::::;;;;;;l1 *
|
||||
* ,,,,:::::::;;;;;;l *
|
||||
* .,,,,::::;;;;;;;:::: *
|
||||
* ,,,,,:::;;;;;::,:::1 *
|
||||
* ,,,,,::;;;t1:,,:::::;l *
|
||||
* .,,,,:;;ll ;::::::;;, *
|
||||
* ,,,:;ll. .1:::;;l *
|
||||
* .,:lt, .1;;l: *
|
||||
* *
|
||||
* https://github.com/bblanchon/ArduinoStreamUtils *
|
||||
* *
|
||||
*****************************************************/
|
||||
56
lib/ArduinoStreamUtils/examples/ReadBuffer/ReadBuffer.ino
Normal file
@@ -0,0 +1,56 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to buffer the read operations of a stream.
|
||||
//
|
||||
// Like "echo," it reads from the serial port and prints back the same thing.
|
||||
// What's interesting with this program is that it reads the input in chunks of
|
||||
// 64 bytes, even if it seems to read them one by one.
|
||||
|
||||
#include <StreamUtils.h>
|
||||
|
||||
ReadBufferingStream bufferedSerial{Serial, 64};
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial)
|
||||
continue;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Even if it looks like the bytes are extracted one by one, they are actually
|
||||
// read by chunks of 64 bytes and placed in a buffer.
|
||||
while (bufferedSerial.available()) {
|
||||
Serial.write(bufferedSerial.read());
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* *
|
||||
* Love this project? *
|
||||
* Star it on GitHub! *
|
||||
* *
|
||||
* .,,. *
|
||||
* ,,:1. *
|
||||
* ,.,:;1 *
|
||||
* .,,,::;: *
|
||||
* ,,,,::;;. *
|
||||
* .,,,:::;;; *
|
||||
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
|
||||
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
|
||||
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
|
||||
* .;;;:::,,,,,,,,::::::;:::;;1t: *
|
||||
* :;;:,,,,,,::::::;;;;;;l1 *
|
||||
* ,,,,:::::::;;;;;;l *
|
||||
* .,,,,::::;;;;;;;:::: *
|
||||
* ,,,,,:::;;;;;::,:::1 *
|
||||
* ,,,,,::;;;t1:,,:::::;l *
|
||||
* .,,,,:;;ll ;::::::;;, *
|
||||
* ,,,:;ll. .1:::;;l *
|
||||
* .,:lt, .1;;l: *
|
||||
* *
|
||||
* https://github.com/bblanchon/ArduinoStreamUtils *
|
||||
* *
|
||||
*****************************************************/
|
||||
55
lib/ArduinoStreamUtils/examples/ReadLogger/ReadLogger.ino
Normal file
@@ -0,0 +1,55 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to log what read from a Stream
|
||||
|
||||
#include <StreamUtils.h>
|
||||
|
||||
// Create a new stream that will forward all calls to Serial, and log to Serial.
|
||||
// It will write back everything it reads, just like "echo"
|
||||
ReadLoggingStream loggingStream(Serial, Serial);
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial)
|
||||
continue;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Read the serial port.
|
||||
// Because loggingStream write everything it read, the program will show what
|
||||
// you sent.
|
||||
while (Serial.available()) {
|
||||
loggingStream.write(Serial.read());
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* *
|
||||
* Love this project? *
|
||||
* Star it on GitHub! *
|
||||
* *
|
||||
* .,,. *
|
||||
* ,,:1. *
|
||||
* ,.,:;1 *
|
||||
* .,,,::;: *
|
||||
* ,,,,::;;. *
|
||||
* .,,,:::;;; *
|
||||
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
|
||||
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
|
||||
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
|
||||
* .;;;:::,,,,,,,,::::::;:::;;1t: *
|
||||
* :;;:,,,,,,::::::;;;;;;l1 *
|
||||
* ,,,,:::::::;;;;;;l *
|
||||
* .,,,,::::;;;;;;;:::: *
|
||||
* ,,,,,:::;;;;;::,:::1 *
|
||||
* ,,,,,::;;;t1:,,:::::;l *
|
||||
* .,,,,:;;ll ;::::::;;, *
|
||||
* ,,,:;ll. .1:::;;l *
|
||||
* .,:lt, .1;;l: *
|
||||
* *
|
||||
* https://github.com/bblanchon/ArduinoStreamUtils *
|
||||
* *
|
||||
*****************************************************/
|
||||
54
lib/ArduinoStreamUtils/examples/StringPrint/StringPrint.ino
Normal file
@@ -0,0 +1,54 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to use StringPrint
|
||||
|
||||
#include <StreamUtils.h>
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial)
|
||||
continue;
|
||||
|
||||
StringPrint stream;
|
||||
|
||||
stream.print("Temperature = ");
|
||||
stream.print(22.3);
|
||||
stream.print(" °C");
|
||||
|
||||
Serial.print(stream.str());
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// no used in this example
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* *
|
||||
* Love this project? *
|
||||
* Star it on GitHub! *
|
||||
* *
|
||||
* .,,. *
|
||||
* ,,:1. *
|
||||
* ,.,:;1 *
|
||||
* .,,,::;: *
|
||||
* ,,,,::;;. *
|
||||
* .,,,:::;;; *
|
||||
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
|
||||
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
|
||||
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
|
||||
* .;;;:::,,,,,,,,::::::;:::;;1t: *
|
||||
* :;;:,,,,,,::::::;;;;;;l1 *
|
||||
* ,,,,:::::::;;;;;;l *
|
||||
* .,,,,::::;;;;;;;:::: *
|
||||
* ,,,,,:::;;;;;::,:::1 *
|
||||
* ,,,,,::;;;t1:,,:::::;l *
|
||||
* .,,,,:;;ll ;::::::;;, *
|
||||
* ,,,:;ll. .1:::;;l *
|
||||
* .,:lt, .1;;l: *
|
||||
* *
|
||||
* https://github.com/bblanchon/ArduinoStreamUtils *
|
||||
* *
|
||||
*****************************************************/
|
||||
@@ -0,0 +1,55 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to use StringStream
|
||||
|
||||
#include <StreamUtils.h>
|
||||
|
||||
StringStream stream;
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial)
|
||||
continue;
|
||||
|
||||
stream.print("Temperature = ");
|
||||
stream.print(22.3);
|
||||
stream.print(" °C");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (stream.available() > 0) {
|
||||
Serial.print((char)stream.read());
|
||||
}
|
||||
delay(250);
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* *
|
||||
* Love this project? *
|
||||
* Star it on GitHub! *
|
||||
* *
|
||||
* .,,. *
|
||||
* ,,:1. *
|
||||
* ,.,:;1 *
|
||||
* .,,,::;: *
|
||||
* ,,,,::;;. *
|
||||
* .,,,:::;;; *
|
||||
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
|
||||
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
|
||||
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
|
||||
* .;;;:::,,,,,,,,::::::;:::;;1t: *
|
||||
* :;;:,,,,,,::::::;;;;;;l1 *
|
||||
* ,,,,:::::::;;;;;;l *
|
||||
* .,,,,::::;;;;;;;:::: *
|
||||
* ,,,,,:::;;;;;::,:::1 *
|
||||
* ,,,,,::;;;t1:,,:::::;l *
|
||||
* .,,,,:;;ll ;::::::;;, *
|
||||
* ,,,:;ll. .1:::;;l *
|
||||
* .,:lt, .1;;l: *
|
||||
* *
|
||||
* https://github.com/bblanchon/ArduinoStreamUtils *
|
||||
* *
|
||||
*****************************************************/
|
||||
62
lib/ArduinoStreamUtils/examples/WriteBuffer/WriteBuffer.ino
Normal file
@@ -0,0 +1,62 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to buffer writes to a stream.
|
||||
//
|
||||
// Like "echo," it reads from the serial port and prints back the same thing.
|
||||
// What's interesting with this program is that it writes in chunks of
|
||||
// 8 bytes, even if it seems to write them one by one.
|
||||
//
|
||||
// As you'll see, you need to type at least 8 bytes to see something. That's
|
||||
// because it waits for the buffered to be full before sending it to the serial.
|
||||
|
||||
#include <StreamUtils.h>
|
||||
|
||||
// Create a new Stream that buffers all writes to Serial
|
||||
WriteBufferingStream bufferedSerial{Serial, 8};
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial)
|
||||
continue;
|
||||
|
||||
Serial.println(F("Send at least 8 bytes to see the result"));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Even if it looks like the bytes are sent one by one, they are actual
|
||||
// written in chunks of 8 bytes.
|
||||
while (Serial.available()) {
|
||||
bufferedSerial.write(Serial.read());
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* *
|
||||
* Love this project? *
|
||||
* Star it on GitHub! *
|
||||
* *
|
||||
* .,,. *
|
||||
* ,,:1. *
|
||||
* ,.,:;1 *
|
||||
* .,,,::;: *
|
||||
* ,,,,::;;. *
|
||||
* .,,,:::;;; *
|
||||
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
|
||||
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
|
||||
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
|
||||
* .;;;:::,,,,,,,,::::::;:::;;1t: *
|
||||
* :;;:,,,,,,::::::;;;;;;l1 *
|
||||
* ,,,,:::::::;;;;;;l *
|
||||
* .,,,,::::;;;;;;;:::: *
|
||||
* ,,,,,:::;;;;;::,:::1 *
|
||||
* ,,,,,::;;;t1:,,:::::;l *
|
||||
* .,,,,:;;ll ;::::::;;, *
|
||||
* ,,,:;ll. .1:::;;l *
|
||||
* .,:lt, .1;;l: *
|
||||
* *
|
||||
* https://github.com/bblanchon/ArduinoStreamUtils *
|
||||
* *
|
||||
*****************************************************/
|
||||
55
lib/ArduinoStreamUtils/examples/WriteLogger/WriteLogger.ino
Normal file
@@ -0,0 +1,55 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to log what written to a Stream
|
||||
|
||||
#include <StreamUtils.h>
|
||||
|
||||
// Create a new stream that will forward all calls to Serial, and log to Serial.
|
||||
// Everything will be written twice to the Serial!
|
||||
WriteLoggingStream loggingStream(Serial, Serial);
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial)
|
||||
continue;
|
||||
|
||||
// Write to the serial port.
|
||||
// Because loggingStream logs each write operation, the string will we written
|
||||
// twice
|
||||
loggingStream.println("Hello World!");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* *
|
||||
* Love this project? *
|
||||
* Star it on GitHub! *
|
||||
* *
|
||||
* .,,. *
|
||||
* ,,:1. *
|
||||
* ,.,:;1 *
|
||||
* .,,,::;: *
|
||||
* ,,,,::;;. *
|
||||
* .,,,:::;;; *
|
||||
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
|
||||
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
|
||||
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
|
||||
* .;;;:::,,,,,,,,::::::;:::;;1t: *
|
||||
* :;;:,,,,,,::::::;;;;;;l1 *
|
||||
* ,,,,:::::::;;;;;;l *
|
||||
* .,,,,::::;;;;;;;:::: *
|
||||
* ,,,,,:::;;;;;::,:::1 *
|
||||
* ,,,,,::;;;t1:,,:::::;l *
|
||||
* .,,,,:;;ll ;::::::;;, *
|
||||
* ,,,:;ll. .1:::;;l *
|
||||
* .,:lt, .1;;l: *
|
||||
* *
|
||||
* https://github.com/bblanchon/ArduinoStreamUtils *
|
||||
* *
|
||||
*****************************************************/
|
||||
1
lib/ArduinoStreamUtils/extras/images/EepromStream.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker id="a" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker id="b" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker></defs><rect ry="1.228" rx="1.228" y=".25" x="38.123" height="13.985" width="41.57" fill="#ddd" stroke="#000" stroke-width=".5"/><path d="M28.451 4.631h24.7" fill="none" stroke="#00878f" stroke-width=".5" marker-end="url(#a)"/><rect ry="1.228" rx="1.228" y="3.277" x="54.378" height="7.611" width="21.726" fill="#fff" stroke="#000" stroke-width=".5"/><text y="8.632" x="56.992" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="8.467" letter-spacing="0" word-spacing="0" font-family="Consolas" stroke-width=".265"><tspan y="8.632" x="56.992" font-size="4.939">EEPROM</tspan></text><path d="M54.093 9.848H28.126" fill="none" stroke="#e47128" stroke-width=".5" marker-end="url(#b)"/></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker id="b" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker></defs><rect width="41.57" height="13.985" x="38.123" y=".25" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="-.263" y="8.925" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="-.263" y="8.925" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="93.777" y="8.454" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="93.777" y="8.454" font-size="4.939">original</tspan></text><path d="M28.451 4.634h61.238" fill="none" stroke="#00878f" stroke-width=".5" marker-end="url(#a)"/><path d="M89.689 9.708H28.45" fill="none" stroke="#e47128" stroke-width=".5" marker-end="url(#b)"/><path d="M43.874 9.708c13.976-.11 6.585 2.298 19.874 2.322 6.623.011 17.253.017 25.88.016" fill="none" stroke="#e47128" stroke-width=".3" stroke-dasharray=".60007511,.30003755"/><text y="11.539" x="60.257" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="3.52" font-family="Consolas" letter-spacing="0" word-spacing="0" fill="#e47128" stroke-width=".11"><tspan y="11.539" x="60.257" font-size="2.053">parity bits</tspan></text></svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker id="c" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="b" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker></defs><g transform="translate(98.669 59.515)"><rect ry="1.228" rx="1.228" y="-59.265" x="-60.546" height="13.985" width="41.57" fill="#ddd" stroke="#000" stroke-width=".5"/><path d="M-70.218-54.88H-8.98" fill="none" stroke="#00878f" stroke-width=".5" marker-end="url(#a)"/><path d="M-9.213-49.664h-61.33" fill="none" stroke="#e47128" stroke-width=".5" marker-end="url(#b)"/><text y="-50.59" x="-98.932" style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan y="-50.59" x="-98.932" font-size="4.939">decorated</tspan></text><text y="-51.061" x="-4.892" style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan y="-51.061" x="-4.892" font-size="4.939">original</tspan></text><path d="M-54.343-54.88c13.977.108 6.585-2.299 19.874-2.322 6.623-.012 16.862-.018 25.489-.017" fill="none" stroke="#00878f" stroke-width=".3" stroke-dasharray=".60000012,.30000006" marker-end="url(#c)"/><text y="-55.516" x="-37.96" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="3.52" font-family="Consolas" letter-spacing="0" word-spacing="0" fill="#00878f" stroke-width=".11"><tspan y="-55.516" x="-37.96" font-size="2.053">parity bits</tspan></text></g></svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
1
lib/ArduinoStreamUtils/extras/images/HammingStream.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker id="c" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker><marker id="b" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker></defs><rect width="41.57" height="13.985" x="38.123" y=".25" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="-.263" y="8.925" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="-.263" y="8.925" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="93.777" y="8.454" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="93.777" y="8.454" font-size="4.939">original</tspan></text><path d="M28.451 4.634h61.238" fill="none" stroke="#00878f" stroke-width=".5" marker-end="url(#a)"/><path d="M44.326 4.634c13.977.11 6.585-2.298 19.874-2.321 6.623-.012 16.862-.018 25.489-.017" fill="none" stroke="#00878f" stroke-width=".3" stroke-dasharray=".60000012,.30000006" marker-end="url(#b)"/><text y="3.999" x="60.709" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="3.52" font-family="Consolas" letter-spacing="0" word-spacing="0" fill="#00878f" stroke-width=".11"><tspan y="3.999" x="60.709" font-size="2.053">parity bits</tspan></text><path d="M89.689 9.708H28.45" fill="none" stroke="#e47128" stroke-width=".5" marker-end="url(#c)"/><path d="M43.874 9.708c13.976-.11 6.585 2.298 19.874 2.322 6.623.011 17.253.017 25.88.016" fill="none" stroke="#e47128" stroke-width=".3" stroke-dasharray=".60007511,.30003755"/><text y="11.539" x="60.257" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="3.52" font-family="Consolas" letter-spacing="0" word-spacing="0" fill="#e47128" stroke-width=".11"><tspan y="11.539" x="60.257" font-size="2.053">parity bits</tspan></text></svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
1
lib/ArduinoStreamUtils/extras/images/Logger.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="83.339" viewBox="0 0 115.175 22.05"><defs><marker id="d" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="c" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="b" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker></defs><g transform="translate(-39.95 -20.829)"><rect width="41.57" height="13.985" x="78.073" y="21.079" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><g fill="none" stroke-width=".5"><path d="M69.4 25.463h61.238" stroke="#00878f" marker-end="url(#a)" transform="translate(-.999)"/><path d="M130.405 30.68H69.076" stroke="#e47128" marker-end="url(#b)" transform="translate(-.999)"/></g><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="39.688" y="29.753" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="39.688" y="29.753" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="133.728" y="29.283" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="133.728" y="29.283" font-size="4.939">original</tspan></text></g><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="90.274" y="65.863" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265" transform="translate(-35.395 -44.826)"><tspan x="90.274" y="65.863" font-size="4.939">log</tspan></text><path d="M109.984 54.716c-12.353.036-13.228 2.364-14.03 7.49" fill="none" stroke="#e47128" stroke-width=".4" marker-end="url(#c)" transform="translate(-35.395 -44.826)"/><path d="M77.615 49.403c12.353.036 14.564 7.643 15.366 12.768" fill="none" stroke="#00878f" stroke-width=".4" marker-end="url(#d)" transform="translate(-35.395 -44.826)"/></svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
1
lib/ArduinoStreamUtils/extras/images/ReadBuffer.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="b" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker></defs><g transform="translate(-39.95 -20.829)"><rect width="41.57" height="13.985" x="78.073" y="21.079" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><g fill="none" stroke-width=".5"><path d="M69.4 25.463h61.238" stroke="#00878f" marker-end="url(#a)" transform="translate(-.999)"/><path d="M130.405 30.68H69.076" stroke="#e47128" marker-end="url(#b)" transform="translate(-.999)"/></g><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="39.688" y="29.753" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="39.688" y="29.753" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="133.728" y="29.283" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="133.728" y="29.283" font-size="4.939">original</tspan></text></g><g transform="translate(-39.95 -45.962)"><rect ry=".483" rx=".483" y="53.317" x="87.265" height="4.944" width="23.186" fill="#fff" stroke="#e47128" stroke-width=".5"/><text y="57.228" x="91.548" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="4.386" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan y="57.228" x="91.548">buffer</tspan></text></g></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
1
lib/ArduinoStreamUtils/extras/images/ReadLogger.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="83.339" viewBox="0 0 115.175 22.05"><defs><marker id="c" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="b" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker></defs><g transform="translate(-39.95 -20.829)"><rect width="41.57" height="13.985" x="78.073" y="21.079" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><g fill="none" stroke-width=".5"><path d="M69.4 25.463h61.238" stroke="#00878f" marker-end="url(#a)" transform="translate(-.999)"/><path d="M130.405 30.68H69.076" stroke="#e47128" marker-end="url(#b)" transform="translate(-.999)"/></g><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="39.688" y="29.753" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="39.688" y="29.753" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="133.728" y="29.283" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="133.728" y="29.283" font-size="4.939">original</tspan></text></g><text y="80.982" x="120.512" style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265" transform="translate(-65.633 -59.945)"><tspan y="80.982" x="120.512" font-size="4.939">log</tspan></text><path d="M140.223 69.835c-12.353.036-13.229 2.364-14.03 7.49" fill="none" stroke="#e47128" stroke-width=".4" marker-end="url(#c)" transform="translate(-65.633 -59.945)"/></svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
1
lib/ArduinoStreamUtils/extras/images/StringPrint.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker id="a" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker></defs><rect ry="1.228" rx="1.228" y=".25" x="38.123" height="13.985" width="41.57" fill="#ddd" stroke="#000" stroke-width=".5"/><path d="M28.451 4.631h24.7" fill="none" stroke="#00878f" stroke-width=".5" marker-end="url(#a)"/><rect ry="1.228" rx="1.228" y="3.277" x="54.378" height="7.611" width="21.726" fill="#fff" stroke="#000" stroke-width=".5"/><text y="8.632" x="56.992" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan y="8.632" x="56.992" font-size="4.939">String</tspan></text></svg>
|
||||
|
After Width: | Height: | Size: 984 B |
1
lib/ArduinoStreamUtils/extras/images/StringStream.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker id="a" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker id="b" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker></defs><rect ry="1.228" rx="1.228" y=".25" x="38.123" height="13.985" width="41.57" fill="#ddd" stroke="#000" stroke-width=".5"/><path d="M28.451 4.631h24.7" fill="none" stroke="#00878f" stroke-width=".5" marker-end="url(#a)"/><rect ry="1.228" rx="1.228" y="3.277" x="54.378" height="7.611" width="21.726" fill="#fff" stroke="#000" stroke-width=".5"/><text y="8.632" x="56.992" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan y="8.632" x="56.992" font-size="4.939">String</tspan></text><path d="M54.093 9.848H28.126" fill="none" stroke="#e47128" stroke-width=".5" marker-end="url(#b)"/></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
1
lib/ArduinoStreamUtils/extras/images/WriteBuffer.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="b" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker></defs><g transform="translate(-39.95 -20.829)"><rect width="41.57" height="13.985" x="78.073" y="21.079" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><g fill="none" stroke-width=".5"><path d="M69.4 25.463h61.238" stroke="#00878f" marker-end="url(#a)" transform="translate(-.999)"/><path d="M130.405 30.68H69.076" stroke="#e47128" marker-end="url(#b)" transform="translate(-.999)"/></g><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="39.688" y="29.753" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="39.688" y="29.753" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="133.728" y="29.283" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="133.728" y="29.283" font-size="4.939">original</tspan></text></g><g transform="translate(-39.95 -51.12)"><rect ry=".483" rx=".483" y="53.317" x="87.265" height="4.944" width="23.186" fill="#fff" stroke="#00878f" stroke-width=".5"/><text y="57.228" x="91.548" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="4.386" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan y="57.228" x="91.548">buffer</tspan></text></g></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
1
lib/ArduinoStreamUtils/extras/images/WriteLogger.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="83.337" viewBox="0 0 115.175 22.05"><defs><marker orient="auto" refY="0" refX="0" id="c" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="b" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker></defs><g transform="translate(-39.95 -20.829)"><rect width="41.57" height="13.985" x="78.073" y="21.079" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><g fill="none" stroke-width=".5"><path d="M69.4 25.463h61.238" stroke="#00878f" marker-end="url(#a)" transform="translate(-.999)"/><path d="M130.405 30.68H69.076" stroke="#e47128" marker-end="url(#b)" transform="translate(-.999)"/></g><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="39.688" y="29.753" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="39.688" y="29.753" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="133.728" y="29.283" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="133.728" y="29.283" font-size="4.939">original</tspan></text></g><text y="128.607" x="100.101" style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265" transform="translate(-45.222 -107.57)"><tspan y="128.607" x="100.101" font-size="4.939">log</tspan></text><path d="M87.442 112.147c12.353.036 14.565 7.643 15.367 12.769" fill="none" stroke="#00878f" stroke-width=".4" marker-end="url(#c)" transform="translate(-45.222 -107.57)"/></svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="435.307" height="81.808" viewBox="0 0 115.175 21.645"><defs><marker orient="auto" refY="0" refX="0" id="c" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#848484" fill-rule="evenodd" stroke="#848484" stroke-width=".375" stroke-linejoin="round"/></marker><marker id="a" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker><marker id="b" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker></defs><g transform="translate(-39.95 -21.077)"><rect width="41.57" height="13.985" x="78.073" y="28.487" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><path d="M129.407 38.617h-61.33" fill="none" stroke="#e47128" stroke-width=".5" marker-end="url(#a)"/><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="39.688" y="37.691" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="39.688" y="37.691" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="133.728" y="37.221" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="133.728" y="37.221" font-size="4.939">original</tspan></text><path d="M68.62 33.947H93.42c3.95 0 3.568-3.143 2.08-3.137-1.488.006-2.08 3.137 1.58 3.144l.254-.007c3.766-.096 3.368-3.125 1.88-3.119-1.49.006-1.88 3.12 1.541 3.12h.215c3.95 0 3.569-3.144 2.08-3.138-1.488.006-2.08 3.137 1.87 3.137h24.655" fill="none" stroke="#00878f" stroke-width=".5" marker-end="url(#b)"/><path d="M103.025 30.448v-5.364" id="d" fill="none" fill-rule="evenodd" stroke="#848484" stroke-width=".249" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="4" stroke-dasharray=".24941605,.24941605" stroke-dashoffset="0" stroke-opacity="1" marker-end="url(#c)"/><text style="line-height:125%;-inkscape-font-specification:Consolas" x="93.793" y="23.561" font-weight="400" font-size="3.416" font-family="Consolas" letter-spacing="0" word-spacing="0" fill="#848484" stroke-width=".107"><tspan x="93.793" y="23.561">wait()</tspan></text><use x="0" y="0" xlink:href="#d" id="e" transform="translate(-3.807)" width="100%" height="100%"/><use xlink:href="#e" transform="translate(-3.808)" width="100%" height="100%"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
137
lib/ArduinoStreamUtils/extras/test/BufferingPrintTest.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "FailingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Prints/BufferingPrint.hpp"
|
||||
#include "StreamUtils/Prints/SpyingPrint.hpp"
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("BufferingPrint") {
|
||||
StringPrint target;
|
||||
|
||||
StringPrint log;
|
||||
SpyingPrint spy{target, log};
|
||||
|
||||
GIVEN("capacity is 4") {
|
||||
BufferingPrint bufferingPrint{spy, 4};
|
||||
|
||||
SUBCASE("flush() calls write()") {
|
||||
bufferingPrint.write("ABC", 3);
|
||||
bufferingPrint.flush();
|
||||
|
||||
#if STREAMUTILS_PRINT_FLUSH_EXISTS
|
||||
CHECK(log.str() ==
|
||||
"write('ABC', 3) -> 3"
|
||||
"flush()");
|
||||
#else
|
||||
CHECK(log.str() == "write('ABC', 3) -> 3");
|
||||
#endif
|
||||
}
|
||||
|
||||
GIVEN("the buffer is empty") {
|
||||
SUBCASE("write(uint8_t)") {
|
||||
int n = bufferingPrint.write('A');
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("write(uint8_t) should flush") {
|
||||
bufferingPrint.write('A');
|
||||
bufferingPrint.write('B');
|
||||
bufferingPrint.write('C');
|
||||
bufferingPrint.write('D');
|
||||
bufferingPrint.write('E');
|
||||
|
||||
CHECK(log.str() == "write('ABCD', 4) -> 4");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,3) goes in buffer") {
|
||||
size_t n = bufferingPrint.write("ABC", 3);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,4) bypasses buffer") {
|
||||
size_t n = bufferingPrint.write("ABCD", 4);
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(log.str() == "write('ABCD', 4) -> 4");
|
||||
}
|
||||
SUBCASE("write(char*,2) bypasses buffer") {
|
||||
size_t n = bufferingPrint.write("ABCD", 4);
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(log.str() == "write('ABCD', 4) -> 4");
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("one byte in the buffer") {
|
||||
bufferingPrint.write('A');
|
||||
|
||||
SUBCASE("write(char*,3) goes in buffer and flush") {
|
||||
size_t n = bufferingPrint.write("BCD", 3);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "write('ABCD', 4) -> 4");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,7) bypasses") {
|
||||
size_t n = bufferingPrint.write("BCDEFGH", 7);
|
||||
|
||||
CHECK(n == 7);
|
||||
CHECK(log.str() ==
|
||||
"write('ABCD', 4) -> 4"
|
||||
"write('EFGH', 4) -> 4");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("capacity is 0") {
|
||||
BufferingPrint bufferingPrint{spy, 0};
|
||||
|
||||
// SUBCASE("capacity()") {
|
||||
// CHECK(bufferingPrint.capacity() == 0);
|
||||
// }
|
||||
|
||||
SUBCASE("write(uint8_t) forwards to target") {
|
||||
int n = bufferingPrint.write('X');
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "write('X') -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,1) forwards to target") {
|
||||
int n = bufferingPrint.write("A", 1);
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "write('A', 1) -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("flush()") {
|
||||
bufferingPrint.flush();
|
||||
|
||||
#if STREAMUTILS_PRINT_FLUSH_EXISTS
|
||||
CHECK(log.str() == "flush()");
|
||||
#else
|
||||
CHECK(log.str() == "");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("Destructor should flush") {
|
||||
{
|
||||
BufferingPrint bufferingPrint{spy, 10};
|
||||
bufferingPrint.write("ABC", 3);
|
||||
}
|
||||
|
||||
CHECK(log.str() == "write('ABC', 3) -> 3");
|
||||
}
|
||||
}
|
||||
104
lib/ArduinoStreamUtils/extras/test/CMakeLists.txt
Normal file
@@ -0,0 +1,104 @@
|
||||
# StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
# Copyright Benoit Blanchon 2019-2021
|
||||
# MIT License
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||
add_compile_options(-Wall -Wextra -Werror -Wundef)
|
||||
endif()
|
||||
|
||||
set(SOURCES
|
||||
BufferingPrintTest.cpp
|
||||
EepromStreamTest.cpp
|
||||
FailingAllocator.hpp
|
||||
HammingClientTest.cpp
|
||||
HammingDecodingClientTest.cpp
|
||||
HammingDecodingStreamTest.cpp
|
||||
HammingEncodingClientTest.cpp
|
||||
HammingEncodingStreamTest.cpp
|
||||
HammingPrintTest.cpp
|
||||
HammingStreamTest.cpp
|
||||
LoggingClientTest.cpp
|
||||
LoggingPrintTest.cpp
|
||||
LoggingStreamTest.cpp
|
||||
MemoryStreamTest.cpp
|
||||
ReadBufferingClientTest.cpp
|
||||
ReadBufferingStreamTest.cpp
|
||||
ReadLoggingClientTest.cpp
|
||||
ReadLoggingStreamTest.cpp
|
||||
ReadThrottlingStreamTest.cpp
|
||||
StringPrintTest.cpp
|
||||
StringStreamTest.cpp
|
||||
WaitingPrintTest.cpp
|
||||
WriteBufferingClientTest.cpp
|
||||
WriteBufferingStreamTest.cpp
|
||||
WriteLoggingClientTest.cpp
|
||||
WriteLoggingStreamTest.cpp
|
||||
WriteWaitingClientTest.cpp
|
||||
WriteWaitingStreamTest.cpp
|
||||
|
||||
doctest.h
|
||||
main.cpp
|
||||
)
|
||||
|
||||
########## AVR ##########
|
||||
|
||||
add_subdirectory(cores/avr)
|
||||
|
||||
add_executable(StreamUtilsTestAvr ${SOURCES})
|
||||
target_link_libraries(StreamUtilsTestAvr AvrCore)
|
||||
|
||||
add_test(Avr StreamUtilsTestAvr)
|
||||
|
||||
########## ESP32 ##########
|
||||
|
||||
add_subdirectory(cores/esp32)
|
||||
|
||||
add_executable(StreamUtilsTestEsp32 ${SOURCES})
|
||||
target_link_libraries(StreamUtilsTestEsp32 Esp32Core)
|
||||
|
||||
add_test(Esp32 StreamUtilsTestEsp32)
|
||||
|
||||
########## ESP8266 ##########
|
||||
|
||||
add_subdirectory(cores/esp8266)
|
||||
|
||||
add_executable(StreamUtilsTestEsp8266 ${SOURCES})
|
||||
target_link_libraries(StreamUtilsTestEsp8266 Esp8266Core)
|
||||
|
||||
add_test(Esp8266 StreamUtilsTestEsp8266)
|
||||
|
||||
########## NRF52 ##########
|
||||
|
||||
add_subdirectory(cores/nrf52)
|
||||
|
||||
add_executable(StreamUtilsTestNrf52 ${SOURCES})
|
||||
target_link_libraries(StreamUtilsTestNrf52 Nrf52Core)
|
||||
|
||||
add_test(Nrf52 StreamUtilsTestNrf52)
|
||||
|
||||
########## SAMD ##########
|
||||
|
||||
add_subdirectory(cores/samd)
|
||||
|
||||
add_executable(StreamUtilsTestSamd ${SOURCES})
|
||||
target_link_libraries(StreamUtilsTestSamd SamdCore)
|
||||
|
||||
add_test(Samd StreamUtilsTestSamd)
|
||||
|
||||
########## STM32 ##########
|
||||
|
||||
add_subdirectory(cores/stm32)
|
||||
|
||||
add_executable(StreamUtilsTestStm32 ${SOURCES})
|
||||
target_link_libraries(StreamUtilsTestStm32 Stm32Core)
|
||||
|
||||
add_test(Stm32 StreamUtilsTestStm32)
|
||||
|
||||
########## Teensy ##########
|
||||
|
||||
add_subdirectory(cores/teensy)
|
||||
|
||||
add_executable(StreamUtilsTestTeensy ${SOURCES})
|
||||
target_link_libraries(StreamUtilsTestTeensy TeensyCore)
|
||||
|
||||
add_test(Teensy StreamUtilsTestTeensy)
|
||||
57
lib/ArduinoStreamUtils/extras/test/EepromStreamTest.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "StreamUtils/Streams/EepromStream.hpp"
|
||||
|
||||
#if STREAMUTILS_ENABLE_EEPROM
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("EepromStream") {
|
||||
SUBCASE("available()") {
|
||||
EepromStream s(42, 84);
|
||||
CHECK(s.available() == 84);
|
||||
}
|
||||
|
||||
SUBCASE("write(uint8_t)") {
|
||||
EepromStream s(0, 2);
|
||||
CHECK(s.write('a') == 1);
|
||||
CHECK(s.write('b') == 1);
|
||||
CHECK(s.write('c') == 0);
|
||||
CHECK(s.write('d') == 0);
|
||||
s.flush();
|
||||
CHECK(s.readString() == "ab");
|
||||
}
|
||||
|
||||
SUBCASE("write(const uint8_t *, size_t)") {
|
||||
EepromStream s(0, 5);
|
||||
CHECK(s.write("abc", 3) == 3);
|
||||
CHECK(s.write("def", 3) == 2);
|
||||
CHECK(s.write("ghi", 3) == 0);
|
||||
s.flush();
|
||||
CHECK(s.readString() == "abcde");
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
EepromStream s(0, 2);
|
||||
s.write("ab", 2);
|
||||
CHECK(s.read() == 'a');
|
||||
CHECK(s.read() == 'b');
|
||||
CHECK(s.read() == -1);
|
||||
}
|
||||
|
||||
SUBCASE("peek()") {
|
||||
EepromStream s(0, 2);
|
||||
s.write("ab", 2);
|
||||
CHECK(s.peek() == 'a');
|
||||
CHECK(s.peek() == 'a');
|
||||
s.read();
|
||||
CHECK(s.peek() == 'b');
|
||||
s.read();
|
||||
CHECK(s.peek() == -1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
14
lib/ArduinoStreamUtils/extras/test/FailingAllocator.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h> // size_t
|
||||
|
||||
struct FailingAllocator {
|
||||
void* allocate(size_t) {
|
||||
return nullptr;
|
||||
}
|
||||
void deallocate(void*) {}
|
||||
};
|
||||
30
lib/ArduinoStreamUtils/extras/test/HammingClientTest.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "SpyingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Clients/HammingClient.hpp"
|
||||
#include "StreamUtils/Clients/MemoryClient.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("HammingClient") {
|
||||
MemoryClient upstream(64);
|
||||
|
||||
HammingClient<7, 4> client{upstream};
|
||||
|
||||
SUBCASE("read() decodes") {
|
||||
upstream.print("Tq");
|
||||
|
||||
CHECK(client.read() == 'A');
|
||||
}
|
||||
|
||||
SUBCASE("write() encodes") {
|
||||
client.write('A');
|
||||
|
||||
CHECK(upstream.readString() == "Tq");
|
||||
}
|
||||
}
|
||||
137
lib/ArduinoStreamUtils/extras/test/HammingDecodingClientTest.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "SpyingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Clients/HammingDecodingClient.hpp"
|
||||
#include "StreamUtils/Clients/MemoryClient.hpp"
|
||||
#include "StreamUtils/Clients/SpyingClient.hpp"
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("HammingDecodingClient") {
|
||||
MemoryClient upstream(64);
|
||||
StringPrint log;
|
||||
SpyingClient spy{upstream, log};
|
||||
SpyingAllocator allocator{log};
|
||||
|
||||
BasicHammingDecodingClient<7, 4, SpyingAllocator&> client{spy, allocator};
|
||||
|
||||
SUBCASE("read() with small buffer") {
|
||||
uint8_t buffer[8];
|
||||
|
||||
SUBCASE("empty input") {
|
||||
size_t result = client.read(buffer, sizeof(buffer));
|
||||
|
||||
CHECK(result == 0);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "read(16) -> 0 [timeout]");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("decodes input") {
|
||||
upstream.print("TqTb");
|
||||
|
||||
size_t result = client.read(buffer, sizeof(buffer));
|
||||
|
||||
CHECK(result == 2);
|
||||
CHECK(std::string((char*)buffer, result) == "AB");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "read(16) -> 4 [timeout]");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("includes byte loaded by peek()") {
|
||||
upstream.print("TqTb");
|
||||
client.peek();
|
||||
log.clear();
|
||||
|
||||
size_t result = client.read(buffer, sizeof(buffer));
|
||||
|
||||
CHECK(result == 2);
|
||||
CHECK(std::string((char*)buffer, result) == "AB");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "read(15) -> 3 [timeout]");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("stores dangling byte") {
|
||||
upstream.print("TqT");
|
||||
|
||||
size_t result = client.read(buffer, sizeof(buffer));
|
||||
|
||||
CHECK(result == 1);
|
||||
CHECK(std::string((char*)buffer, result) == "A");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "read(16) -> 3 [timeout]");
|
||||
#endif
|
||||
|
||||
log.clear();
|
||||
upstream.print("b");
|
||||
CHECK(client.peek() == 'B');
|
||||
CHECK(log.str() == "peek() -> 98");
|
||||
}
|
||||
|
||||
SUBCASE("clears the byte loaded by peek") {
|
||||
upstream.print("TqTb");
|
||||
client.peek();
|
||||
client.read(buffer, sizeof(buffer));
|
||||
client.peek();
|
||||
CHECK(log.str() ==
|
||||
"read() -> 84"
|
||||
"peek() -> 113"
|
||||
"read(15) -> 3 [timeout]"
|
||||
"read() -> -1");
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("read() with large buffer") {
|
||||
uint8_t buffer[32];
|
||||
|
||||
SUBCASE("empty input") {
|
||||
size_t result = client.read(buffer, sizeof(buffer));
|
||||
|
||||
CHECK(result == 0);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"allocate(64) -> ptr"
|
||||
"read(64) -> 0 [timeout]"
|
||||
"deallocate(ptr)");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("decodes input") {
|
||||
upstream.print("TqTb");
|
||||
|
||||
size_t result = client.read(buffer, sizeof(buffer));
|
||||
|
||||
CHECK(result == 2);
|
||||
CHECK(std::string((char*)buffer, result) == "AB");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"allocate(64) -> ptr"
|
||||
"read(64) -> 4 [timeout]"
|
||||
"deallocate(ptr)");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("uses input buffer if allocation fails") {
|
||||
upstream.print("TqTb");
|
||||
allocator.forceFail = true;
|
||||
|
||||
size_t result = client.read(buffer, sizeof(buffer));
|
||||
|
||||
CHECK(result == 2);
|
||||
CHECK(std::string((char*)buffer, result) == "AB");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"allocate(64) -> null"
|
||||
"read(32) -> 4 [timeout]");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
290
lib/ArduinoStreamUtils/extras/test/HammingDecodingStreamTest.cpp
Normal file
@@ -0,0 +1,290 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "SpyingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
#include "StreamUtils/Streams/HammingDecodingStream.hpp"
|
||||
#include "StreamUtils/Streams/SpyingStream.hpp"
|
||||
#include "StreamUtils/Streams/StringStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("HammingDecodingStream") {
|
||||
StringStream upstream;
|
||||
StringPrint log;
|
||||
SpyingStream spy{upstream, log};
|
||||
SpyingAllocator allocator{log};
|
||||
|
||||
BasicHammingDecodingStream<7, 4, SpyingAllocator&> stream{spy, allocator};
|
||||
|
||||
SUBCASE("available()") {
|
||||
SUBCASE("empty input") {
|
||||
CHECK(stream.available() == 0);
|
||||
CHECK(log.str() == "available() -> 0");
|
||||
}
|
||||
|
||||
SUBCASE("even number of bytes") {
|
||||
upstream.print("ABCDEFGH");
|
||||
|
||||
CHECK(stream.available() == 4);
|
||||
CHECK(log.str() == "available() -> 8");
|
||||
}
|
||||
|
||||
SUBCASE("odd number of bytes") {
|
||||
upstream.print("ABCDEFGHI");
|
||||
|
||||
CHECK(stream.available() == 4);
|
||||
CHECK(log.str() == "available() -> 9");
|
||||
}
|
||||
|
||||
SUBCASE("even number of bytes after peek") {
|
||||
upstream.print("ABCDEFGH");
|
||||
stream.peek();
|
||||
log.clear();
|
||||
CHECK(stream.available() == 4);
|
||||
CHECK(log.str() == "available() -> 7");
|
||||
}
|
||||
|
||||
SUBCASE("odd number of bytes after peek") {
|
||||
upstream.print("ABCDEFGHI");
|
||||
stream.peek();
|
||||
log.clear();
|
||||
CHECK(stream.available() == 4);
|
||||
CHECK(log.str() == "available() -> 8");
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("peek()") {
|
||||
SUBCASE("returns -1 when empty") {
|
||||
int result = stream.peek();
|
||||
|
||||
CHECK(result == -1);
|
||||
CHECK(log.str() == "read() -> -1");
|
||||
}
|
||||
|
||||
SUBCASE("returns -1 when only one byte in input") {
|
||||
upstream.print("A");
|
||||
|
||||
int result = stream.peek();
|
||||
|
||||
CHECK(result == -1);
|
||||
CHECK(log.str() ==
|
||||
"read() -> 65"
|
||||
"peek() -> -1");
|
||||
}
|
||||
|
||||
SUBCASE("returns decoded value") {
|
||||
upstream.print("Tq");
|
||||
|
||||
int result = stream.peek();
|
||||
|
||||
CHECK(result == 'A');
|
||||
CHECK(log.str() ==
|
||||
"read() -> 84"
|
||||
"peek() -> 113");
|
||||
}
|
||||
|
||||
SUBCASE("doesn't call read() the second time") {
|
||||
upstream.print("A");
|
||||
stream.peek();
|
||||
log.clear();
|
||||
|
||||
int result = stream.peek();
|
||||
|
||||
CHECK(result == -1);
|
||||
CHECK(log.str() == "peek() -> -1");
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
SUBCASE("returns -1 if empty") {
|
||||
int result = stream.read();
|
||||
|
||||
CHECK(result == -1);
|
||||
CHECK(log.str() == "read() -> -1");
|
||||
}
|
||||
|
||||
SUBCASE("returns -1 if only one byte in input") {
|
||||
upstream.print("A");
|
||||
|
||||
int result = stream.read();
|
||||
|
||||
CHECK(result == -1);
|
||||
CHECK(log.str() ==
|
||||
"read() -> 65"
|
||||
"read() -> -1");
|
||||
}
|
||||
|
||||
SUBCASE("returns decoded value if two bytes in input") {
|
||||
upstream.print("Tq");
|
||||
|
||||
int result = stream.read();
|
||||
|
||||
CHECK(result == 'A');
|
||||
CHECK(log.str() ==
|
||||
"read() -> 84"
|
||||
"read() -> 113");
|
||||
}
|
||||
|
||||
SUBCASE("reuses the byte read by peek()") {
|
||||
upstream.print("Tq");
|
||||
stream.peek();
|
||||
log.clear();
|
||||
|
||||
int result = stream.read();
|
||||
|
||||
CHECK(result == 'A');
|
||||
CHECK(log.str() == "read() -> 113");
|
||||
}
|
||||
|
||||
SUBCASE("reuses the byte read by previous call") {
|
||||
upstream.print("T");
|
||||
stream.read();
|
||||
upstream.print("q");
|
||||
log.clear();
|
||||
|
||||
int result = stream.read();
|
||||
|
||||
CHECK(result == 'A');
|
||||
CHECK(log.str() == "read() -> 113");
|
||||
}
|
||||
|
||||
SUBCASE("flushes the buffered byte") {
|
||||
upstream.print("TqTb");
|
||||
|
||||
CHECK(stream.read() == 'A');
|
||||
CHECK(stream.read() == 'B');
|
||||
|
||||
CHECK(log.str() ==
|
||||
"read() -> 84"
|
||||
"read() -> 113"
|
||||
"read() -> 84"
|
||||
"read() -> 98");
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("readBytes() with small buffer") {
|
||||
char buffer[8];
|
||||
|
||||
SUBCASE("empty input") {
|
||||
size_t result = stream.readBytes(buffer, sizeof(buffer));
|
||||
|
||||
CHECK(result == 0);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "readBytes(16) -> 0 [timeout]");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("decodes input") {
|
||||
upstream.print("TqTb");
|
||||
|
||||
size_t result = stream.readBytes(buffer, sizeof(buffer));
|
||||
|
||||
CHECK(result == 2);
|
||||
CHECK(std::string(buffer, result) == "AB");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "readBytes(16) -> 4 [timeout]");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("includes byte loaded by peek()") {
|
||||
upstream.print("TqTb");
|
||||
stream.peek();
|
||||
log.clear();
|
||||
|
||||
size_t result = stream.readBytes(buffer, sizeof(buffer));
|
||||
|
||||
CHECK(result == 2);
|
||||
CHECK(std::string(buffer, result) == "AB");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "readBytes(15) -> 3 [timeout]");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("stores dangling byte") {
|
||||
upstream.print("TqT");
|
||||
|
||||
size_t result = stream.readBytes(buffer, sizeof(buffer));
|
||||
|
||||
CHECK(result == 1);
|
||||
CHECK(std::string(buffer, result) == "A");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "readBytes(16) -> 3 [timeout]");
|
||||
#endif
|
||||
|
||||
log.clear();
|
||||
upstream.print("b");
|
||||
CHECK(stream.peek() == 'B');
|
||||
CHECK(log.str() == "peek() -> 98");
|
||||
}
|
||||
|
||||
SUBCASE("clears the byte loaded by peek") {
|
||||
upstream.print("TqTb");
|
||||
stream.peek();
|
||||
stream.readBytes(buffer, sizeof(buffer));
|
||||
CHECK(stream.peek() == -1);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"read() -> 84"
|
||||
"peek() -> 113"
|
||||
"readBytes(15) -> 3 [timeout]"
|
||||
"read() -> -1");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("readBytes() with large buffer") {
|
||||
char buffer[32];
|
||||
|
||||
SUBCASE("empty input") {
|
||||
size_t result = stream.readBytes(buffer, sizeof(buffer));
|
||||
|
||||
CHECK(result == 0);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"allocate(64) -> ptr"
|
||||
"readBytes(64) -> 0 [timeout]"
|
||||
"deallocate(ptr)");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("decodes input") {
|
||||
upstream.print("TqTb");
|
||||
|
||||
size_t result = stream.readBytes(buffer, sizeof(buffer));
|
||||
|
||||
CHECK(result == 2);
|
||||
CHECK(std::string(buffer, result) == "AB");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"allocate(64) -> ptr"
|
||||
"readBytes(64) -> 4 [timeout]"
|
||||
"deallocate(ptr)");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("uses input buffer if allocation fails") {
|
||||
upstream.print("TqTb");
|
||||
allocator.forceFail = true;
|
||||
|
||||
size_t result = stream.readBytes(buffer, sizeof(buffer));
|
||||
|
||||
CHECK(result == 2);
|
||||
CHECK(std::string(buffer, result) == "AB");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"allocate(64) -> null"
|
||||
"readBytes(32) -> 4 [timeout]");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("flush()") {
|
||||
stream.flush();
|
||||
CHECK(log.str() == "flush()");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "SpyingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Clients/HammingEncodingClient.hpp"
|
||||
#include "StreamUtils/Clients/MemoryClient.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("HammingEncodingClient") {
|
||||
MemoryClient upstream(64);
|
||||
|
||||
HammingEncodingClient<7, 4> client{upstream};
|
||||
|
||||
SUBCASE("read() forwards upstream data") {
|
||||
upstream.print("A");
|
||||
|
||||
CHECK(client.read() == 'A');
|
||||
}
|
||||
|
||||
SUBCASE("write() encodes") {
|
||||
client.write('A');
|
||||
|
||||
CHECK(upstream.readString() == "Tq");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "SpyingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Streams/HammingEncodingStream.hpp"
|
||||
#include "StreamUtils/Streams/MemoryStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("HammingEncodingStream") {
|
||||
MemoryStream upstream(64);
|
||||
|
||||
HammingEncodingStream<7, 4> stream{upstream};
|
||||
|
||||
SUBCASE("read() forwards upstream data") {
|
||||
upstream.print("A");
|
||||
|
||||
CHECK(stream.read() == 'A');
|
||||
}
|
||||
|
||||
SUBCASE("write() encodes") {
|
||||
stream.write('A');
|
||||
|
||||
CHECK(upstream.readString() == "Tq");
|
||||
}
|
||||
}
|
||||
202
lib/ArduinoStreamUtils/extras/test/HammingPrintTest.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "SpyingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Prints/HammingPrint.hpp"
|
||||
#include "StreamUtils/Prints/SpyingPrint.hpp"
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
#include "StreamUtils/Streams/MemoryStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("HammingPrint") {
|
||||
MemoryStream upstream(4);
|
||||
|
||||
StringPrint log;
|
||||
SpyingPrint spy{upstream, log};
|
||||
SpyingAllocator allocator{log};
|
||||
|
||||
BasicHammingPrint<7, 4, SpyingAllocator&> print{spy, allocator};
|
||||
|
||||
SUBCASE("write(char*, size_t)") {
|
||||
SUBCASE("stops if even byte fails") {
|
||||
CHECK(print.print("ABA") == 2);
|
||||
print.write('A'); // try to flush remainder
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('TqTbTq', 6) -> 4"
|
||||
"write('T') -> 0" // no remainder
|
||||
);
|
||||
}
|
||||
|
||||
SUBCASE("saves remainder if odd byte fails") {
|
||||
upstream.print("?");
|
||||
|
||||
CHECK(print.print("ABA") == 2);
|
||||
print.write('A'); // try to flush remainder
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('TqTbTq', 6) -> 3"
|
||||
"write('b') -> 0" // remainder!!
|
||||
);
|
||||
}
|
||||
|
||||
SUBCASE("writes remainder first") {
|
||||
upstream.print("???");
|
||||
print.write('A'); // add remainder
|
||||
log.clear();
|
||||
upstream.readString();
|
||||
|
||||
CHECK(print.print("ABA") == 2);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('q') -> 1"
|
||||
"write('TqTbTq', 6) -> 3");
|
||||
}
|
||||
|
||||
SUBCASE("stops if remainder fails") {
|
||||
upstream.print("???");
|
||||
print.write('A'); // add remainder
|
||||
log.clear();
|
||||
|
||||
CHECK(print.print("ABA") == 0);
|
||||
|
||||
CHECK(log.str() == "write('q') -> 0");
|
||||
}
|
||||
|
||||
SUBCASE("allocates in stack when buffer is small") {
|
||||
print.write("ABABABABABABABAB", 16);
|
||||
|
||||
CHECK(log.str() == "write('TqTbTqTbTqTbTqTbTqTbTqTbTqTbTqTb', 32) -> 4");
|
||||
}
|
||||
|
||||
SUBCASE("allocates in heap when buffer is large") {
|
||||
print.write("ABABABABABABABABA", 17);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"allocate(34) -> ptr"
|
||||
"write('TqTbTqTbTqTbTqTbTqTbTqTbTqTbTqTbTq', 34) -> 4"
|
||||
"deallocate(ptr)");
|
||||
}
|
||||
|
||||
SUBCASE("falls back to stack if heap fails") {
|
||||
allocator.forceFail = true;
|
||||
print.write("ABABABABABABABABA", 17);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"allocate(34) -> null"
|
||||
"write('TqTbTqTbTqTbTqTbTqTbTqTbTqTbTqTb', 32) -> 4");
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("write(char)") {
|
||||
SUBCASE("writes both bytes") {
|
||||
CHECK(print.write('A') == 1);
|
||||
|
||||
CHECK(upstream.readString() == "Tq");
|
||||
CHECK(log.str() ==
|
||||
"write('T') -> 1"
|
||||
"write('q') -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("stops if first by fails") {
|
||||
upstream.print("????");
|
||||
|
||||
CHECK(print.write('A') == 0);
|
||||
print.write('A'); // try to flush remainder
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('T') -> 0"
|
||||
"write('T') -> 0" // no remainder
|
||||
);
|
||||
}
|
||||
|
||||
SUBCASE("saves remainder if second by fails") {
|
||||
upstream.print("???");
|
||||
|
||||
CHECK(print.write('A') == 1);
|
||||
print.write('A'); // try to flush remainder
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('T') -> 1"
|
||||
"write('q') -> 0"
|
||||
"write('q') -> 0" // remainder!!
|
||||
);
|
||||
}
|
||||
|
||||
SUBCASE("writes remainder first") {
|
||||
upstream.print("???");
|
||||
print.write('A'); // add remainder
|
||||
log.clear();
|
||||
upstream.readString();
|
||||
|
||||
CHECK(print.write('A') == 1);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('q') -> 1"
|
||||
"write('T') -> 1"
|
||||
"write('q') -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("stops if remainder fails") {
|
||||
upstream.print("???");
|
||||
print.write('A'); // add remainder
|
||||
log.clear();
|
||||
|
||||
CHECK(print.write('A') == 0);
|
||||
print.write('A'); // try to flush remainder
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('q') -> 0"
|
||||
"write('q') -> 0" // remainder!!
|
||||
);
|
||||
}
|
||||
|
||||
SUBCASE("resets remainder") {
|
||||
upstream.print("???");
|
||||
print.write('A'); // add remainder
|
||||
log.clear();
|
||||
upstream.read();
|
||||
|
||||
CHECK(print.write('A') == 0);
|
||||
print.write('A'); // try to flush remainder
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('q') -> 1"
|
||||
"write('T') -> 0"
|
||||
"write('T') -> 0" // no remainder
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#if STREAMUTILS_PRINT_FLUSH_EXISTS
|
||||
SUBCASE("flush() writes remainder") {
|
||||
upstream.print("???");
|
||||
print.write('A'); // add remainder
|
||||
log.clear();
|
||||
upstream.read();
|
||||
|
||||
print.flush();
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('q') -> 1"
|
||||
"flush()" // no remainder
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
SUBCASE("destructor flushes remainder") {
|
||||
{
|
||||
BasicHammingPrint<7, 4, SpyingAllocator&> print{spy, allocator};
|
||||
upstream.print("???");
|
||||
print.write('A'); // add remainder
|
||||
log.clear();
|
||||
}
|
||||
|
||||
CHECK(log.str() == "write('q') -> 0");
|
||||
}
|
||||
}
|
||||
30
lib/ArduinoStreamUtils/extras/test/HammingStreamTest.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "SpyingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Streams/HammingStream.hpp"
|
||||
#include "StreamUtils/Streams/MemoryStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("HammingStream") {
|
||||
MemoryStream upstream(64);
|
||||
|
||||
HammingStream<7, 4> stream{upstream};
|
||||
|
||||
SUBCASE("read() decodes") {
|
||||
upstream.print("Tq");
|
||||
|
||||
CHECK(stream.read() == 'A');
|
||||
}
|
||||
|
||||
SUBCASE("write() encodes") {
|
||||
stream.write('A');
|
||||
|
||||
CHECK(upstream.readString() == "Tq");
|
||||
}
|
||||
}
|
||||
138
lib/ArduinoStreamUtils/extras/test/LoggingClientTest.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "StreamUtils/Clients/LoggingClient.hpp"
|
||||
#include "StreamUtils/Clients/MemoryClient.hpp"
|
||||
#include "StreamUtils/Clients/SpyingClient.hpp"
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("LoggingClient") {
|
||||
MemoryClient target(4);
|
||||
|
||||
StringPrint log;
|
||||
SpyingClient spy{target, log};
|
||||
|
||||
StringPrint output;
|
||||
LoggingClient loggingClient{spy, output};
|
||||
|
||||
SUBCASE("available()") {
|
||||
target.print("ABC");
|
||||
|
||||
size_t n = loggingClient.available();
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "available() -> 3");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("connect(IPAddress)") {
|
||||
int n = loggingClient.connect(IPAddress("1.2.3.4"), 80);
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("connect(const char*)") {
|
||||
int n = loggingClient.connect("1.2.3.4", 80);
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("connected()") {
|
||||
uint8_t n = loggingClient.connected();
|
||||
|
||||
CHECK(n == false);
|
||||
CHECK(log.str() == "connected() -> 0");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("stop()") {
|
||||
loggingClient.stop();
|
||||
|
||||
CHECK(log.str() == "stop()");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("operator bool()") {
|
||||
bool n = loggingClient.operator bool();
|
||||
|
||||
CHECK(n == true);
|
||||
CHECK(log.str() == "operator bool() -> true");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("peek()") {
|
||||
target.print("ABC");
|
||||
|
||||
int n = loggingClient.peek();
|
||||
|
||||
CHECK(n == 'A');
|
||||
CHECK(log.str() == "peek() -> 65");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
target.print("ABC");
|
||||
|
||||
int n = loggingClient.read();
|
||||
|
||||
CHECK(n == 'A');
|
||||
CHECK(log.str() == "read() -> 65");
|
||||
CHECK(output.str() == "A");
|
||||
}
|
||||
|
||||
SUBCASE("read(uint8_t*,size_t)") {
|
||||
target.print("ABC");
|
||||
|
||||
uint8_t s[4] = {0};
|
||||
size_t n = loggingClient.read(s, 4);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "read(4) -> 3 [timeout]");
|
||||
CHECK(output.str() == "ABC");
|
||||
}
|
||||
|
||||
SUBCASE("readBytes()") {
|
||||
target.print("ABC");
|
||||
|
||||
char s[4] = {0};
|
||||
size_t n = loggingClient.readBytes(s, 4);
|
||||
|
||||
CHECK(n == 3);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "readBytes(4) -> 3 [timeout]");
|
||||
#endif
|
||||
CHECK(output.str() == "ABC");
|
||||
}
|
||||
|
||||
SUBCASE("write(char)") {
|
||||
int n = loggingClient.write('A');
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "write('A') -> 1");
|
||||
CHECK(output.str() == "A");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,size_t)") {
|
||||
int n = loggingClient.write("ABCDEF", 6);
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(log.str() == "write('ABCDEF', 6) -> 4");
|
||||
CHECK(output.str() == "ABCD");
|
||||
}
|
||||
|
||||
SUBCASE("flush()") {
|
||||
loggingClient.flush();
|
||||
|
||||
CHECK(output.str() == "");
|
||||
CHECK(log.str() == "flush()");
|
||||
}
|
||||
}
|
||||
41
lib/ArduinoStreamUtils/extras/test/LoggingPrintTest.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "StreamUtils/Prints/LoggingPrint.hpp"
|
||||
#include "StreamUtils/Streams/MemoryStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("LoggingPrint") {
|
||||
MemoryStream primary(4);
|
||||
MemoryStream secondary(64);
|
||||
LoggingPrint loggingPrint{primary, secondary};
|
||||
|
||||
SUBCASE("write(char)") {
|
||||
int n = loggingPrint.write('A');
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(primary.readString() == "A");
|
||||
CHECK(secondary.readString() == "A");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,size_t)") {
|
||||
int n = loggingPrint.write("ABCDEF", 6);
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(primary.readString() == "ABCD");
|
||||
CHECK(secondary.readString() == "ABCD");
|
||||
}
|
||||
|
||||
#if STREAMUTILS_PRINT_FLUSH_EXISTS
|
||||
SUBCASE("flush()") {
|
||||
loggingPrint.write("AB", 2);
|
||||
REQUIRE(primary.available() == 2);
|
||||
loggingPrint.flush();
|
||||
REQUIRE(primary.available() == 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
93
lib/ArduinoStreamUtils/extras/test/LoggingStreamTest.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
#include "StreamUtils/Streams/LoggingStream.hpp"
|
||||
#include "StreamUtils/Streams/MemoryStream.hpp"
|
||||
#include "StreamUtils/Streams/SpyingStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("LoggingStream") {
|
||||
MemoryStream upstream{4};
|
||||
StringPrint output;
|
||||
|
||||
StringPrint log;
|
||||
SpyingStream upstreamSpy{upstream, log};
|
||||
|
||||
LoggingStream loggingStream{upstreamSpy, output};
|
||||
|
||||
// upstream -> upstreamSpy -> loggingStream -> output
|
||||
// |
|
||||
// v
|
||||
// log
|
||||
|
||||
SUBCASE("available()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
size_t n = loggingStream.available();
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "available() -> 3");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("peek()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
int n = loggingStream.peek();
|
||||
|
||||
CHECK(n == 'A');
|
||||
CHECK(log.str() == "peek() -> 65");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
int n = loggingStream.read();
|
||||
|
||||
CHECK(n == 'A');
|
||||
CHECK(log.str() == "read() -> 65");
|
||||
CHECK(output.str() == "A");
|
||||
}
|
||||
|
||||
SUBCASE("readBytes()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
char s[4] = {0};
|
||||
size_t n = loggingStream.readBytes(s, 4);
|
||||
|
||||
CHECK(n == 3);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "readBytes(4) -> 3 [timeout]");
|
||||
#endif
|
||||
CHECK(output.str() == "ABC");
|
||||
}
|
||||
|
||||
SUBCASE("write(char)") {
|
||||
int n = loggingStream.write('A');
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "write('A') -> 1");
|
||||
CHECK(output.str() == "A");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,size_t)") {
|
||||
int n = loggingStream.write("ABCDEF", 6);
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(log.str() == "write('ABCDEF', 6) -> 4");
|
||||
CHECK(output.str() == "ABCD");
|
||||
}
|
||||
|
||||
SUBCASE("flush()") {
|
||||
loggingStream.flush();
|
||||
|
||||
CHECK(log.str() == "flush()");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
}
|
||||
116
lib/ArduinoStreamUtils/extras/test/MemoryStreamTest.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "StreamUtils/Streams/MemoryStream.hpp"
|
||||
#include "StreamUtils/Streams/SpyingStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("MemoryStream") {
|
||||
MemoryStream stream(4);
|
||||
|
||||
WHEN("stream is empty") {
|
||||
THEN("available() return 0") {
|
||||
CHECK(stream.available() == 0);
|
||||
}
|
||||
|
||||
THEN("write(uint8) returns 1") {
|
||||
CHECK(stream.write('A') == 1);
|
||||
}
|
||||
|
||||
THEN("write(\"ABCD\",4) returns 4") {
|
||||
CHECK(stream.write("ABCD", 4) == 4);
|
||||
}
|
||||
|
||||
THEN("write(uint8*,8) returns 4") {
|
||||
CHECK(stream.write("ABCDEFGH", 8) == 4);
|
||||
}
|
||||
|
||||
THEN("read() return -1") {
|
||||
CHECK(stream.read() == -1);
|
||||
}
|
||||
|
||||
THEN("peek() return -1") {
|
||||
CHECK(stream.peek() == -1);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("stream is full") {
|
||||
stream.print("ABCD");
|
||||
|
||||
THEN("available() return 4") {
|
||||
CHECK(stream.available() == 4);
|
||||
}
|
||||
|
||||
THEN("write(uint8) returns 0") {
|
||||
CHECK(stream.write('A') == 0);
|
||||
}
|
||||
|
||||
THEN("write(\"ABCD\",4) returns 0") {
|
||||
CHECK(stream.write("ABCD", 4) == 0);
|
||||
}
|
||||
|
||||
THEN("read() returns the next value") {
|
||||
CHECK(stream.read() == 'A');
|
||||
CHECK(stream.read() == 'B');
|
||||
}
|
||||
|
||||
THEN("read(uint8_t*,size_t) extracts the next bytes") {
|
||||
char data[5] = {0};
|
||||
CHECK(stream.readBytes(data, 4) == 4);
|
||||
CHECK(data == std::string("ABCD"));
|
||||
}
|
||||
|
||||
THEN("peek() returns the first value") {
|
||||
CHECK(stream.peek() == 'A');
|
||||
CHECK(stream.peek() == 'A');
|
||||
}
|
||||
|
||||
SUBCASE("read() makes room for one byte") {
|
||||
stream.read(); // make room
|
||||
REQUIRE(stream.available() == 3);
|
||||
|
||||
stream.write('E'); // write at the beginning
|
||||
REQUIRE(stream.available() == 4);
|
||||
|
||||
char data[5] = {0};
|
||||
stream.readBytes(data, 4);
|
||||
CHECK(data == std::string("BCDE"));
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("lower half is filled") {
|
||||
stream.print("AB");
|
||||
|
||||
THEN("available() return 2") {
|
||||
CHECK(stream.available() == 2);
|
||||
}
|
||||
|
||||
THEN("write(uint8) returns 1") {
|
||||
CHECK(stream.write('C') == 1);
|
||||
}
|
||||
|
||||
THEN("write(\"ABCD\",4) returns 2") {
|
||||
CHECK(stream.write("ABCD", 4) == 2);
|
||||
}
|
||||
|
||||
THEN("read() returns the next value") {
|
||||
CHECK(stream.read() == 'A');
|
||||
CHECK(stream.read() == 'B');
|
||||
}
|
||||
|
||||
THEN("read(uint8_t*,size_t) extracts the next bytes") {
|
||||
char data[5] = {0};
|
||||
CHECK(stream.readBytes(data, 4) == 2);
|
||||
CHECK(data == std::string("AB"));
|
||||
}
|
||||
|
||||
THEN("peek() returns the first value") {
|
||||
CHECK(stream.peek() == 'A');
|
||||
CHECK(stream.peek() == 'A');
|
||||
}
|
||||
}
|
||||
}
|
||||
337
lib/ArduinoStreamUtils/extras/test/ReadBufferingClientTest.cpp
Normal file
@@ -0,0 +1,337 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "FailingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Clients/MemoryClient.hpp"
|
||||
#include "StreamUtils/Clients/ReadBufferingClient.hpp"
|
||||
#include "StreamUtils/Clients/SpyingClient.hpp"
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("ReadBufferingClient") {
|
||||
MemoryClient target(64);
|
||||
StringPrint log;
|
||||
SpyingClient spy{target, log};
|
||||
|
||||
SUBCASE("capacity = 4") {
|
||||
ReadBufferingClient bufferedClient{spy, 4};
|
||||
Client& client = bufferedClient;
|
||||
|
||||
SUBCASE("available()") {
|
||||
target.print("ABCDEFGH");
|
||||
|
||||
SUBCASE("empty input") {
|
||||
target.flush();
|
||||
CHECK(client.available() == 0);
|
||||
CHECK(log.str() == "available() -> 0");
|
||||
}
|
||||
|
||||
SUBCASE("read empty input") {
|
||||
target.flush();
|
||||
|
||||
client.read();
|
||||
|
||||
CHECK(client.available() == 0);
|
||||
CHECK(log.str() ==
|
||||
"available() -> 0"
|
||||
"read() -> -1"
|
||||
"available() -> 0");
|
||||
}
|
||||
|
||||
SUBCASE("same a target") {
|
||||
CHECK(client.available() == 8);
|
||||
CHECK(log.str() == "available() -> 8");
|
||||
}
|
||||
|
||||
SUBCASE("target + in buffer") {
|
||||
client.read();
|
||||
|
||||
CHECK(client.available() == 7);
|
||||
CHECK(log.str() ==
|
||||
"available() -> 8"
|
||||
"read(4) -> 4"
|
||||
"available() -> 4");
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("peek()") {
|
||||
SUBCASE("returns -1 when empty") {
|
||||
target.flush();
|
||||
|
||||
int result = client.peek();
|
||||
|
||||
CHECK(result == -1);
|
||||
CHECK(log.str() == "peek() -> -1");
|
||||
}
|
||||
|
||||
SUBCASE("doesn't call readBytes() when buffer is empty") {
|
||||
target.print("A");
|
||||
|
||||
int result = client.peek();
|
||||
|
||||
CHECK(result == 'A');
|
||||
CHECK(log.str() == "peek() -> 65");
|
||||
}
|
||||
|
||||
SUBCASE("doesn't call peek() when buffer is full") {
|
||||
target.print("AB");
|
||||
|
||||
client.read();
|
||||
int result = client.peek();
|
||||
|
||||
CHECK(result == 'B');
|
||||
CHECK(log.str() ==
|
||||
"available() -> 2"
|
||||
"read(2) -> 2");
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
SUBCASE("reads 4 bytes at a time") {
|
||||
target.print("ABCDEFG");
|
||||
std::string result;
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
result += (char)client.read();
|
||||
}
|
||||
|
||||
CHECK(result == "ABCDEFG");
|
||||
CHECK(log.str() ==
|
||||
"available() -> 7"
|
||||
"read(4) -> 4"
|
||||
"available() -> 3"
|
||||
"read(3) -> 3");
|
||||
}
|
||||
|
||||
SUBCASE("returns -1 when empty") {
|
||||
target.flush();
|
||||
|
||||
int result = client.read();
|
||||
|
||||
CHECK(result == -1);
|
||||
CHECK(log.str() ==
|
||||
"available() -> 0"
|
||||
"read() -> -1");
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
SUBCASE("empty input") {
|
||||
target.flush();
|
||||
|
||||
char c;
|
||||
size_t result = client.readBytes(&c, 1);
|
||||
|
||||
CHECK(result == 0);
|
||||
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 0"
|
||||
"readBytes(1) -> 0 [timeout]");
|
||||
#else
|
||||
CHECK(log.str() ==
|
||||
"available() -> 0"
|
||||
"read() -> -1"); // [timeout] from timedRead()
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("reads 4 bytes when requested one") {
|
||||
target.print("ABCDEFG");
|
||||
|
||||
char c;
|
||||
size_t result = client.readBytes(&c, 1);
|
||||
|
||||
CHECK(c == 'A');
|
||||
CHECK(result == 1);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 7"
|
||||
"readBytes(4) -> 4");
|
||||
#else
|
||||
CHECK(log.str() ==
|
||||
"available() -> 7"
|
||||
"read(4) -> 4");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("copy one byte from buffer") {
|
||||
target.print("ABCDEFGH");
|
||||
client.read(); // load buffer
|
||||
|
||||
char c;
|
||||
size_t result = client.readBytes(&c, 1);
|
||||
|
||||
CHECK(c == 'B');
|
||||
CHECK(result == 1);
|
||||
CHECK(log.str() ==
|
||||
"available() -> 8"
|
||||
"read(4) -> 4");
|
||||
}
|
||||
|
||||
SUBCASE("copy content from buffer then bypass buffer") {
|
||||
target.print("ABCDEFGH");
|
||||
client.read(); // load buffer
|
||||
|
||||
char c[8] = {0};
|
||||
size_t result = client.readBytes(c, 7);
|
||||
|
||||
CHECK(c == std::string("BCDEFGH"));
|
||||
CHECK(result == 7);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 8"
|
||||
"read(4) -> 4"
|
||||
"available() -> 4"
|
||||
"readBytes(4) -> 4");
|
||||
#else
|
||||
CHECK(log.str() ==
|
||||
"available() -> 8"
|
||||
"read(4) -> 4"
|
||||
"available() -> 4"
|
||||
"read(4) -> 4");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("copy content from buffer twice") {
|
||||
target.print("ABCDEFGH");
|
||||
client.read(); // load buffer
|
||||
|
||||
char c[8] = {0};
|
||||
size_t result = client.readBytes(c, 4);
|
||||
|
||||
CHECK(c == std::string("BCDE"));
|
||||
CHECK(result == 4);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 8"
|
||||
"read(4) -> 4"
|
||||
"available() -> 4"
|
||||
"readBytes(4) -> 4");
|
||||
#else
|
||||
CHECK(log.str() ==
|
||||
"available() -> 8"
|
||||
"read(4) -> 4"
|
||||
"available() -> 4"
|
||||
"read(4) -> 4");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("read past the end") {
|
||||
target.print("A");
|
||||
|
||||
char c;
|
||||
client.readBytes(&c, 1);
|
||||
size_t result = client.readBytes(&c, 1);
|
||||
|
||||
CHECK(result == 0);
|
||||
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 1"
|
||||
"readBytes(1) -> 1"
|
||||
"available() -> 0"
|
||||
"readBytes(1) -> 0 [timeout]");
|
||||
#else
|
||||
CHECK(log.str() ==
|
||||
"available() -> 1"
|
||||
"read() -> 65"
|
||||
"available() -> 0"
|
||||
"read() -> -1"); // [timeout] from timedRead()
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("flush()") {
|
||||
client.flush();
|
||||
CHECK(log.str() == "flush()");
|
||||
}
|
||||
|
||||
SUBCASE("copy constructor") {
|
||||
target.print("ABCDEFGH");
|
||||
bufferedClient.read();
|
||||
|
||||
auto dup = bufferedClient;
|
||||
|
||||
int result = dup.read();
|
||||
|
||||
CHECK(result == 'B');
|
||||
CHECK(log.str() ==
|
||||
"available() -> 8"
|
||||
"read(4) -> 4");
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("No memory") {
|
||||
BasicReadBufferingClient<FailingAllocator> client(spy, 4);
|
||||
|
||||
SUBCASE("available()") {
|
||||
target.print("ABC");
|
||||
|
||||
CHECK(client.available() == 3);
|
||||
}
|
||||
|
||||
// SUBCASE("capacity()") {
|
||||
// CHECK(client.capacity() == 0);
|
||||
// }
|
||||
|
||||
SUBCASE("peek()") {
|
||||
target.print("ABC");
|
||||
|
||||
int c = client.peek();
|
||||
|
||||
CHECK(c == 'A');
|
||||
CHECK(log.str() == "peek() -> 65");
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
target.print("ABC");
|
||||
|
||||
int c = client.read();
|
||||
|
||||
CHECK(c == 'A');
|
||||
CHECK(log.str() == "read() -> 65");
|
||||
}
|
||||
|
||||
SUBCASE("readBytes()") {
|
||||
target.print("ABC");
|
||||
|
||||
char s[4] = {0};
|
||||
int n = client.readBytes(s, 3);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(s == std::string("ABC"));
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "readBytes(3) -> 3");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("Real example") {
|
||||
ReadBufferingClient bufferedClient{spy, 64};
|
||||
Client& client = bufferedClient;
|
||||
|
||||
target.print("{\"helloWorld\":\"Hello World\"}");
|
||||
|
||||
char c[] = "ABCDEFGH";
|
||||
CHECK(client.readBytes(&c[0], 1) == 1);
|
||||
CHECK(client.readBytes(&c[1], 1) == 1);
|
||||
CHECK(client.readBytes(&c[2], 1) == 1);
|
||||
CHECK(client.readBytes(&c[3], 1) == 1);
|
||||
|
||||
CHECK(c == std::string("{\"heEFGH"));
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 28"
|
||||
"readBytes(28) -> 28");
|
||||
#else
|
||||
CHECK(log.str() ==
|
||||
"available() -> 28"
|
||||
"read(28) -> 28");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
318
lib/ArduinoStreamUtils/extras/test/ReadBufferingStreamTest.cpp
Normal file
@@ -0,0 +1,318 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "FailingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
#include "StreamUtils/Streams/ReadBufferingStream.hpp"
|
||||
#include "StreamUtils/Streams/SpyingStream.hpp"
|
||||
#include "StreamUtils/Streams/StringStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("ReadBufferingStream") {
|
||||
StringStream upstream;
|
||||
StringPrint log;
|
||||
SpyingStream spy{upstream, log};
|
||||
|
||||
SUBCASE("capacity = 4") {
|
||||
ReadBufferingStream bufferedStream{spy, 4};
|
||||
Stream& stream = bufferedStream;
|
||||
|
||||
SUBCASE("available()") {
|
||||
SUBCASE("empty input") {
|
||||
CHECK(stream.available() == 0);
|
||||
CHECK(log.str() == "available() -> 0");
|
||||
}
|
||||
|
||||
SUBCASE("read empty input") {
|
||||
int n = stream.read();
|
||||
|
||||
CHECK(n == -1);
|
||||
CHECK(stream.available() == 0);
|
||||
CHECK(log.str() ==
|
||||
"available() -> 0"
|
||||
"read() -> -1"
|
||||
"available() -> 0");
|
||||
}
|
||||
|
||||
SUBCASE("same a upstream") {
|
||||
upstream.print("ABCDEFGH");
|
||||
|
||||
CHECK(stream.available() == 8);
|
||||
CHECK(log.str() == "available() -> 8");
|
||||
}
|
||||
|
||||
SUBCASE("upstream + in buffer") {
|
||||
upstream.print("ABCDEFGH");
|
||||
|
||||
int n = stream.read();
|
||||
|
||||
CHECK(n == 'A');
|
||||
CHECK(stream.available() == 7);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 8"
|
||||
"readBytes(4) -> 4"
|
||||
"available() -> 4");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("peek()") {
|
||||
SUBCASE("returns -1 when empty") {
|
||||
upstream.flush();
|
||||
|
||||
int result = stream.peek();
|
||||
|
||||
CHECK(result == -1);
|
||||
CHECK(log.str() == "peek() -> -1");
|
||||
}
|
||||
|
||||
SUBCASE("doesn't call readBytes() when buffer is empty") {
|
||||
upstream.print("A");
|
||||
|
||||
int result = stream.peek();
|
||||
|
||||
CHECK(result == 'A');
|
||||
CHECK(log.str() == "peek() -> 65");
|
||||
}
|
||||
|
||||
SUBCASE("doesn't call peek() when buffer is full") {
|
||||
upstream.print("AB");
|
||||
|
||||
stream.read();
|
||||
int result = stream.peek();
|
||||
|
||||
CHECK(result == 'B');
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 2"
|
||||
"readBytes(2) -> 2");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
SUBCASE("reads 4 bytes at a time") {
|
||||
upstream.print("ABCDEFG");
|
||||
std::string result;
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
result += (char)stream.read();
|
||||
}
|
||||
|
||||
CHECK(result == "ABCDEFG");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 7"
|
||||
"readBytes(4) -> 4"
|
||||
"available() -> 3"
|
||||
"readBytes(3) -> 3");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("returns -1 when empty") {
|
||||
upstream.flush();
|
||||
|
||||
int result = stream.read();
|
||||
|
||||
CHECK(result == -1);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 0"
|
||||
"read() -> -1");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("readBytes()") {
|
||||
SUBCASE("empty input") {
|
||||
upstream.flush();
|
||||
|
||||
char c;
|
||||
size_t result = stream.readBytes(&c, 1);
|
||||
|
||||
CHECK(result == 0);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 0"
|
||||
"readBytes(1) -> 0 [timeout]");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("reads 4 bytes when requested one") {
|
||||
upstream.print("ABCDEFG");
|
||||
|
||||
char c;
|
||||
size_t result = stream.readBytes(&c, 1);
|
||||
|
||||
CHECK(c == 'A');
|
||||
CHECK(result == 1);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 7"
|
||||
"readBytes(4) -> 4");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("copy one byte from buffer") {
|
||||
upstream.print("ABCDEFGH");
|
||||
stream.read(); // load buffer
|
||||
|
||||
char c;
|
||||
size_t result = stream.readBytes(&c, 1);
|
||||
|
||||
CHECK(c == 'B');
|
||||
CHECK(result == 1);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 8"
|
||||
"readBytes(4) -> 4");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("copy content from buffer then bypass buffer") {
|
||||
upstream.print("ABCDEFGH");
|
||||
stream.read(); // load buffer
|
||||
|
||||
char c[8] = {0};
|
||||
size_t result = stream.readBytes(c, 7);
|
||||
|
||||
CHECK(c == std::string("BCDEFGH"));
|
||||
CHECK(result == 7);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 8"
|
||||
"readBytes(4) -> 4"
|
||||
"available() -> 4"
|
||||
"readBytes(4) -> 4");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("copy content from buffer twice") {
|
||||
upstream.print("ABCDEFGH");
|
||||
stream.read(); // load buffer
|
||||
|
||||
char c[8] = {0};
|
||||
size_t result = stream.readBytes(c, 4);
|
||||
|
||||
CHECK(c == std::string("BCDE"));
|
||||
CHECK(result == 4);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 8"
|
||||
"readBytes(4) -> 4"
|
||||
"available() -> 4"
|
||||
"readBytes(4) -> 4");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("read past the end") {
|
||||
upstream.print("A");
|
||||
|
||||
char c;
|
||||
stream.readBytes(&c, 1);
|
||||
size_t result = stream.readBytes(&c, 1);
|
||||
|
||||
CHECK(result == 0);
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 1"
|
||||
"readBytes(1) -> 1"
|
||||
"available() -> 0"
|
||||
"readBytes(1) -> 0 [timeout]");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("flush()") {
|
||||
stream.flush();
|
||||
CHECK(log.str() == "flush()");
|
||||
}
|
||||
|
||||
SUBCASE("copy constructor") {
|
||||
upstream.print("ABCDEFGH");
|
||||
bufferedStream.read();
|
||||
|
||||
auto dup = bufferedStream;
|
||||
|
||||
int result = dup.read();
|
||||
|
||||
CHECK(result == 'B');
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 8"
|
||||
"readBytes(4) -> 4");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("No memory") {
|
||||
BasicReadBufferingStream<FailingAllocator> stream(spy, 4);
|
||||
|
||||
SUBCASE("available()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
CHECK(stream.available() == 3);
|
||||
}
|
||||
|
||||
// SUBCASE("capacity()") {
|
||||
// CHECK(stream.capacity() == 0);
|
||||
// }
|
||||
|
||||
SUBCASE("peek()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
int c = stream.peek();
|
||||
|
||||
CHECK(c == 'A');
|
||||
CHECK(log.str() == "peek() -> 65");
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
int c = stream.read();
|
||||
|
||||
CHECK(c == 'A');
|
||||
CHECK(log.str() == "read() -> 65");
|
||||
}
|
||||
|
||||
SUBCASE("readBytes()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
char s[4] = {0};
|
||||
int n = stream.readBytes(s, 3);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(s == std::string("ABC"));
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "readBytes(3) -> 3");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("Real example") {
|
||||
ReadBufferingStream bufferedStream{spy, 64};
|
||||
Stream& stream = bufferedStream;
|
||||
|
||||
upstream.print("{\"helloWorld\":\"Hello World\"}");
|
||||
|
||||
char c[] = "ABCDEFGH";
|
||||
CHECK(stream.readBytes(&c[0], 1) == 1);
|
||||
CHECK(stream.readBytes(&c[1], 1) == 1);
|
||||
CHECK(stream.readBytes(&c[2], 1) == 1);
|
||||
CHECK(stream.readBytes(&c[3], 1) == 1);
|
||||
|
||||
CHECK(c == std::string("{\"heEFGH"));
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() ==
|
||||
"available() -> 28"
|
||||
"readBytes(28) -> 28");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
139
lib/ArduinoStreamUtils/extras/test/ReadLoggingClientTest.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "FailingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Clients/MemoryClient.hpp"
|
||||
#include "StreamUtils/Clients/ReadLoggingClient.hpp"
|
||||
#include "StreamUtils/Clients/SpyingClient.hpp"
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("ReadLoggingClient") {
|
||||
MemoryClient target(4);
|
||||
|
||||
StringPrint log;
|
||||
SpyingClient upstreamSpy{target, log};
|
||||
|
||||
StringPrint output;
|
||||
ReadLoggingClient loggingClient{upstreamSpy, output};
|
||||
|
||||
SUBCASE("available()") {
|
||||
target.print("ABC");
|
||||
|
||||
size_t n = loggingClient.available();
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "available() -> 3");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("connect(IPAddress)") {
|
||||
int n = loggingClient.connect(IPAddress("1.2.3.4"), 80);
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("connect(const char*)") {
|
||||
int n = loggingClient.connect("1.2.3.4", 80);
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("connected()") {
|
||||
uint8_t n = loggingClient.connected();
|
||||
|
||||
CHECK(n == false);
|
||||
CHECK(log.str() == "connected() -> 0");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("stop()") {
|
||||
loggingClient.stop();
|
||||
|
||||
CHECK(log.str() == "stop()");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("operator bool()") {
|
||||
bool n = loggingClient.operator bool();
|
||||
|
||||
CHECK(n == true);
|
||||
CHECK(log.str() == "operator bool() -> true");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("peek()") {
|
||||
target.print("ABC");
|
||||
|
||||
int n = loggingClient.peek();
|
||||
|
||||
CHECK(n == 'A');
|
||||
CHECK(log.str() == "peek() -> 65");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
target.print("ABC");
|
||||
|
||||
int n = loggingClient.read();
|
||||
|
||||
CHECK(n == 'A');
|
||||
CHECK(log.str() == "read() -> 65");
|
||||
CHECK(output.str() == "A");
|
||||
}
|
||||
|
||||
SUBCASE("read(uint8_t*,size_t)") {
|
||||
target.print("ABC");
|
||||
|
||||
uint8_t s[4] = {0};
|
||||
size_t n = loggingClient.read(s, 4);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "read(4) -> 3 [timeout]");
|
||||
CHECK(output.str() == "ABC");
|
||||
}
|
||||
|
||||
SUBCASE("readBytes()") {
|
||||
target.print("ABC");
|
||||
|
||||
char s[4] = {0};
|
||||
size_t n = loggingClient.readBytes(s, 4);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(output.str() == "ABC");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "readBytes(4) -> 3 [timeout]");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("write(char)") {
|
||||
int n = loggingClient.write('A');
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "write('A') -> 1");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,size_t)") {
|
||||
int n = loggingClient.write("ABCDEF", 6);
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(log.str() == "write('ABCDEF', 6) -> 4");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("flush()") {
|
||||
loggingClient.flush();
|
||||
|
||||
CHECK(log.str() == "flush()");
|
||||
}
|
||||
}
|
||||
89
lib/ArduinoStreamUtils/extras/test/ReadLoggingStreamTest.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "FailingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
#include "StreamUtils/Streams/MemoryStream.hpp"
|
||||
#include "StreamUtils/Streams/ReadLoggingStream.hpp"
|
||||
#include "StreamUtils/Streams/SpyingStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("ReadLoggingStream") {
|
||||
MemoryStream upstream(4);
|
||||
|
||||
StringPrint log;
|
||||
SpyingStream upstreamSpy{upstream, log};
|
||||
|
||||
StringPrint output;
|
||||
ReadLoggingStream loggingStream{upstreamSpy, output};
|
||||
|
||||
SUBCASE("available()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
size_t n = loggingStream.available();
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "available() -> 3");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("peek()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
int n = loggingStream.peek();
|
||||
|
||||
CHECK(n == 'A');
|
||||
CHECK(log.str() == "peek() -> 65");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
int n = loggingStream.read();
|
||||
|
||||
CHECK(n == 'A');
|
||||
CHECK(log.str() == "read() -> 65");
|
||||
CHECK(output.str() == "A");
|
||||
}
|
||||
|
||||
SUBCASE("readBytes()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
char s[4] = {0};
|
||||
size_t n = loggingStream.readBytes(s, 4);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(output.str() == "ABC");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "readBytes(4) -> 3 [timeout]");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("write(char)") {
|
||||
int n = loggingStream.write('A');
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "write('A') -> 1");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,size_t)") {
|
||||
int n = loggingStream.write("ABCDEF", 6);
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(log.str() == "write('ABCDEF', 6) -> 4");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("flush()") {
|
||||
loggingStream.flush();
|
||||
|
||||
CHECK(log.str() == "flush()");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "FailingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Streams/ReadThrottlingStream.hpp"
|
||||
#include "StreamUtils/Streams/StringStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
class SpyingThrottler {
|
||||
public:
|
||||
SpyingThrottler(uint32_t rate) {
|
||||
_log << "C(" << rate << ")";
|
||||
}
|
||||
|
||||
SpyingThrottler(const SpyingThrottler& src) {
|
||||
_log << src._log.str();
|
||||
}
|
||||
|
||||
void throttle() {
|
||||
_log << "T";
|
||||
}
|
||||
|
||||
std::string log() const {
|
||||
return _log.str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::stringstream _log;
|
||||
};
|
||||
|
||||
using ReadThrottlingStream = BasicReadThrottlingStream<SpyingThrottler>;
|
||||
|
||||
TEST_CASE("ReadThrottlingStream") {
|
||||
StringStream upstream;
|
||||
|
||||
ReadThrottlingStream throttledStream{upstream, 4};
|
||||
Stream& stream = throttledStream;
|
||||
const SpyingThrottler& throttler = throttledStream.throttler();
|
||||
|
||||
SUBCASE("available()") {
|
||||
upstream.print("ABCD");
|
||||
CHECK(stream.available() == 4);
|
||||
CHECK(throttler.log() == "C(4)");
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
upstream.print("ABCD");
|
||||
int n = stream.read();
|
||||
|
||||
CHECK(n == 'A');
|
||||
CHECK(throttler.log() == "C(4)T");
|
||||
}
|
||||
|
||||
SUBCASE("readBytes()") {
|
||||
upstream.print("ABCD");
|
||||
char output[8] = {0};
|
||||
|
||||
SUBCASE("read more than available") {
|
||||
size_t n = stream.readBytes(output, sizeof(output));
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(strcmp("ABCD", output) == 0);
|
||||
CHECK(throttler.log() == "C(4)TTTTT");
|
||||
}
|
||||
|
||||
SUBCASE("read less than available") {
|
||||
size_t n = stream.readBytes(output, 2);
|
||||
|
||||
CHECK(n == 2);
|
||||
CHECK(strcmp("AB", output) == 0);
|
||||
CHECK(throttler.log() == "C(4)TT");
|
||||
}
|
||||
|
||||
SUBCASE("read as many as available") {
|
||||
size_t n = stream.readBytes(output, 4);
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(strcmp("ABCD", output) == 0);
|
||||
CHECK(throttler.log() == "C(4)TTTT");
|
||||
}
|
||||
}
|
||||
}
|
||||
36
lib/ArduinoStreamUtils/extras/test/SpyingAllocator.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "StreamUtils/Ports/DefaultAllocator.hpp"
|
||||
|
||||
class SpyingAllocator {
|
||||
public:
|
||||
SpyingAllocator(Print& log) : _log(&log) {}
|
||||
|
||||
bool forceFail = false;
|
||||
|
||||
void* allocate(size_t n) {
|
||||
void* ptr = forceFail ? 0 : _allocator.allocate(n);
|
||||
_log->print("allocate(");
|
||||
_log->print(n);
|
||||
_log->print(") -> ");
|
||||
_log->print(ptr ? "ptr" : "null");
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void deallocate(void* ptr) {
|
||||
_log->print("deallocate(");
|
||||
_log->print(ptr ? "ptr" : "null");
|
||||
_log->print(")");
|
||||
_allocator.deallocate(ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
Print* _log;
|
||||
StreamUtils::DefaultAllocator _allocator;
|
||||
};
|
||||
77
lib/ArduinoStreamUtils/extras/test/StringPrintTest.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("StringPrint") {
|
||||
WHEN("Constructed with no argument") {
|
||||
StringPrint s;
|
||||
|
||||
THEN("str() return an empty String") {
|
||||
CHECK(s.str() == "");
|
||||
}
|
||||
|
||||
THEN("write(uint8_t) appends the string") {
|
||||
s.write('A');
|
||||
s.write('B');
|
||||
CHECK(s.str() == "AB");
|
||||
}
|
||||
|
||||
THEN("write(uint8_t) return 1") {
|
||||
CHECK(s.write('A') == 1);
|
||||
CHECK(s.write('B') == 1);
|
||||
}
|
||||
|
||||
THEN("write(0) return 0") {
|
||||
CHECK(s.write(0) == 0);
|
||||
}
|
||||
|
||||
THEN("write(uint8_t*, size_t) appends the string") {
|
||||
s.write(reinterpret_cast<const uint8_t*>("ABXXX"), 2);
|
||||
s.write(reinterpret_cast<const uint8_t*>("CDEXX"), 3);
|
||||
CHECK(s.str() == "ABCDE");
|
||||
}
|
||||
|
||||
THEN("write(uint8_t*, size_t) return number of chars written") {
|
||||
uint8_t dummy[32] = {1, 2, 3, 0, 5, 6};
|
||||
CHECK(s.write(dummy, 2) == 2);
|
||||
CHECK(s.write(dummy, 3) == 3);
|
||||
CHECK(s.write(dummy, 4) == 3);
|
||||
}
|
||||
|
||||
THEN("str(String) sets the string") {
|
||||
s.str("world!");
|
||||
CHECK(s.str() == "world!");
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("Constructed with string") {
|
||||
StringPrint s("hello");
|
||||
|
||||
THEN("str() return the stirng passed to contructor") {
|
||||
CHECK(s.str() == "hello");
|
||||
}
|
||||
|
||||
THEN("write(uint8_t) appends the string") {
|
||||
s.write('A');
|
||||
s.write('B');
|
||||
CHECK(s.str() == "helloAB");
|
||||
}
|
||||
|
||||
THEN("write(uint8_t*, size_t) appends the string") {
|
||||
s.write(reinterpret_cast<const uint8_t*>("ABXXX"), 2);
|
||||
s.write(reinterpret_cast<const uint8_t*>("CDEXX"), 3);
|
||||
CHECK(s.str() == "helloABCDE");
|
||||
}
|
||||
|
||||
THEN("str(String) replaces the string") {
|
||||
s.str("world!");
|
||||
CHECK(s.str() == "world!");
|
||||
}
|
||||
}
|
||||
}
|
||||
116
lib/ArduinoStreamUtils/extras/test/StringStreamTest.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "StreamUtils/Streams/StringStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("StringStream") {
|
||||
WHEN("Constructed with no argument") {
|
||||
StringStream s;
|
||||
|
||||
THEN("str() return an empty String") {
|
||||
CHECK(s.str() == "");
|
||||
}
|
||||
|
||||
THEN("write(uint8_t) appends the string") {
|
||||
s.write('A');
|
||||
s.write('B');
|
||||
CHECK(s.str() == "AB");
|
||||
}
|
||||
|
||||
THEN("write(uint8_t) return 1") {
|
||||
CHECK(s.write('A') == 1);
|
||||
CHECK(s.write('B') == 1);
|
||||
}
|
||||
|
||||
THEN("write(0) return 0") {
|
||||
CHECK(s.write(0) == 0);
|
||||
}
|
||||
|
||||
THEN("write(uint8_t*, size_t) appends the string") {
|
||||
s.write(reinterpret_cast<const uint8_t*>("ABXXX"), 2);
|
||||
s.write(reinterpret_cast<const uint8_t*>("CDEXX"), 3);
|
||||
CHECK(s.str() == "ABCDE");
|
||||
}
|
||||
|
||||
THEN("write(uint8_t*, size_t) return number of chars written") {
|
||||
uint8_t dummy[32] = {1, 2, 3, 0, 5, 6};
|
||||
CHECK(s.write(dummy, 2) == 2);
|
||||
CHECK(s.write(dummy, 3) == 3);
|
||||
CHECK(s.write(dummy, 4) == 3);
|
||||
}
|
||||
|
||||
THEN("str(String) sets the string") {
|
||||
s.str("world!");
|
||||
CHECK(s.str() == "world!");
|
||||
}
|
||||
|
||||
THEN("available() returns 0") {
|
||||
CHECK(s.available() == 0);
|
||||
}
|
||||
|
||||
THEN("peek() return -1") {
|
||||
CHECK(s.peek() == -1);
|
||||
}
|
||||
|
||||
THEN("peek() return -1") {
|
||||
CHECK(s.read() == -1);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("Constructed with string") {
|
||||
StringStream s("hello");
|
||||
|
||||
THEN("str() returns the string passed to contructor") {
|
||||
CHECK(s.str() == "hello");
|
||||
}
|
||||
|
||||
THEN("available() returns the length passed to the constructor") {
|
||||
CHECK(s.available() == 5);
|
||||
}
|
||||
|
||||
THEN("write(uint8_t) appends the string") {
|
||||
s.write('A');
|
||||
s.write('B');
|
||||
CHECK(s.str() == "helloAB");
|
||||
}
|
||||
|
||||
THEN("write(uint8_t*, size_t) appends the string") {
|
||||
s.write(reinterpret_cast<const uint8_t*>("ABXXX"), 2);
|
||||
s.write(reinterpret_cast<const uint8_t*>("CDEXX"), 3);
|
||||
CHECK(s.str() == "helloABCDE");
|
||||
}
|
||||
|
||||
THEN("str(String) replaces the string") {
|
||||
s.str("world!");
|
||||
CHECK(s.str() == "world!");
|
||||
}
|
||||
|
||||
THEN("peek() return the first char") {
|
||||
CHECK(s.peek() == 'h');
|
||||
}
|
||||
|
||||
THEN("peek() return the next char") {
|
||||
CHECK(s.read() == 'h');
|
||||
CHECK(s.read() == 'e');
|
||||
}
|
||||
|
||||
THEN("readBytes() can return the begining of the string") {
|
||||
char buffer[32] = {0};
|
||||
CHECK(s.readBytes(buffer, 3) == 3);
|
||||
CHECK(buffer == std::string("hel"));
|
||||
CHECK(s.available() == 2);
|
||||
}
|
||||
|
||||
THEN("readBytes() can return the whole string") {
|
||||
char buffer[32] = {0};
|
||||
CHECK(s.readBytes(buffer, 32) == 5);
|
||||
CHECK(buffer == std::string("hello"));
|
||||
CHECK(s.available() == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
104
lib/ArduinoStreamUtils/extras/test/WaitingPrintTest.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "FailingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
#include "StreamUtils/Prints/WaitingPrint.hpp"
|
||||
#include "StreamUtils/Streams/MemoryStream.hpp"
|
||||
#include "StreamUtils/Streams/SpyingStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("WaitingPrint") {
|
||||
MemoryStream upstream(4);
|
||||
|
||||
StringPrint log;
|
||||
SpyingStream spy{upstream, log};
|
||||
WaitingPrint stream{static_cast<Print&>(spy), [&spy]() { spy.flush(); }};
|
||||
|
||||
SUBCASE("write(char*, size_t)") {
|
||||
SUBCASE("no need to wait") {
|
||||
CHECK(stream.print("ABC") == 3);
|
||||
|
||||
CHECK(log.str() == "write('ABC', 3) -> 3");
|
||||
}
|
||||
|
||||
SUBCASE("need to wait") {
|
||||
CHECK(stream.print("ABCDEFG") == 7);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('ABCDEFG', 7) -> 4"
|
||||
"flush()"
|
||||
"write('EFG', 3) -> 3");
|
||||
}
|
||||
|
||||
SUBCASE("need to wait twice") {
|
||||
CHECK(stream.print("ABCDEFGIJKL") == 11);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('ABCDEFGIJKL', 11) -> 4"
|
||||
"flush()"
|
||||
"write('EFGIJKL', 7) -> 4"
|
||||
"flush()"
|
||||
"write('JKL', 3) -> 3");
|
||||
}
|
||||
|
||||
SUBCASE("doesn't wait when timeout is 0") {
|
||||
stream.setTimeout(0);
|
||||
|
||||
CHECK(stream.print("ABCDEFG") == 4);
|
||||
|
||||
CHECK(log.str() == "write('ABCDEFG', 7) -> 4");
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("write(char)") {
|
||||
SUBCASE("no need to wait") {
|
||||
CHECK(stream.write('A') == 1);
|
||||
CHECK(stream.write('B') == 1);
|
||||
CHECK(stream.write('C') == 1);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('A') -> 1"
|
||||
"write('B') -> 1"
|
||||
"write('C') -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("need to wait") {
|
||||
for (int i = 0; i < 7; i++)
|
||||
CHECK(stream.write("ABCDEFG"[i]) == 1);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('A') -> 1"
|
||||
"write('B') -> 1"
|
||||
"write('C') -> 1"
|
||||
"write('D') -> 1"
|
||||
"write('E') -> 0"
|
||||
"flush()"
|
||||
"write('E') -> 1"
|
||||
"write('F') -> 1"
|
||||
"write('G') -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("doesn't wait when timeout is 0") {
|
||||
stream.setTimeout(0);
|
||||
|
||||
CHECK(stream.write('A') == 1);
|
||||
CHECK(stream.write('B') == 1);
|
||||
CHECK(stream.write('C') == 1);
|
||||
CHECK(stream.write('D') == 1);
|
||||
CHECK(stream.write('E') == 0);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('A') -> 1"
|
||||
"write('B') -> 1"
|
||||
"write('C') -> 1"
|
||||
"write('D') -> 1"
|
||||
"write('E') -> 0");
|
||||
}
|
||||
}
|
||||
}
|
||||
203
lib/ArduinoStreamUtils/extras/test/WriteBufferingClientTest.cpp
Normal file
@@ -0,0 +1,203 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "FailingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Clients/MemoryClient.hpp"
|
||||
#include "StreamUtils/Clients/SpyingClient.hpp"
|
||||
#include "StreamUtils/Clients/WriteBufferingClient.hpp"
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("WriteBufferingClient") {
|
||||
MemoryClient target(64);
|
||||
|
||||
StringPrint log;
|
||||
SpyingClient spy{target, log};
|
||||
|
||||
GIVEN("capacity is 4") {
|
||||
WriteBufferingClient bufferingClient{spy, 4};
|
||||
|
||||
SUBCASE("available()") {
|
||||
target.print("ABC");
|
||||
|
||||
CHECK(bufferingClient.available() == 3);
|
||||
CHECK(log.str() == "available() -> 3");
|
||||
}
|
||||
|
||||
SUBCASE("connect(IPAddress)") {
|
||||
int n = bufferingClient.connect(IPAddress("1.2.3.4"), 80);
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("connect(const char*)") {
|
||||
int n = bufferingClient.connect("1.2.3.4", 80);
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("connected()") {
|
||||
uint8_t n = bufferingClient.connected();
|
||||
|
||||
CHECK(n == false);
|
||||
CHECK(log.str() == "connected() -> 0");
|
||||
}
|
||||
|
||||
SUBCASE("stop()") {
|
||||
bufferingClient.write("ABC", 3);
|
||||
bufferingClient.stop();
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('ABC', 3) -> 3"
|
||||
"stop()");
|
||||
}
|
||||
|
||||
SUBCASE("operator bool()") {
|
||||
bool n = bufferingClient.operator bool();
|
||||
|
||||
CHECK(n == true);
|
||||
CHECK(log.str() == "operator bool() -> true");
|
||||
}
|
||||
|
||||
SUBCASE("flush() forwards to target)") {
|
||||
bufferingClient.flush();
|
||||
|
||||
CHECK(log.str() == "flush()");
|
||||
}
|
||||
|
||||
SUBCASE("flush() calls write() and flush()") {
|
||||
bufferingClient.write("ABC", 3);
|
||||
bufferingClient.flush();
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('ABC', 3) -> 3"
|
||||
"flush()");
|
||||
}
|
||||
|
||||
SUBCASE("peek()") {
|
||||
target.print("ABC");
|
||||
|
||||
CHECK(bufferingClient.peek() == 'A');
|
||||
CHECK(log.str() == "peek() -> 65");
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
target.print("ABC");
|
||||
|
||||
CHECK(bufferingClient.read() == 'A');
|
||||
CHECK(log.str() == "read() -> 65");
|
||||
}
|
||||
|
||||
SUBCASE("readBytes()") {
|
||||
target.print("ABC");
|
||||
|
||||
char s[4] = {0};
|
||||
int n = bufferingClient.readBytes(s, 3);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(s == std::string("ABC"));
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "readBytes(3) -> 3");
|
||||
#endif
|
||||
}
|
||||
|
||||
GIVEN("the buffer is empty") {
|
||||
SUBCASE("write(uint8_t)") {
|
||||
int n = bufferingClient.write('A');
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("write(uint8_t) should flush") {
|
||||
bufferingClient.write('A');
|
||||
bufferingClient.write('B');
|
||||
bufferingClient.write('C');
|
||||
bufferingClient.write('D');
|
||||
bufferingClient.write('E');
|
||||
|
||||
CHECK(log.str() == "write('ABCD', 4) -> 4");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,3) goes in buffer") {
|
||||
size_t n = bufferingClient.write("ABC", 3);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,4) bypasses buffer") {
|
||||
size_t n = bufferingClient.write("ABCD", 4);
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(log.str() == "write('ABCD', 4) -> 4");
|
||||
}
|
||||
SUBCASE("write(char*,2) bypasses buffer") {
|
||||
size_t n = bufferingClient.write("ABCD", 4);
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(log.str() == "write('ABCD', 4) -> 4");
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("one byte in the buffer") {
|
||||
bufferingClient.write('A');
|
||||
|
||||
SUBCASE("write(char*,3) goes in buffer and flush") {
|
||||
size_t n = bufferingClient.write("BCD", 3);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "write('ABCD', 4) -> 4");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,7) bypasses") {
|
||||
size_t n = bufferingClient.write("BCDEFGH", 7);
|
||||
|
||||
CHECK(n == 7);
|
||||
CHECK(log.str() ==
|
||||
"write('ABCD', 4) -> 4"
|
||||
"write('EFGH', 4) -> 4");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("capacity is 0") {
|
||||
WriteBufferingClient bufferingClient{spy, 0};
|
||||
|
||||
SUBCASE("write(uint8_t) forwards to target") {
|
||||
int n = bufferingClient.write('X');
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "write('X') -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,1) forwards to target") {
|
||||
int n = bufferingClient.write("A", 1);
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "write('A', 1) -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("flush() forwards to target") {
|
||||
bufferingClient.flush();
|
||||
|
||||
CHECK(log.str() == "flush()");
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("Destructor should flush") {
|
||||
{
|
||||
WriteBufferingClient bufferingClient{spy, 10};
|
||||
bufferingClient.write("ABC", 3);
|
||||
}
|
||||
|
||||
CHECK(log.str() == "write('ABC', 3) -> 3");
|
||||
}
|
||||
}
|
||||
166
lib/ArduinoStreamUtils/extras/test/WriteBufferingStreamTest.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "FailingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
#include "StreamUtils/Streams/MemoryStream.hpp"
|
||||
#include "StreamUtils/Streams/SpyingStream.hpp"
|
||||
#include "StreamUtils/Streams/WriteBufferingStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("WriteBufferingStream") {
|
||||
MemoryStream upstream(64);
|
||||
|
||||
StringPrint log;
|
||||
SpyingStream spy{upstream, log};
|
||||
|
||||
GIVEN("capacity is 4") {
|
||||
WriteBufferingStream stream{spy, 4};
|
||||
|
||||
SUBCASE("available()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
CHECK(stream.available() == 3);
|
||||
CHECK(log.str() == "available() -> 3");
|
||||
}
|
||||
|
||||
SUBCASE("flush() forwards to upstream)") {
|
||||
stream.flush();
|
||||
|
||||
CHECK(log.str() == "flush()");
|
||||
}
|
||||
|
||||
SUBCASE("flush() calls write() and flush()") {
|
||||
stream.write("ABC", 3);
|
||||
stream.flush();
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('ABC', 3) -> 3"
|
||||
"flush()");
|
||||
}
|
||||
|
||||
SUBCASE("peek()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
CHECK(stream.peek() == 'A');
|
||||
CHECK(log.str() == "peek() -> 65");
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
CHECK(stream.read() == 'A');
|
||||
CHECK(log.str() == "read() -> 65");
|
||||
}
|
||||
|
||||
SUBCASE("readBytes()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
char s[4] = {0};
|
||||
int n = stream.readBytes(s, 3);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(s == std::string("ABC"));
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "readBytes(3) -> 3");
|
||||
#endif
|
||||
}
|
||||
|
||||
GIVEN("the buffer is empty") {
|
||||
SUBCASE("write(uint8_t)") {
|
||||
int n = stream.write('A');
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("write(uint8_t) should flush") {
|
||||
stream.write('A');
|
||||
stream.write('B');
|
||||
stream.write('C');
|
||||
stream.write('D');
|
||||
stream.write('E');
|
||||
|
||||
CHECK(log.str() == "write('ABCD', 4) -> 4");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,3) goes in buffer") {
|
||||
size_t n = stream.write("ABC", 3);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,4) bypasses buffer") {
|
||||
size_t n = stream.write("ABCD", 4);
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(log.str() == "write('ABCD', 4) -> 4");
|
||||
}
|
||||
SUBCASE("write(char*,2) bypasses buffer") {
|
||||
size_t n = stream.write("ABCD", 4);
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(log.str() == "write('ABCD', 4) -> 4");
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("one byte in the buffer") {
|
||||
stream.write('A');
|
||||
|
||||
SUBCASE("write(char*,3) goes in buffer and flush") {
|
||||
size_t n = stream.write("BCD", 3);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "write('ABCD', 4) -> 4");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,7) bypasses") {
|
||||
size_t n = stream.write("BCDEFGH", 7);
|
||||
|
||||
CHECK(n == 7);
|
||||
CHECK(log.str() ==
|
||||
"write('ABCD', 4) -> 4"
|
||||
"write('EFGH', 4) -> 4");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("capacity is 0") {
|
||||
WriteBufferingStream stream{spy, 0};
|
||||
|
||||
SUBCASE("write(uint8_t) forwards to upstream") {
|
||||
int n = stream.write('X');
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "write('X') -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,1) forwards to upstream") {
|
||||
int n = stream.write("A", 1);
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "write('A', 1) -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("flush() forwards to upstream") {
|
||||
stream.flush();
|
||||
|
||||
CHECK(log.str() == "flush()");
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("Destructor should flush") {
|
||||
{
|
||||
WriteBufferingStream stream{spy, 10};
|
||||
stream.write("ABC", 3);
|
||||
}
|
||||
|
||||
CHECK(log.str() == "write('ABC', 3) -> 3");
|
||||
}
|
||||
}
|
||||
140
lib/ArduinoStreamUtils/extras/test/WriteLoggingClientTest.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "FailingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Clients/MemoryClient.hpp"
|
||||
#include "StreamUtils/Clients/SpyingClient.hpp"
|
||||
#include "StreamUtils/Clients/WriteLoggingClient.hpp"
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("WriteLoggingClient") {
|
||||
MemoryClient target(4);
|
||||
|
||||
StringPrint log;
|
||||
SpyingClient spy{target, log};
|
||||
|
||||
StringPrint output;
|
||||
WriteLoggingClient loggingClient{spy, output};
|
||||
|
||||
SUBCASE("available()") {
|
||||
target.print("ABC");
|
||||
|
||||
size_t n = loggingClient.available();
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "available() -> 3");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("connect(IPAddress)") {
|
||||
int n = loggingClient.connect(IPAddress("1.2.3.4"), 80);
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("connect(const char*)") {
|
||||
int n = loggingClient.connect("1.2.3.4", 80);
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("connected()") {
|
||||
uint8_t n = loggingClient.connected();
|
||||
|
||||
CHECK(n == false);
|
||||
CHECK(log.str() == "connected() -> 0");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("stop()") {
|
||||
loggingClient.stop();
|
||||
|
||||
CHECK(log.str() == "stop()");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("operator bool()") {
|
||||
bool n = loggingClient.operator bool();
|
||||
|
||||
CHECK(n == true);
|
||||
CHECK(log.str() == "operator bool() -> true");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("peek()") {
|
||||
target.print("ABC");
|
||||
|
||||
int n = loggingClient.peek();
|
||||
|
||||
CHECK(n == 'A');
|
||||
CHECK(log.str() == "peek() -> 65");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
target.print("ABC");
|
||||
|
||||
int n = loggingClient.read();
|
||||
|
||||
CHECK(n == 'A');
|
||||
CHECK(log.str() == "read() -> 65");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("read(uint8_t*,size_t)") {
|
||||
target.print("ABC");
|
||||
|
||||
uint8_t s[4] = {0};
|
||||
size_t n = loggingClient.read(s, 4);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "read(4) -> 3 [timeout]");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("readBytes()") {
|
||||
target.print("ABC");
|
||||
|
||||
char s[4] = {0};
|
||||
size_t n = loggingClient.readBytes(s, 4);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(output.str() == "");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "readBytes(4) -> 3 [timeout]");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("write(char)") {
|
||||
int n = loggingClient.write('A');
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "write('A') -> 1");
|
||||
CHECK(output.str() == "A");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,size_t)") {
|
||||
int n = loggingClient.write("ABCDEF", 6);
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(log.str() == "write('ABCDEF', 6) -> 4");
|
||||
CHECK(output.str() == "ABCD");
|
||||
}
|
||||
|
||||
SUBCASE("flush()") {
|
||||
loggingClient.flush();
|
||||
|
||||
CHECK(output.str() == "");
|
||||
CHECK(log.str() == "flush()");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "FailingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
#include "StreamUtils/Streams/MemoryStream.hpp"
|
||||
#include "StreamUtils/Streams/SpyingStream.hpp"
|
||||
#include "StreamUtils/Streams/WriteLoggingStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("WriteLoggingStream") {
|
||||
MemoryStream upstream(4);
|
||||
|
||||
StringPrint log;
|
||||
SpyingStream upstreamSpy{upstream, log};
|
||||
|
||||
StringPrint output;
|
||||
WriteLoggingStream loggingStream{upstreamSpy, output};
|
||||
|
||||
SUBCASE("available()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
size_t n = loggingStream.available();
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(log.str() == "available() -> 3");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("peek()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
int n = loggingStream.peek();
|
||||
|
||||
CHECK(n == 'A');
|
||||
CHECK(log.str() == "peek() -> 65");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("read()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
int n = loggingStream.read();
|
||||
|
||||
CHECK(n == 'A');
|
||||
CHECK(log.str() == "read() -> 65");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
|
||||
SUBCASE("readBytes()") {
|
||||
upstream.print("ABC");
|
||||
|
||||
char s[4] = {0};
|
||||
size_t n = loggingStream.readBytes(s, 4);
|
||||
|
||||
CHECK(n == 3);
|
||||
CHECK(output.str() == "");
|
||||
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
|
||||
CHECK(log.str() == "readBytes(4) -> 3 [timeout]");
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("write(char)") {
|
||||
int n = loggingStream.write('A');
|
||||
|
||||
CHECK(n == 1);
|
||||
CHECK(log.str() == "write('A') -> 1");
|
||||
CHECK(output.str() == "A");
|
||||
}
|
||||
|
||||
SUBCASE("write(char*,size_t)") {
|
||||
int n = loggingStream.write("ABCDEF", 6);
|
||||
|
||||
CHECK(n == 4);
|
||||
CHECK(log.str() == "write('ABCDEF', 6) -> 4");
|
||||
CHECK(output.str() == "ABCD");
|
||||
}
|
||||
|
||||
SUBCASE("flush()") {
|
||||
loggingStream.flush();
|
||||
|
||||
CHECK(log.str() == "flush()");
|
||||
CHECK(output.str() == "");
|
||||
}
|
||||
}
|
||||
104
lib/ArduinoStreamUtils/extras/test/WriteWaitingClientTest.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "FailingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Clients/MemoryClient.hpp"
|
||||
#include "StreamUtils/Clients/SpyingClient.hpp"
|
||||
#include "StreamUtils/Clients/WriteWaitingClient.hpp"
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("WriteWaitingClient") {
|
||||
MemoryClient upstream(4);
|
||||
|
||||
StringPrint log;
|
||||
SpyingClient spy{upstream, log};
|
||||
WriteWaitingClient client{spy, [&spy]() { spy.flush(); }};
|
||||
|
||||
SUBCASE("write(char*, size_t)") {
|
||||
SUBCASE("no need to wait") {
|
||||
CHECK(client.print("ABC") == 3);
|
||||
|
||||
CHECK(log.str() == "write('ABC', 3) -> 3");
|
||||
}
|
||||
|
||||
SUBCASE("need to wait") {
|
||||
CHECK(client.print("ABCDEFG") == 7);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('ABCDEFG', 7) -> 4"
|
||||
"flush()"
|
||||
"write('EFG', 3) -> 3");
|
||||
}
|
||||
|
||||
SUBCASE("need to wait twice") {
|
||||
CHECK(client.print("ABCDEFGIJKL") == 11);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('ABCDEFGIJKL', 11) -> 4"
|
||||
"flush()"
|
||||
"write('EFGIJKL', 7) -> 4"
|
||||
"flush()"
|
||||
"write('JKL', 3) -> 3");
|
||||
}
|
||||
|
||||
SUBCASE("doesn't wait when timeout is 0") {
|
||||
client.setTimeout(0);
|
||||
|
||||
CHECK(client.print("ABCDEFG") == 4);
|
||||
|
||||
CHECK(log.str() == "write('ABCDEFG', 7) -> 4");
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("write(char)") {
|
||||
SUBCASE("no need to wait") {
|
||||
CHECK(client.write('A') == 1);
|
||||
CHECK(client.write('B') == 1);
|
||||
CHECK(client.write('C') == 1);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('A') -> 1"
|
||||
"write('B') -> 1"
|
||||
"write('C') -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("need to wait") {
|
||||
for (int i = 0; i < 7; i++)
|
||||
CHECK(client.write("ABCDEFG"[i]) == 1);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('A') -> 1"
|
||||
"write('B') -> 1"
|
||||
"write('C') -> 1"
|
||||
"write('D') -> 1"
|
||||
"write('E') -> 0"
|
||||
"flush()"
|
||||
"write('E') -> 1"
|
||||
"write('F') -> 1"
|
||||
"write('G') -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("doesn't wait when timeout is 0") {
|
||||
client.setTimeout(0);
|
||||
|
||||
CHECK(client.write('A') == 1);
|
||||
CHECK(client.write('B') == 1);
|
||||
CHECK(client.write('C') == 1);
|
||||
CHECK(client.write('D') == 1);
|
||||
CHECK(client.write('E') == 0);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('A') -> 1"
|
||||
"write('B') -> 1"
|
||||
"write('C') -> 1"
|
||||
"write('D') -> 1"
|
||||
"write('E') -> 0");
|
||||
}
|
||||
}
|
||||
}
|
||||
104
lib/ArduinoStreamUtils/extras/test/WriteWaitingStreamTest.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "FailingAllocator.hpp"
|
||||
|
||||
#include "StreamUtils/Prints/StringPrint.hpp"
|
||||
#include "StreamUtils/Streams/MemoryStream.hpp"
|
||||
#include "StreamUtils/Streams/SpyingStream.hpp"
|
||||
#include "StreamUtils/Streams/WriteWaitingStream.hpp"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
using namespace StreamUtils;
|
||||
|
||||
TEST_CASE("WriteWaitingStream") {
|
||||
MemoryStream upstream(4);
|
||||
|
||||
StringPrint log;
|
||||
SpyingStream spy{upstream, log};
|
||||
WriteWaitingStream stream{spy, [&spy]() { spy.flush(); }};
|
||||
|
||||
SUBCASE("write(char*, size_t)") {
|
||||
SUBCASE("no need to wait") {
|
||||
CHECK(stream.print("ABC") == 3);
|
||||
|
||||
CHECK(log.str() == "write('ABC', 3) -> 3");
|
||||
}
|
||||
|
||||
SUBCASE("need to wait") {
|
||||
CHECK(stream.print("ABCDEFG") == 7);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('ABCDEFG', 7) -> 4"
|
||||
"flush()"
|
||||
"write('EFG', 3) -> 3");
|
||||
}
|
||||
|
||||
SUBCASE("need to wait twice") {
|
||||
CHECK(stream.print("ABCDEFGIJKL") == 11);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('ABCDEFGIJKL', 11) -> 4"
|
||||
"flush()"
|
||||
"write('EFGIJKL', 7) -> 4"
|
||||
"flush()"
|
||||
"write('JKL', 3) -> 3");
|
||||
}
|
||||
|
||||
SUBCASE("doesn't wait when timeout is 0") {
|
||||
stream.setTimeout(0);
|
||||
|
||||
CHECK(stream.print("ABCDEFG") == 4);
|
||||
|
||||
CHECK(log.str() == "write('ABCDEFG', 7) -> 4");
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("write(char)") {
|
||||
SUBCASE("no need to wait") {
|
||||
CHECK(stream.write('A') == 1);
|
||||
CHECK(stream.write('B') == 1);
|
||||
CHECK(stream.write('C') == 1);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('A') -> 1"
|
||||
"write('B') -> 1"
|
||||
"write('C') -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("need to wait") {
|
||||
for (int i = 0; i < 7; i++)
|
||||
CHECK(stream.write("ABCDEFG"[i]) == 1);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('A') -> 1"
|
||||
"write('B') -> 1"
|
||||
"write('C') -> 1"
|
||||
"write('D') -> 1"
|
||||
"write('E') -> 0"
|
||||
"flush()"
|
||||
"write('E') -> 1"
|
||||
"write('F') -> 1"
|
||||
"write('G') -> 1");
|
||||
}
|
||||
|
||||
SUBCASE("doesn't wait when timeout is 0") {
|
||||
stream.setTimeout(0);
|
||||
|
||||
CHECK(stream.write('A') == 1);
|
||||
CHECK(stream.write('B') == 1);
|
||||
CHECK(stream.write('C') == 1);
|
||||
CHECK(stream.write('D') == 1);
|
||||
CHECK(stream.write('E') == 0);
|
||||
|
||||
CHECK(log.str() ==
|
||||
"write('A') -> 1"
|
||||
"write('B') -> 1"
|
||||
"write('C') -> 1"
|
||||
"write('D') -> 1"
|
||||
"write('E') -> 0");
|
||||
}
|
||||
}
|
||||
}
|
||||
18
lib/ArduinoStreamUtils/extras/test/cores/avr/Arduino.h
Normal file
@@ -0,0 +1,18 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Client.h>
|
||||
#include <Print.h>
|
||||
#include <Stream.h>
|
||||
#include <WString.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
inline unsigned long millis() {
|
||||
return static_cast<unsigned long>(time(NULL));
|
||||
}
|
||||
|
||||
inline void yield() {}
|
||||
22
lib/ArduinoStreamUtils/extras/test/cores/avr/CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
# StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
# Copyright Benoit Blanchon 2019-2021
|
||||
# MIT License
|
||||
|
||||
add_library(AvrCore
|
||||
Client.h
|
||||
EEPROM.cpp
|
||||
EEPROM.h
|
||||
Print.h
|
||||
Stream.h
|
||||
WString.h
|
||||
)
|
||||
|
||||
target_include_directories(AvrCore
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
target_compile_definitions(AvrCore
|
||||
PUBLIC
|
||||
ARDUINO_ARCH_AVR
|
||||
)
|
||||
27
lib/ArduinoStreamUtils/extras/test/cores/avr/Client.h
Normal file
@@ -0,0 +1,27 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Stream.h"
|
||||
#include "WString.h"
|
||||
|
||||
using IPAddress = String;
|
||||
|
||||
struct Client : Stream {
|
||||
virtual int connect(IPAddress ip, uint16_t port) = 0;
|
||||
virtual int connect(const char *host, uint16_t port) = 0;
|
||||
virtual uint8_t connected() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual operator bool() = 0;
|
||||
|
||||
// Already in Stream
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
virtual size_t write(const uint8_t *buf, size_t size) = 0;
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
|
||||
// Curiously not in Stream
|
||||
virtual int read(uint8_t *buf, size_t size) = 0;
|
||||
};
|
||||
12
lib/ArduinoStreamUtils/extras/test/cores/avr/EEPROM.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "EEPROM.h"
|
||||
|
||||
EEPROMClass EEPROM;
|
||||
static uint8_t data[512];
|
||||
|
||||
uint8_t EEPROMClass::read(int address) {
|
||||
return data[address];
|
||||
}
|
||||
|
||||
void EEPROMClass::update(int address, uint8_t value) {
|
||||
data[address] = value;
|
||||
}
|
||||
12
lib/ArduinoStreamUtils/extras/test/cores/avr/EEPROM.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class EEPROMClass {
|
||||
public:
|
||||
uint8_t read(int);
|
||||
void update(int, uint8_t);
|
||||
// void write(int, uint8_t); <- it exists but we want to use update() instead
|
||||
};
|
||||
|
||||
extern EEPROMClass EEPROM;
|
||||
42
lib/ArduinoStreamUtils/extras/test/cores/avr/Print.h
Normal file
@@ -0,0 +1,42 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
|
||||
#include <WString.h>
|
||||
|
||||
struct Print {
|
||||
virtual size_t write(const uint8_t *buffer, size_t size) = 0;
|
||||
virtual size_t write(uint8_t data) = 0;
|
||||
virtual void flush() {}
|
||||
|
||||
size_t write(const char *buffer, size_t size) {
|
||||
return write((const uint8_t *)buffer, size);
|
||||
}
|
||||
|
||||
size_t print(const String &s) {
|
||||
return write(s.c_str(), s.length());
|
||||
}
|
||||
|
||||
size_t print(const char *s) {
|
||||
return write(s, std::strlen(s));
|
||||
}
|
||||
|
||||
size_t println() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t print(const T &value) {
|
||||
return print(String(value));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t println(const T &value) {
|
||||
return print(value);
|
||||
}
|
||||
};
|
||||
41
lib/ArduinoStreamUtils/extras/test/cores/avr/Stream.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
struct Stream : Print {
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int peek() = 0;
|
||||
|
||||
size_t readBytes(char *buffer, size_t length) {
|
||||
size_t count = 0;
|
||||
while (count < length) {
|
||||
int c = timedRead();
|
||||
if (c < 0)
|
||||
break;
|
||||
*buffer++ = (char)c;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
String readString() {
|
||||
String result;
|
||||
int c;
|
||||
while ((c = timedRead()) >= 0) {
|
||||
result += static_cast<char>(c);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void setTimeout(unsigned long) {}
|
||||
|
||||
protected:
|
||||
int timedRead() {
|
||||
return read();
|
||||
}
|
||||
};
|
||||
43
lib/ArduinoStreamUtils/extras/test/cores/avr/WString.h
Normal file
@@ -0,0 +1,43 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class String : private std::string {
|
||||
public:
|
||||
String() {}
|
||||
String(const String& s) : std::string(s) {}
|
||||
String(String&& s) : std::string(std::move(s)) {}
|
||||
String(const char* s) : std::string(s) {}
|
||||
String(int n) : std::string(std::to_string(n)) {}
|
||||
|
||||
String& operator=(const String& rhs) {
|
||||
std::string::operator=(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
using std::string::c_str;
|
||||
using std::string::length;
|
||||
using std::string::operator+=;
|
||||
using std::string::operator[];
|
||||
|
||||
void remove(unsigned int index, unsigned int count) {
|
||||
erase(begin() + index, begin() + index + count);
|
||||
}
|
||||
|
||||
void toCharArray(char* buf, unsigned int bufsize,
|
||||
unsigned int index = 0) const {
|
||||
copy(buf, bufsize, index);
|
||||
}
|
||||
|
||||
friend bool operator==(const String& lhs, const char* rhs) {
|
||||
return static_cast<const std::string&>(lhs) == rhs;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const String& rhs) {
|
||||
return lhs << static_cast<const std::string&>(rhs);
|
||||
}
|
||||
};
|
||||
18
lib/ArduinoStreamUtils/extras/test/cores/esp32/Arduino.h
Normal file
@@ -0,0 +1,18 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Client.h>
|
||||
#include <Print.h>
|
||||
#include <Stream.h>
|
||||
#include <WString.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
inline unsigned long millis() {
|
||||
return static_cast<unsigned long>(time(NULL));
|
||||
}
|
||||
|
||||
inline void yield() {}
|
||||
@@ -0,0 +1,22 @@
|
||||
# StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
# Copyright Benoit Blanchon 2019-2021
|
||||
# MIT License
|
||||
|
||||
add_library(Esp32Core
|
||||
Client.h
|
||||
EEPROM.cpp
|
||||
EEPROM.h
|
||||
Print.h
|
||||
Stream.h
|
||||
WString.h
|
||||
)
|
||||
|
||||
target_include_directories(Esp32Core
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
target_compile_definitions(Esp32Core
|
||||
PUBLIC
|
||||
ARDUINO_ARCH_ESP32
|
||||
)
|
||||
26
lib/ArduinoStreamUtils/extras/test/cores/esp32/Client.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Stream.h"
|
||||
#include "WString.h"
|
||||
|
||||
using IPAddress = String;
|
||||
|
||||
class Client : public Stream {
|
||||
public:
|
||||
virtual int connect(IPAddress ip, uint16_t port) = 0;
|
||||
virtual int connect(const char *host, uint16_t port) = 0;
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
virtual size_t write(const uint8_t *buf, size_t size) = 0;
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int read(uint8_t *buf, size_t size) = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual uint8_t connected() = 0;
|
||||
virtual operator bool() = 0;
|
||||
};
|
||||
20
lib/ArduinoStreamUtils/extras/test/cores/esp32/EEPROM.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "EEPROM.h"
|
||||
|
||||
#include <string.h> // memcpy
|
||||
|
||||
EEPROMClass EEPROM;
|
||||
static uint8_t commitedData[512];
|
||||
static uint8_t pendingData[512];
|
||||
|
||||
uint8_t EEPROMClass::read(int address) {
|
||||
return commitedData[address];
|
||||
}
|
||||
|
||||
void EEPROMClass::write(int address, uint8_t value) {
|
||||
pendingData[address] = value;
|
||||
}
|
||||
|
||||
bool EEPROMClass::commit() {
|
||||
memcpy(commitedData, pendingData, 512);
|
||||
return true;
|
||||
}
|
||||
12
lib/ArduinoStreamUtils/extras/test/cores/esp32/EEPROM.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class EEPROMClass {
|
||||
public:
|
||||
uint8_t read(int);
|
||||
void write(int, uint8_t);
|
||||
bool commit();
|
||||
};
|
||||
|
||||
extern EEPROMClass EEPROM;
|
||||
42
lib/ArduinoStreamUtils/extras/test/cores/esp32/Print.h
Normal file
@@ -0,0 +1,42 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <WString.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
|
||||
struct Print {
|
||||
virtual ~Print() {}
|
||||
virtual size_t write(const uint8_t *buffer, size_t size) = 0;
|
||||
virtual size_t write(uint8_t data) = 0;
|
||||
|
||||
size_t write(const char *buffer, size_t size) {
|
||||
return write((const uint8_t *)buffer, size);
|
||||
}
|
||||
|
||||
size_t print(const String &s) {
|
||||
return write(s.c_str(), s.length());
|
||||
}
|
||||
|
||||
size_t print(const char *s) {
|
||||
return write(s, std::strlen(s));
|
||||
}
|
||||
|
||||
size_t println() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t print(const T &value) {
|
||||
return print(String(value));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t println(const T &value) {
|
||||
return print(value);
|
||||
}
|
||||
};
|
||||
48
lib/ArduinoStreamUtils/extras/test/cores/esp32/Stream.h
Normal file
@@ -0,0 +1,48 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
struct Stream : Print {
|
||||
virtual ~Stream() {}
|
||||
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
|
||||
virtual size_t readBytes(char *buffer, size_t length) {
|
||||
size_t count = 0;
|
||||
while (count < length) {
|
||||
int c = timedRead();
|
||||
if (c < 0)
|
||||
break;
|
||||
*buffer++ = (char)c;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
virtual size_t readBytes(uint8_t *buffer, size_t length) {
|
||||
return readBytes((char *)buffer, length);
|
||||
}
|
||||
|
||||
virtual String readString() {
|
||||
String result;
|
||||
int c;
|
||||
while ((c = timedRead()) >= 0) {
|
||||
result += c;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void setTimeout(unsigned long) {}
|
||||
|
||||
protected:
|
||||
int timedRead() {
|
||||
return read();
|
||||
}
|
||||
};
|
||||
5
lib/ArduinoStreamUtils/extras/test/cores/esp32/WString.h
Normal file
@@ -0,0 +1,5 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "../avr/WString.h"
|
||||
18
lib/ArduinoStreamUtils/extras/test/cores/esp8266/Arduino.h
Normal file
@@ -0,0 +1,18 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Client.h>
|
||||
#include <Print.h>
|
||||
#include <Stream.h>
|
||||
#include <WString.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
inline unsigned long millis() {
|
||||
return static_cast<unsigned long>(time(NULL));
|
||||
}
|
||||
|
||||
inline void yield() {}
|
||||
@@ -0,0 +1,22 @@
|
||||
# StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
# Copyright Benoit Blanchon 2019-2021
|
||||
# MIT License
|
||||
|
||||
add_library(Esp8266Core
|
||||
Client.h
|
||||
EEPROM.cpp
|
||||
EEPROM.h
|
||||
Print.h
|
||||
Stream.h
|
||||
WString.h
|
||||
)
|
||||
|
||||
target_include_directories(Esp8266Core
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
target_compile_definitions(Esp8266Core
|
||||
PUBLIC
|
||||
ARDUINO_ARCH_ESP8266
|
||||
)
|
||||
26
lib/ArduinoStreamUtils/extras/test/cores/esp8266/Client.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Stream.h"
|
||||
#include "WString.h"
|
||||
|
||||
using IPAddress = String;
|
||||
|
||||
class Client : public Stream {
|
||||
public:
|
||||
virtual int connect(IPAddress ip, uint16_t port) = 0;
|
||||
virtual int connect(const char *host, uint16_t port) = 0;
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
virtual size_t write(const uint8_t *buf, size_t size) = 0;
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int read(uint8_t *buf, size_t size) = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual uint8_t connected() = 0;
|
||||
virtual operator bool() = 0;
|
||||
};
|
||||
19
lib/ArduinoStreamUtils/extras/test/cores/esp8266/EEPROM.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "EEPROM.h"
|
||||
|
||||
#include <string.h> // memcpy
|
||||
|
||||
EEPROMClass EEPROM;
|
||||
static uint8_t commitedData[512];
|
||||
static uint8_t pendingData[512];
|
||||
|
||||
uint8_t EEPROMClass::read(int address) {
|
||||
return commitedData[address];
|
||||
}
|
||||
|
||||
void EEPROMClass::write(int address, uint8_t value) {
|
||||
pendingData[address] = value;
|
||||
}
|
||||
|
||||
void EEPROMClass::commit() {
|
||||
memcpy(commitedData, pendingData, 512);
|
||||
}
|
||||
12
lib/ArduinoStreamUtils/extras/test/cores/esp8266/EEPROM.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class EEPROMClass {
|
||||
public:
|
||||
uint8_t read(int);
|
||||
void write(int, uint8_t);
|
||||
void commit();
|
||||
};
|
||||
|
||||
extern EEPROMClass EEPROM;
|
||||
43
lib/ArduinoStreamUtils/extras/test/cores/esp8266/Print.h
Normal file
@@ -0,0 +1,43 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <WString.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
|
||||
struct Print {
|
||||
virtual size_t write(const uint8_t *buffer, size_t size) = 0;
|
||||
virtual size_t write(uint8_t data) = 0;
|
||||
|
||||
size_t write(const char *buffer, size_t size) {
|
||||
return write((const uint8_t *)buffer, size);
|
||||
}
|
||||
|
||||
size_t print(const String &s) {
|
||||
return write(s.c_str(), s.length());
|
||||
}
|
||||
|
||||
size_t print(const char *s) {
|
||||
return write(s, std::strlen(s));
|
||||
}
|
||||
|
||||
size_t println() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t print(const T &value) {
|
||||
return print(String(value));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t println(const T &value) {
|
||||
return print(value);
|
||||
}
|
||||
|
||||
virtual void flush() {}
|
||||
};
|
||||
45
lib/ArduinoStreamUtils/extras/test/cores/esp8266/Stream.h
Normal file
@@ -0,0 +1,45 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
struct Stream : Print {
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int peek() = 0;
|
||||
|
||||
virtual size_t readBytes(char *buffer, size_t length) {
|
||||
size_t count = 0;
|
||||
while (count < length) {
|
||||
int c = timedRead();
|
||||
if (c < 0)
|
||||
break;
|
||||
*buffer++ = (char)c;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
virtual size_t readBytes(uint8_t *buffer, size_t length) {
|
||||
return readBytes((char *)buffer, length);
|
||||
}
|
||||
|
||||
virtual String readString() {
|
||||
String result;
|
||||
int c;
|
||||
while ((c = timedRead()) >= 0) {
|
||||
result += c;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void setTimeout(unsigned long) {}
|
||||
|
||||
protected:
|
||||
int timedRead() {
|
||||
return read();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
|
||||
// Copyright Benoit Blanchon 2019-2021
|
||||
// MIT License
|
||||
|
||||
#include "../avr/WString.h"
|
||||