From 376a2e7f6e9f63d8cb3010715c4776d91a137741 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 5 May 2024 15:43:31 +0200 Subject: [PATCH] StreamConcat example --- examples/StreamFiles/StreamConcat.h | 33 +++++++++++++ examples/StreamFiles/StreamFiles.ino | 73 ++++++++++++++++++++++++++++ examples/StreamFiles/StreamString.h | 36 ++++++++++++++ platformio.ini | 5 +- 4 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 examples/StreamFiles/StreamConcat.h create mode 100644 examples/StreamFiles/StreamFiles.ino create mode 100644 examples/StreamFiles/StreamString.h diff --git a/examples/StreamFiles/StreamConcat.h b/examples/StreamFiles/StreamConcat.h new file mode 100644 index 0000000..ba95ebe --- /dev/null +++ b/examples/StreamFiles/StreamConcat.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +class StreamConcat : public Stream { + public: + StreamConcat(Stream* s1, Stream* s2) : _s1(s1), _s2(s2) {} + + size_t write(const uint8_t* p, size_t n) override { return 0; } + size_t write(uint8_t c) override { return 0; } + void flush() override {} + + int available() override { return _s1->available() + _s2->available(); } + + int read() override { + int c = _s1->read(); + return c != -1 ? c : _s2->read(); + } + + size_t readBytes(char* buffer, size_t length) override { + size_t count = _s1->readBytes(buffer, length); + return count > 0 ? count : _s2->readBytes(buffer, length); + } + + int peek() override { + int c = _s1->peek(); + return c != -1 ? c : _s2->peek(); + } + + private: + Stream* _s1; + Stream* _s2; +}; diff --git a/examples/StreamFiles/StreamFiles.ino b/examples/StreamFiles/StreamFiles.ino new file mode 100644 index 0000000..d5621f5 --- /dev/null +++ b/examples/StreamFiles/StreamFiles.ino @@ -0,0 +1,73 @@ +#include +#include +#ifdef ESP32 +#include +#include +#elif defined(ESP8266) +#include +#include +#endif +#include "StreamConcat.h" +#include "StreamString.h" +#include +#include + +DNSServer dnsServer; +AsyncWebServer server(80); + +void setup() { + Serial.begin(115200); + + LittleFS.begin(); + + WiFi.mode(WIFI_AP); + WiFi.softAP("esp-captive"); + dnsServer.start(53, "*", WiFi.softAPIP()); + + File file1 = LittleFS.open("/header.html", "w"); + file1.print("ESP Captive Portal"); + file1.close(); + + File file2 = LittleFS.open("/body.html", "w"); + file2.print("

Welcome to ESP Captive Portal

"); + file2.close(); + + File file3 = LittleFS.open("/footer.html", "w"); + file3.print(""); + file3.close(); + + server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) { + File header = LittleFS.open("/header.html", "r"); + File body = LittleFS.open("/body.html", "r"); + StreamConcat stream1(&header, &body); + + StreamString content; + content.printf("FreeHeap: %" PRIu32, ESP.getFreeHeap()); + StreamConcat stream2 = StreamConcat(&stream1, &content); + + File footer = LittleFS.open("/footer.html", "r"); + StreamConcat stream3 = StreamConcat(&stream2, &footer); + + request->send(stream3, "text/html", stream3.available()); + header.close(); + body.close(); + footer.close(); + }); + + server.onNotFound([](AsyncWebServerRequest* request) { + request->send(404, "text/plain", "Not found"); + }); + + server.begin(); +} + +uint32_t last = 0; + +void loop() { + // dnsServer.processNextRequest(); + + if (millis() - last > 2000) { + Serial.printf("FreeHeap: %" PRIu32, ESP.getFreeHeap()); + last = millis(); + } +} \ No newline at end of file diff --git a/examples/StreamFiles/StreamString.h b/examples/StreamFiles/StreamString.h new file mode 100644 index 0000000..f392b45 --- /dev/null +++ b/examples/StreamFiles/StreamString.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +class StreamString : public Stream { + public: + size_t write(const uint8_t* p, size_t n) override { return _buffer.concat(reinterpret_cast(p), n) ? n : 0; } + size_t write(uint8_t c) override { return _buffer.concat(static_cast(c)) ? 1 : 0; } + void flush() override {} + + int available() override { return static_cast(_buffer.length()); } + + int read() override { + if (_buffer.length() == 0) + return -1; + char c = _buffer[0]; + _buffer.remove(0, 1); + return c; + } + + size_t readBytes(char* buffer, size_t length) override { + if (length > _buffer.length()) + length = _buffer.length(); + // Don't use _str.ToCharArray() because it inserts a terminator + memcpy(buffer, _buffer.c_str(), length); + _buffer.remove(0, static_cast(length)); + return length; + } + + int peek() override { return _buffer.length() > 0 ? _buffer[0] : -1; } + + const String& buffer() const { return _buffer; } + + private: + String _buffer; +}; diff --git a/platformio.ini b/platformio.ini index 0bcd99e..cdb0381 100644 --- a/platformio.ini +++ b/platformio.ini @@ -3,7 +3,7 @@ framework = arduino build_flags = -Wall -Wextra -D CONFIG_ARDUHAL_LOG_COLORS - -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG + ; -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG lib_deps = bblanchon/ArduinoJson @ 7.0.4 mathieucarbou/Async TCP @ ^3.1.2 @@ -13,8 +13,9 @@ monitor_filters = esp32_exception_decoder, log2file [platformio] lib_dir = . -src_dir = examples/CaptivePortal +; src_dir = examples/CaptivePortal ; src_dir = examples/SimpleServer +src_dir = examples/StreamFiles [env:v660] platform = espressif32@6.6.0