From 1af677d88bb6507f5bf798a373b6f83a81fbde0a Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Fri, 14 Jun 2024 01:34:29 +0530 Subject: [PATCH] feat: add rp2040 support --- .github/workflows/ci.yml | 9 ++++++- README.md | 3 ++- docs/_config.yml | 2 +- docs/index.md | 3 ++- examples/CaptivePortal/CaptivePortal.ino | 3 +++ examples/Filters/Filters.ino | 3 +++ examples/SimpleServer/SimpleServer.ino | 3 +++ examples/StreamFiles/StreamConcat.h | 4 +++ examples/StreamFiles/StreamFiles.ino | 11 +++++++++ examples/StreamFiles/StreamString.h | 4 +++ library.json | 11 +++++++-- library.properties | 4 +-- platformio.ini | 12 +++++++++ src/AsyncEventSource.cpp | 4 +-- src/AsyncEventSource.h | 7 +++++- src/AsyncWebSocket.cpp | 10 ++++---- src/AsyncWebSocket.h | 8 +++++- src/ESPAsyncWebServer.h | 31 +++++++++++++++--------- src/WebAuthentication.cpp | 4 +-- src/WebHandlers.cpp | 8 ++++++ 20 files changed, 114 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c23d2ea..9b477bd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,10 @@ jobs: - core: esp8266:esp8266 board: esp8266:esp8266:huzzah index_url: https://arduino.esp8266.com/stable/package_esp8266com_index.json - + - name: package_rp2040_index.json + core: rp2040:rp2040 + board: rp2040:rp2040:rpipicow + index_url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json steps: - name: Checkout uses: actions/checkout@v4 @@ -55,6 +58,10 @@ jobs: if: ${{ matrix.core == 'esp8266:esp8266' }} run: ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL=true arduino-cli lib install --git-url https://github.com/mathieucarbou/esphome-ESPAsyncTCP#v2.0.0 + - name: Install AsyncTCP (RP2040) + if: ${{ matrix.core == 'rp2040:rp2040' }} + run: ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL=true arduino-cli lib install --git-url https://github.com/khoih-prog/AsyncTCP_RP2040W#v1.2.0 + - name: Build CaptivePortal run: arduino-cli compile --library . --warnings none -b ${{ matrix.board }} "examples/CaptivePortal/CaptivePortal.ino" diff --git a/README.md b/README.md index dc87c07..888ae66 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,14 @@ [![Continuous Integration](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml/badge.svg)](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml) [![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/ESP%20Async%20WebServer.svg)](https://registry.platformio.org/libraries/mathieucarbou/ESP%20Async%20WebServer) -Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 +Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040 Supports: WebSocket, SSE, Authentication, Arduino Json 7, File Upload, Static File serving, URL Rewrite, URL Redirect, etc. This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubox-node-org/ESPAsyncWebServer) and includes all the concurrency fixes. ## Changes in this fork +- [@ayushsharma82](https://github.com/ayushsharma82) and [@mathieucarbou](https://github.com/mathieucarbou): Add RP2040 support ([#31](https://github.com/mathieucarbou/ESPAsyncWebServer/pull/31)) - [@mathieucarbou](https://github.com/mathieucarbou): `SSE_MAX_QUEUED_MESSAGES` to control the maximum number of messages that can be queued for a SSE client - [@mathieucarbou](https://github.com/mathieucarbou): `write()` function public in `AsyncEventSource.h` - [@mathieucarbou](https://github.com/mathieucarbou): `WS_MAX_QUEUED_MESSAGES`: control the maximum number of messages that can be queued for a Websocket client diff --git a/docs/_config.yml b/docs/_config.yml index 95d65c2..e6d54d2 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,7 +1,7 @@ # bundle exec jekyll serve --host=0.0.0.0 title: ESP Async WebServer -description: "Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266" +description: "Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040" remote_theme: pages-themes/cayman@v0.2.0 plugins: - jekyll-remote-theme diff --git a/docs/index.md b/docs/index.md index dc87c07..888ae66 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,13 +4,14 @@ [![Continuous Integration](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml/badge.svg)](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml) [![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/ESP%20Async%20WebServer.svg)](https://registry.platformio.org/libraries/mathieucarbou/ESP%20Async%20WebServer) -Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 +Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040 Supports: WebSocket, SSE, Authentication, Arduino Json 7, File Upload, Static File serving, URL Rewrite, URL Redirect, etc. This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubox-node-org/ESPAsyncWebServer) and includes all the concurrency fixes. ## Changes in this fork +- [@ayushsharma82](https://github.com/ayushsharma82) and [@mathieucarbou](https://github.com/mathieucarbou): Add RP2040 support ([#31](https://github.com/mathieucarbou/ESPAsyncWebServer/pull/31)) - [@mathieucarbou](https://github.com/mathieucarbou): `SSE_MAX_QUEUED_MESSAGES` to control the maximum number of messages that can be queued for a SSE client - [@mathieucarbou](https://github.com/mathieucarbou): `write()` function public in `AsyncEventSource.h` - [@mathieucarbou](https://github.com/mathieucarbou): `WS_MAX_QUEUED_MESSAGES`: control the maximum number of messages that can be queued for a Websocket client diff --git a/examples/CaptivePortal/CaptivePortal.ino b/examples/CaptivePortal/CaptivePortal.ino index cb0b193..2d0de89 100644 --- a/examples/CaptivePortal/CaptivePortal.ino +++ b/examples/CaptivePortal/CaptivePortal.ino @@ -5,6 +5,9 @@ #elif defined(ESP8266) #include #include +#elif defined(TARGET_RP2040) + #include + #include #endif #include "ESPAsyncWebServer.h" diff --git a/examples/Filters/Filters.ino b/examples/Filters/Filters.ino index d26c59f..f031a1f 100644 --- a/examples/Filters/Filters.ino +++ b/examples/Filters/Filters.ino @@ -7,6 +7,9 @@ #elif defined(ESP8266) #include #include +#elif defined(TARGET_RP2040) + #include + #include #endif #include "ESPAsyncWebServer.h" diff --git a/examples/SimpleServer/SimpleServer.ino b/examples/SimpleServer/SimpleServer.ino index ed07401..2472674 100644 --- a/examples/SimpleServer/SimpleServer.ino +++ b/examples/SimpleServer/SimpleServer.ino @@ -12,6 +12,9 @@ #elif defined(ESP8266) #include #include +#elif defined(TARGET_RP2040) + #include + #include #endif #include diff --git a/examples/StreamFiles/StreamConcat.h b/examples/StreamFiles/StreamConcat.h index 1a53f2c..c1e1927 100644 --- a/examples/StreamFiles/StreamConcat.h +++ b/examples/StreamFiles/StreamConcat.h @@ -17,7 +17,11 @@ class StreamConcat : public Stream { return c != -1 ? c : _s2->read(); } +#if defined(TARGET_RP2040) + size_t readBytes(char* buffer, size_t length) { +#else size_t readBytes(char* buffer, size_t length) override { +#endif size_t count = _s1->readBytes(buffer, length); return count > 0 ? count : _s2->readBytes(buffer, length); } diff --git a/examples/StreamFiles/StreamFiles.ino b/examples/StreamFiles/StreamFiles.ino index 424768c..2a2c1b6 100644 --- a/examples/StreamFiles/StreamFiles.ino +++ b/examples/StreamFiles/StreamFiles.ino @@ -6,6 +6,9 @@ #elif defined(ESP8266) #include #include +#elif defined(TARGET_RP2040) + #include + #include #endif #include "StreamConcat.h" #include "StreamString.h" @@ -42,7 +45,11 @@ void setup() { StreamConcat stream1(&header, &body); StreamString content; +#if defined(TARGET_RP2040) + content.printf("FreeHeap: %d", rp2040.getFreeHeap()); +#else content.printf("FreeHeap: %" PRIu32, ESP.getFreeHeap()); +#endif StreamConcat stream2 = StreamConcat(&stream1, &content); File footer = LittleFS.open("/footer.html", "r"); @@ -67,7 +74,11 @@ void loop() { // dnsServer.processNextRequest(); if (millis() - last > 2000) { +#if defined(TARGET_RP2040) + Serial.printf("FreeHeap: %d", rp2040.getFreeHeap()); +#else Serial.printf("FreeHeap: %" PRIu32, ESP.getFreeHeap()); +#endif last = millis(); } } \ No newline at end of file diff --git a/examples/StreamFiles/StreamString.h b/examples/StreamFiles/StreamString.h index f392b45..a6e0655 100644 --- a/examples/StreamFiles/StreamString.h +++ b/examples/StreamFiles/StreamString.h @@ -18,7 +18,11 @@ class StreamString : public Stream { return c; } +#if defined(TARGET_RP2040) + size_t readBytes(char* buffer, size_t length) { +#else size_t readBytes(char* buffer, size_t length) override { +#endif if (length > _buffer.length()) length = _buffer.length(); // Don't use _str.ToCharArray() because it inserts a terminator diff --git a/library.json b/library.json index acd320c..c6442c9 100644 --- a/library.json +++ b/library.json @@ -1,7 +1,7 @@ { "name": "ESP Async WebServer", "version": "2.10.8", - "description": "Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266. Supports: WebSocket, SSE, Authentication, Arduino Json 7, File Upload, Static File serving, URL Rewrite, URL Redirect, etc.", + "description": "Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040. Supports: WebSocket, SSE, Authentication, Arduino Json 7, File Upload, Static File serving, URL Rewrite, URL Redirect, etc.", "keywords": "http,async,websocket,webserver", "homepage": "https://github.com/mathieucarbou/ESPAsyncWebServer", "repository": { @@ -21,7 +21,8 @@ "frameworks": "arduino", "platforms": [ "espressif32", - "espressif8266" + "espressif8266", + "raspberrypi" ], "dependencies": [ { @@ -39,6 +40,12 @@ { "name": "Hash", "platforms": "espressif8266" + }, + { + "owner": "khoih-prog", + "name": "AsyncTCP_RP2040W", + "version": "^1.2.0", + "platforms": "raspberrypi" } ], "export": { diff --git a/library.properties b/library.properties index 3858af9..a147a7c 100644 --- a/library.properties +++ b/library.properties @@ -2,9 +2,9 @@ name=ESP Async WebServer version=2.10.8 author=Me-No-Dev maintainer=Mathieu Carbou -sentence=Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 +sentence=Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040 paragraph=Supports: WebSocket, SSE, Authentication, Arduino Json 7, File Upload, Static File serving, URL Rewrite, URL Redirect, etc category=Other url=https://github.com/mathieucarbou/ESPAsyncWebServer -architectures=esp8266,esp32 +architectures=* license=LGPL-3.0 diff --git a/platformio.ini b/platformio.ini index 795b32d..9535be4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -46,3 +46,15 @@ board = huzzah lib_deps = bblanchon/ArduinoJson @ 7.0.4 esphome/ESPAsyncTCP-esphome @ 2.0.0 + +; PlatformIO support for Raspberry Pi Pico is not official +; https://github.com/platformio/platform-raspberrypi/pull/36 +; https://github.com/earlephilhower/arduino-pico/blob/master/docs/platformio.rst +; board settings: https://github.com/earlephilhower/arduino-pico/blob/master/tools/json/rpipico.json +[env:rpipicow] +upload_protocol = picotool +platform = https://github.com/maxgerhardt/platform-raspberrypi.git +board = rpipicow +lib_deps = + bblanchon/ArduinoJson @ 7.0.4 + khoih-prog/AsyncTCP_RP2040W @ 1.2.0 diff --git a/src/AsyncEventSource.cpp b/src/AsyncEventSource.cpp index 87d8293..4cafdae 100644 --- a/src/AsyncEventSource.cpp +++ b/src/AsyncEventSource.cpp @@ -18,7 +18,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "Arduino.h" -#ifndef ESP8266 +#if defined(ESP32) #include #endif #include "AsyncEventSource.h" @@ -190,7 +190,7 @@ void AsyncEventSourceClient::_queueMessage(const char* message, size_t len) { if (_messageQueue.size() >= SSE_MAX_QUEUED_MESSAGES) { #ifdef ESP8266 ets_printf(String(F("ERROR: Too many messages queued\n")).c_str()); -#else +#elif defined(ESP32) log_e("Too many messages queued: deleting message"); #endif return; diff --git a/src/AsyncEventSource.h b/src/AsyncEventSource.h index 93a4176..0289ebf 100644 --- a/src/AsyncEventSource.h +++ b/src/AsyncEventSource.h @@ -28,11 +28,16 @@ #ifndef SSE_MAX_QUEUED_MESSAGES #define SSE_MAX_QUEUED_MESSAGES 32 #endif -#else // esp8266 +#elif defined(ESP8266) #include #ifndef SSE_MAX_QUEUED_MESSAGES #define SSE_MAX_QUEUED_MESSAGES 8 #endif +#elif defined(TARGET_RP2040) + #include + #ifndef SSE_MAX_QUEUED_MESSAGES + #define SSE_MAX_QUEUED_MESSAGES 32 + #endif #endif #include diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp index 8f1e6a8..e978afc 100644 --- a/src/AsyncWebSocket.cpp +++ b/src/AsyncWebSocket.cpp @@ -25,14 +25,14 @@ #include -#ifndef ESP8266 +#if defined(ESP32) #if ESP_IDF_VERSION_MAJOR < 5 #include "./port/SHA1Builder.h" #else #include #endif #include -#else +#elif defined(TARGET_RP2040) || defined(ESP8266) #include #endif @@ -417,7 +417,7 @@ void AsyncWebSocketClient::_queueMessage(AsyncWebSocketSharedBuffer buffer, uint if (closeWhenFull) { #ifdef ESP8266 ets_printf("AsyncWebSocketClient::_queueMessage: Too many messages queued: closing connection\n"); -#else +#elif defined(ESP32) log_e("Too many messages queued: closing connection"); #endif _status = WS_DISCONNECTED; @@ -426,7 +426,7 @@ void AsyncWebSocketClient::_queueMessage(AsyncWebSocketSharedBuffer buffer, uint } else { #ifdef ESP8266 ets_printf("AsyncWebSocketClient::_queueMessage: Too many messages queued: discarding new message\n"); -#else +#elif defined(ESP32) log_e("Too many messages queued: discarding new message"); #endif } @@ -1155,7 +1155,7 @@ AsyncWebSocketResponse::AsyncWebSocketResponse(const String& key, AsyncWebSocket uint8_t hash[20]; char buffer[33]; -#ifdef ESP8266 +#if defined(ESP8266) || defined(TARGET_RP2040) sha1(key + WS_STR_UUID, hash); #else String k; diff --git a/src/AsyncWebSocket.h b/src/AsyncWebSocket.h index 10e9537..77bf7ee 100644 --- a/src/AsyncWebSocket.h +++ b/src/AsyncWebSocket.h @@ -28,12 +28,18 @@ #ifndef WS_MAX_QUEUED_MESSAGES #define WS_MAX_QUEUED_MESSAGES 32 #endif -#else +#elif defined(ESP8266) #include #ifndef WS_MAX_QUEUED_MESSAGES #define WS_MAX_QUEUED_MESSAGES 8 #endif +#elif defined(TARGET_RP2040) + #include + #ifndef WS_MAX_QUEUED_MESSAGES + #define WS_MAX_QUEUED_MESSAGES 32 + #endif #endif + #include #include diff --git a/src/ESPAsyncWebServer.h b/src/ESPAsyncWebServer.h index cfb829a..eae878c 100644 --- a/src/ESPAsyncWebServer.h +++ b/src/ESPAsyncWebServer.h @@ -34,6 +34,11 @@ #elif defined(ESP8266) #include #include +#elif defined(TARGET_RP2040) + #include + #include + #include + #include #else #error Platform not supported #endif @@ -61,17 +66,21 @@ class AsyncStaticWebHandler; class AsyncCallbackWebHandler; class AsyncResponseStream; -#ifndef WEBSERVER_H -typedef enum { - HTTP_GET = 0b00000001, - HTTP_POST = 0b00000010, - HTTP_DELETE = 0b00000100, - HTTP_PUT = 0b00001000, - HTTP_PATCH = 0b00010000, - HTTP_HEAD = 0b00100000, - HTTP_OPTIONS = 0b01000000, - HTTP_ANY = 0b01111111, -} WebRequestMethod; +#if defined (TARGET_RP2040) + typedef enum http_method WebRequestMethod; +#else + #ifndef WEBSERVER_H + typedef enum { + HTTP_GET = 0b00000001, + HTTP_POST = 0b00000010, + HTTP_DELETE = 0b00000100, + HTTP_PUT = 0b00001000, + HTTP_PATCH = 0b00010000, + HTTP_HEAD = 0b00100000, + HTTP_OPTIONS = 0b01000000, + HTTP_ANY = 0b01111111, + } WebRequestMethod; + #endif #endif #ifndef HAVE_FS_FILE_OPEN_MODE diff --git a/src/WebAuthentication.cpp b/src/WebAuthentication.cpp index 5761616..abd74b8 100644 --- a/src/WebAuthentication.cpp +++ b/src/WebAuthentication.cpp @@ -20,7 +20,7 @@ */ #include "WebAuthentication.h" #include -#ifdef ESP32 +#if defined(ESP32) || defined(TARGET_RP2040) #include #else #include "md5.h" @@ -64,7 +64,7 @@ bool checkBasicAuthentication(const char* hash, const char* username, const char } static bool getMD5(uint8_t* data, uint16_t len, char* output) { // 33 bytes or more -#ifdef ESP32 +#if defined(ESP32) || defined(TARGET_RP2040) MD5Builder md5; md5.begin(); md5.add(data, len); diff --git a/src/WebHandlers.cpp b/src/WebHandlers.cpp index 40232df..d740d86 100644 --- a/src/WebHandlers.cpp +++ b/src/WebHandlers.cpp @@ -210,7 +210,15 @@ void AsyncStaticWebHandler::handleRequest(AsyncWebServerRequest* request) { String etag; if (lw) { setLastModified(gmtime(&lw)); +#if defined(TARGET_RP2040) + // time_t == long long int + const size_t len = 1 + 8 * sizeof(time_t); + char buf[len]; + char* ret = lltoa(lw, buf, len, 10); + etag = ret ? String(ret) : String(request->_tempFile.size()); +#else etag = String(lw); +#endif } else { etag = String(request->_tempFile.size()); }