+ +
+ +--- +--- + +### Debug Terminal Output Samples + +#### 1. AsyncMultiWebServer_ESP32_ENC on ESP32_DEV with ESP32_ENC28J60 + +Following are debug terminal output and screen shots when running example [AsyncMultiWebServer_ESP32_ENC](examples/AsyncMultiWebServer_ESP32_ENC) on `ESP32_DEV with ESP32_ENC28J60`, using ESP32 core `v2.0.0+`, to demonstrate the operation of 3 independent AsyncWebServers on 3 different ports and how to handle the complicated AsyncMultiWebServers. + + +```cpp +Start AsyncMultiWebServer_ESP32_ENC on ESP32_DEV with ESP32_ENC28J60 +AsyncWebServer_ESP32_ENC v1.6.2 for core v2.0.0+ +[AWS] Default SPI pinout: +[AWS] MOSI: 23 +[AWS] MISO: 19 +[AWS] SCK: 18 +[AWS] CS: 5 +[AWS] INT: 4 +[AWS] SPI Clock (MHz): 8 +[AWS] ========================= + +ETH Started +ETH Connected +ETH MAC: DE:AD:BE:EF:FE:13, IPv4: 192.168.2.232 +FULL_DUPLEX, 10Mbps + +Connected to network. IP = 192.168.2.232 +Initialize multiServer OK, serverIndex = 0, port = 8080 +HTTP server started at ports 8080 +Initialize multiServer OK, serverIndex = 1, port = 8081 +HTTP server started at ports 8081 +Initialize multiServer OK, serverIndex = 2, port = 8082 +HTTP server started at ports 8082 +``` + +You can access the Async Advanced WebServers @ the server IP and corresponding ports (8080, 8081 and 8082) + ++ +
+ ++ +
+ ++ +
+ +--- + +#### 2. Async_AdvancedWebServer_MemoryIssues_Send_CString on ESP32_DEV with ESP32_ENC28J60 + +Following is the debug terminal and screen shot when running example [Async_AdvancedWebServer_MemoryIssues_Send_CString](examples/Async_AdvancedWebServer_MemoryIssues_Send_CString), on `ESP32_DEV with ESP32_ENC28J60`, to demonstrate the new and powerful `HEAP-saving` feature + + +##### Using CString ===> smaller heap (120,880 bytes) + +```cpp +Start Async_AdvancedWebServer_MemoryIssues_Send_CString on ESP32_DEV with ESP32_ENC28J60 +AsyncWebServer_ESP32_ENC v1.6.2 for core v2.0.0+ +[AWS] Default SPI pinout: +[AWS] MOSI: 23 +[AWS] MISO: 19 +[AWS] SCK: 18 +[AWS] CS: 5 +[AWS] INT: 4 +[AWS] SPI Clock (MHz): 8 +[AWS] ========================= + +ETH Started +ETH Connected +ETH MAC: DE:AD:BE:EF:FE:13, IPv4: 192.168.2.232 +FULL_DUPLEX, 10Mbps +HTTP EthernetWebServer is @ IP : 192.168.2.232 + +HEAP DATA - Pre Create Arduino String Max heap: 322992 Free heap: 222252 Used heap: 100740 +.... +HEAP DATA - Pre Send Max heap: 322992 Free heap: 218356 Used heap: 104636 + +HEAP DATA - Post Send Max heap: 322992 Free heap: 210204 Used heap: 112716 +... +HEAP DATA - Post Send Max heap: 322992 Free heap: 210148 Used heap: 112772 +``` + +While using `Arduino String`, the HEAP usage is very large + + +#### Async_AdvancedWebServer_MemoryIssues_SendArduinoString ===> very large heap (152,136 bytes) + +```cpp +Start Async_AdvancedWebServer_MemoryIssues_SendArduinoString on ESP32_DEV with ESP32_ENC28J60 +AsyncWebServer_ESP32_ENC v1.6.2 for core v2.0.0+ +[AWS] Default SPI pinout: +[AWS] MOSI: 23 +[AWS] MISO: 19 +[AWS] SCK: 18 +[AWS] CS: 5 +[AWS] INT: 4 +[AWS] SPI Clock (MHz): 8 +[AWS] ========================= + +ETH Started +ETH Connected +ETH MAC: DE:AD:BE:EF:BE:14, IPv4: 192.168.2.232 +FULL_DUPLEX, 10Mbps +HTTP EthernetWebServer is @ IP : 192.168.2.232 + +HEAP DATA - Pre Create Arduino String Max heap: 323272 Free heap: 262532 Used heap: 60740 +.. +HEAP DATA - Pre Send Max heap: 323272 Free heap: 218656 Used heap: 104616 + +HEAP DATA - Post Send Max heap: 323272 Free heap: 179284 Used heap: 143988 +.... +``` + + +You can access the Async Advanced WebServers at the displayed server IP, e.g. `192.168.2.232` + ++ +
+ +--- + +#### 3. Async_AdvancedWebServer_SendChunked on ESP32_DEV with ESP32_ENC28J60 + +Following is debug terminal output when running example [Async_AdvancedWebServer_SendChunked](examples/Async_AdvancedWebServer_SendChunked) on `ESP32_DEV with ESP32_ENC28J60`, using ESP32 core `v2.0.0+`, to demo how to use `beginChunkedResponse()` to send large `html` in chunks + +```cpp +Start Async_AdvancedWebServer_SendChunked on ESP32_DEV with ESP32_ENC28J60 +AsyncWebServer_ESP32_ENC v1.6.2 for core v2.0.0+ +[AWS] Default SPI pinout: +[AWS] MOSI: 23 +[AWS] MISO: 19 +[AWS] SCK: 18 +[AWS] CS: 5 +[AWS] INT: 4 +[AWS] SPI Clock (MHz): 8 +[AWS] ========================= + +ETH Started +ETH Connected +ETH MAC: DE:AD:BE:EF:FE:13, IPv4: 192.168.2.93 +FULL_DUPLEX, 10Mbps +AsyncWebServer is @ IP : 192.168.2.93 +.[AWS] Total length to send in chunks = 31259 +[AWS] Bytes sent in chunk = 5620 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2727 +[AWS] Bytes sent in chunk = 0 +.[AWS] Total length to send in chunks = 31279 +[AWS] Bytes sent in chunk = 5620 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 1428 +[AWS] Bytes sent in chunk = 1428 +[AWS] Bytes sent in chunk = 2755 +[AWS] Bytes sent in chunk = 0 + +``` + +You can access the Async Advanced WebServers @ the server IP + ++ +
+ + +--- + +#### 4. AsyncWebServer_SendChunked on ESP32_DEV with ESP32_ENC28J60 + +Following is debug terminal output when running example [AsyncWebServer_SendChunked](examples/AsyncWebServer_SendChunked) on `ESP32_DEV with ESP32_ENC28J60`, using ESP32 core `v2.0.0+`, to demo how to use `beginChunkedResponse()` to send large `html` in chunks + + +```cpp +Start AsyncWebServer_SendChunked on ESP32_DEV with ESP32_ENC28J60 +AsyncWebServer_ESP32_ENC v1.6.2 for core v2.0.0+ +[AWS] Default SPI pinout: +[AWS] MOSI: 23 +[AWS] MISO: 19 +[AWS] SCK: 18 +[AWS] CS: 5 +[AWS] INT: 4 +[AWS] SPI Clock (MHz): 8 +[AWS] ========================= + +ETH Started +ETH Connected +ETH MAC: DE:AD:BE:EF:BE:14, IPv4: 192.168.2.232 +FULL_DUPLEX, 10Mbps +AsyncWebServer is @ IP : 192.168.2.232 +.[AWS] Total length to send in chunks = 46800 +[AWS] Bytes sent in chunk = 5624 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 1428 +[AWS] Bytes sent in chunk = 1428 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 1088 +[AWS] Bytes sent in chunk = 0 +[AWS] Total length to send in chunks = 46800 +[AWS] Bytes sent in chunk = 5624 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 2864 +[AWS] Bytes sent in chunk = 1080 +[AWS] Bytes sent in chunk = 0 + +``` + +--- +--- + +### Debug + +Debug is enabled by default on Serial. Debug Level from 0 to 4. To disable, change the _ETHERNET_WEBSERVER_LOGLEVEL_ to 0 + +```cpp +// Use this to output debug msgs to Serial +#define DEBUG_ASYNC_WEBSERVER_PORT Serial +// Use this to disable all output debug msgs +// Debug Level from 0 to 4 +#define _ASYNC_WEBSERVER_LOGLEVEL_ 0 +``` + +--- + +### Troubleshooting + +If you get compilation errors, more often than not, you may need to install a newer version of Arduino IDE, the Arduino `ESP32` core or depending libraries. + +Sometimes, the library will only work if you update the `ESP32` core to the latest version because I'm always using the latest cores /libraries. + +--- + +### Issues ### + +Submit issues to: [AsyncWebServer_ESP32_ENC issues](https://github.com/khoih-prog/AsyncWebServer_ESP32_ENC/issues) + +--- +--- + +## TO DO + + 1. Fix bug. Add enhancement + 2. Add support to more Ethernet shields, such as **W5x00, DP83848, TLK110, IP101, RTL8201, DM9051, KSZ8041, KSZ8081, etc.** + +--- + +## DONE + + 1. Initial port to `ESP32` boards using `ENC28J60` Ethernet. + 2. Add more examples. + 3. Add debugging features. + 4. Add Table-of-Contents and Version String + 5. Display compiler `#warning` only when `DEBUG_LEVEL` is 3+ + 6. Fix AsyncWebSocket bug + 7. Support using `CString` to save heap to send `very large data`. Check [request->send(200, textPlainStr, jsonChartDataCharStr); - Without using String Class - to save heap #8](https://github.com/khoih-prog/Portenta_H7_AsyncWebServer/pull/8) + 8. Add examples [Async_AdvancedWebServer_SendChunked](https://github.com/khoih-prog/AsyncWebServer_RP2040W/tree/main/examples/Async_AdvancedWebServer_SendChunked) and [AsyncWebServer_SendChunked](https://github.com/khoih-prog/AsyncWebServer_RP2040W/tree/main/examples/AsyncWebServer_SendChunked) to demo how to use `beginChunkedResponse()` to send large `html` in chunks + 9. Use `allman astyle` and add `utils` + + +--- +--- + + +### Contributions and Thanks + +1. Based on and modified from [Hristo Gochkov's ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer). Many thanks to [Hristo Gochkov](https://github.com/me-no-dev) for great [ESPAsyncWebServer Library](https://github.com/me-no-dev/ESPAsyncWebServer) +2. Thanks to [tobozo](https://github.com/tobozo) to make the library [ESP32-ENC28J60](https://github.com/tobozo/ESP32-ENC28J60) from which this library uses some ideas and codes + + +⭐️⭐️ Hristo Gochkov |
+ tobozo |
+
Uptime: %d d %02d:%02d:%02d
\ +\ +", BOARD_NAME, BOARD_NAME, day, hr % 24, min % 60, sec % 60); + + pageInput = temp; +} + +void handleNotFound(AsyncWebServerRequest *request) +{ + String message = "File Not Found\n\n"; + + message += "URI: "; + message += request->url(); + message += "\nMethod: "; + message += (request->method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += request->args(); + message += "\n"; + + for (uint8_t i = 0; i < request->args(); i++) + { + message += " " + request->argName(i) + ": " + request->arg(i) + "\n"; + } + + request->send(404, "text/plain", message); +} + +String out; + +void handleRoot(AsyncWebServerRequest *request) +{ + out.reserve(STRING_SIZE); + char temp[70]; + + // clear the String to start over + out = String(); + + createPage(out); + + out += "\r\nINDEX | DATA |
---|---|
"; + out += String(lineIndex); + out += " | "; + out += "ESP32_ENC_AsyncWebServer_SendChunked_ABCDEFGHIJKLMNOPQRSTUVWXYZ |
Uptime: %d d %02d:%02d:%02d
\ +\ +\ +", BOARD_NAME, BOARD_NAME, day, hr % 24, min % 60, sec % 60); + + request->send(200, "text/html", temp); +} + +void handleNotFound(AsyncWebServerRequest *request) +{ + String message = "File Not Found\n\n"; + + message += "URI: "; + message += request->url(); + message += "\nMethod: "; + message += (request->method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += request->args(); + message += "\n"; + + for (uint8_t i = 0; i < request->args(); i++) + { + message += " " + request->argName(i) + ": " + request->arg(i) + "\n"; + } + + request->send(404, "text/plain", message); +} + +void drawGraph(AsyncWebServerRequest *request) +{ + String out; + + out.reserve(3000); + char temp[70]; + + out += "\n"; + + request->send(200, "image/svg+xml", out); +} + + +void setup() +{ + Serial.begin(115200); + + while (!Serial && millis() < 5000); + + delay(200); + + Serial.print(F("\nStart AsyncSimpleServer_ESP32_ENC on ")); + Serial.print(BOARD_NAME); + Serial.print(F(" with ")); + Serial.println(SHIELD_TYPE); + Serial.println(ASYNC_WEBSERVER_ESP32_ENC_VERSION); + + AWS_LOGWARN(F("Default SPI pinout:")); + AWS_LOGWARN1(F("MOSI:"), MOSI_GPIO); + AWS_LOGWARN1(F("MISO:"), MISO_GPIO); + AWS_LOGWARN1(F("SCK:"), SCK_GPIO); + AWS_LOGWARN1(F("CS:"), CS_GPIO); + AWS_LOGWARN1(F("INT:"), INT_GPIO); + AWS_LOGWARN1(F("SPI Clock (MHz):"), SPI_CLOCK_MHZ); + AWS_LOGWARN(F("=========================")); + + /////////////////////////////////// + + // To be called before ETH.begin() + ESP32_ENC_onEvent(); + + // start the ethernet connection and the server: + // Use DHCP dynamic IP and random mac + uint16_t index = millis() % NUMBER_OF_MAC; + + //bool begin(int MISO_GPIO, int MOSI_GPIO, int SCLK_GPIO, int CS_GPIO, int INT_GPIO, int SPI_CLOCK_MHZ, + // int SPI_HOST, uint8_t *ENC28J60_Mac = ENC28J60_Default_Mac); + //ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, SPI_HOST ); + ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, SPI_HOST, mac[index] ); + + // Static IP, leave without this line to get IP via DHCP + //bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = 0, IPAddress dns2 = 0); + ETH.config(myIP, myGW, mySN, myDNS); + + ESP32_ENC_waitForConnect(); + + /////////////////////////////////// + + server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) + { + handleRoot(request); + }); + + server.on("/test.svg", HTTP_GET, [](AsyncWebServerRequest * request) + { + drawGraph(request); + }); + + server.on("/inline", [](AsyncWebServerRequest * request) + { + request->send(200, "text/plain", "This works as well"); + }); + + server.onNotFound(handleNotFound); + + server.begin(); + + Serial.print(F("HTTP EthernetWebServer is @ IP : ")); + Serial.println(ETH.localIP()); +} + +void loop() +{ +} diff --git a/examples/Async_AdvancedWebServer_MemoryIssues_SendArduinoString/Async_AdvancedWebServer_MemoryIssues_SendArduinoString.ino b/examples/Async_AdvancedWebServer_MemoryIssues_SendArduinoString/Async_AdvancedWebServer_MemoryIssues_SendArduinoString.ino new file mode 100644 index 0000000..ac7a6a4 --- /dev/null +++ b/examples/Async_AdvancedWebServer_MemoryIssues_SendArduinoString/Async_AdvancedWebServer_MemoryIssues_SendArduinoString.ino @@ -0,0 +1,334 @@ +/**************************************************************************************************************************** + Async_AdvancedWebServer_MemoryIssues_SendArduinoString.ino + + For ENC28J60 Ethernet in ESP32 (ESP32 + ENC28J60) + + AsyncWebServer_ESP32_ENC is a library for the Ethernet ENC28J60 in ESSP32 to run AsyncWebServer + + Based on and modified from ESPAsyncWebServer (https://github.com/me-no-dev/ESPAsyncWebServer) + Built by Khoi Hoang https://github.com/khoih-prog/AsyncWebServer_ESP32_ENC + Licensed under GPLv3 license + + Copyright (c) 2015, Majenko Technologies + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + Neither the name of Majenko Technologies nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************************************************************/ + +#if !( defined(ESP32) ) + #error This code is designed for (ESP32 + ENC28J60) to run on ESP32 platform! Please check your Tools->Board setting. +#endif + +#includeUptime: %d d %02d:%02d:%02d
\ +\ +\ +", BOARD_NAME, BOARD_NAME, day, hr % 24, min % 60, sec % 60); + + request->send(200, "text/html", temp); +} + +void handleNotFound(AsyncWebServerRequest *request) +{ + String message = "File Not Found\n\n"; + + message += "URI: "; + message += request->url(); + message += "\nMethod: "; + message += (request->method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += request->args(); + message += "\n"; + + for (uint8_t i = 0; i < request->args(); i++) + { + message += " " + request->argName(i) + ": " + request->arg(i) + "\n"; + } + + request->send(404, "text/plain", message); +} + +void PrintHeapData(String hIn) +{ + static uint32_t maxFreeHeap = 0xFFFFFFFF; + static uint32_t totalHeap = ESP.getHeapSize(); + + uint32_t freeHeap = ESP.getFreeHeap(); + + // Print and update only when larger heap + if (maxFreeHeap > freeHeap) + { + maxFreeHeap = freeHeap; + + Serial.print("\nHEAP DATA - "); + Serial.print(hIn); + + Serial.print(" Max heap: "); + Serial.print(totalHeap); + Serial.print(" Free heap: "); + Serial.print(ESP.getFreeHeap()); + Serial.print(" Used heap: "); + Serial.println(totalHeap - freeHeap); + } +} + +void PrintStringSize(String & out) +{ + static uint32_t count = 0; + + // Print only when cStr length too large and corrupting memory or every (20 * 5) s + if ( (out.length() >= STRING_SIZE) || (++count > 20) ) + { + Serial.print("\nOut String Length="); + Serial.println(out.length()); + + count = 0; + } +} + +void drawGraph(AsyncWebServerRequest *request) +{ + String out; + + out.reserve(STRING_SIZE); + char temp[70]; + + out += "\n"; + + PrintHeapData("Pre Send"); + + PrintStringSize(out); + + request->send(200, "image/svg+xml", out); + + PrintHeapData("Post Send"); +} + +void setup() +{ + Serial.begin(115200); + + while (!Serial && millis() < 5000); + + delay(200); + + Serial.print("\nStart Async_AdvancedWebServer_MemoryIssues_SendArduinoString on "); + Serial.print(BOARD_NAME); + Serial.print(" with "); + Serial.println(SHIELD_TYPE); + Serial.println(ASYNC_WEBSERVER_ESP32_ENC_VERSION); + + AWS_LOGWARN(F("Default SPI pinout:")); + AWS_LOGWARN1(F("MOSI:"), MOSI_GPIO); + AWS_LOGWARN1(F("MISO:"), MISO_GPIO); + AWS_LOGWARN1(F("SCK:"), SCK_GPIO); + AWS_LOGWARN1(F("CS:"), CS_GPIO); + AWS_LOGWARN1(F("INT:"), INT_GPIO); + AWS_LOGWARN1(F("SPI Clock (MHz):"), SPI_CLOCK_MHZ); + AWS_LOGWARN(F("=========================")); + + /////////////////////////////////// + + // To be called before ETH.begin() + ESP32_ENC_onEvent(); + + // start the ethernet connection and the server: + // Use DHCP dynamic IP and random mac + uint16_t index = millis() % NUMBER_OF_MAC; + + //bool begin(int MISO_GPIO, int MOSI_GPIO, int SCLK_GPIO, int CS_GPIO, int INT_GPIO, int SPI_CLOCK_MHZ, + // int SPI_HOST, uint8_t *ENC28J60_Mac = ENC28J60_Default_Mac); + //ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, SPI_HOST ); + ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, SPI_HOST, mac[index] ); + + // Static IP, leave without this line to get IP via DHCP + //bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = 0, IPAddress dns2 = 0); + ETH.config(myIP, myGW, mySN, myDNS); + + ESP32_ENC_waitForConnect(); + + /////////////////////////////////// + + + /////////////////////////////////// + + server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) + { + handleRoot(request); + }); + + server.on("/test.svg", HTTP_GET, [](AsyncWebServerRequest * request) + { + drawGraph(request); + }); + + server.on("/inline", [](AsyncWebServerRequest * request) + { + request->send(200, "text/plain", "This works as well"); + }); + + server.onNotFound(handleNotFound); + + server.begin(); + + Serial.print(F("HTTP EthernetWebServer is @ IP : ")); + Serial.println(ETH.localIP()); + + PrintHeapData("Pre Create Arduino String"); +} + +void heartBeatPrint() +{ + static int num = 1; + + Serial.print(F(".")); + + if (num == 80) + { + Serial.println(); + num = 1; + } + else if (num++ % 10 == 0) + { + Serial.print(F(" ")); + } +} + +void check_status() +{ + static unsigned long checkstatus_timeout = 0; + +#define STATUS_CHECK_INTERVAL 10000L + + // Send status report every STATUS_REPORT_INTERVAL (60) seconds: we don't need to send updates frequently if there is no status change. + if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0)) + { + heartBeatPrint(); + checkstatus_timeout = millis() + STATUS_CHECK_INTERVAL; + } +} + +void loop() +{ + check_status(); +} diff --git a/examples/Async_AdvancedWebServer_MemoryIssues_Send_CString/Async_AdvancedWebServer_MemoryIssues_Send_CString.ino b/examples/Async_AdvancedWebServer_MemoryIssues_Send_CString/Async_AdvancedWebServer_MemoryIssues_Send_CString.ino new file mode 100644 index 0000000..a950052 --- /dev/null +++ b/examples/Async_AdvancedWebServer_MemoryIssues_Send_CString/Async_AdvancedWebServer_MemoryIssues_Send_CString.ino @@ -0,0 +1,344 @@ +/**************************************************************************************************************************** + Async_AdvancedWebServer_MemoryIssues_Send_CString.ino + + For ENC28J60 Ethernet in ESP32 (ESP32 + ENC28J60) + + AsyncWebServer_ESP32_ENC is a library for the Ethernet ENC28J60 in ESSP32 to run AsyncWebServer + + Based on and modified from ESPAsyncWebServer (https://github.com/me-no-dev/ESPAsyncWebServer) + Built by Khoi Hoang https://github.com/khoih-prog/AsyncWebServer_ESP32_ENC + Licensed under GPLv3 license + + Copyright (c) 2015, Majenko Technologies + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + Neither the name of Majenko Technologies nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************************************************************/ + +#if !( defined(ESP32) ) + #error This code is designed for (ESP32 + ENC28J60) to run on ESP32 platform! Please check your Tools->Board setting. +#endif + +#includeUptime: %d d %02d:%02d:%02d
\ +\ +\ +", BOARD_NAME, BOARD_NAME, day, hr % 24, min % 60, sec % 60); + + request->send(200, "text/html", temp); +} + +void handleNotFound(AsyncWebServerRequest *request) +{ + String message = "File Not Found\n\n"; + + message += "URI: "; + message += request->url(); + message += "\nMethod: "; + message += (request->method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += request->args(); + message += "\n"; + + for (uint8_t i = 0; i < request->args(); i++) + { + message += " " + request->argName(i) + ": " + request->arg(i) + "\n"; + } + + request->send(404, "text/plain", message); +} + +void PrintHeapData(String hIn) +{ + static uint32_t maxFreeHeap = 0xFFFFFFFF; + static uint32_t totalHeap = ESP.getHeapSize(); + + uint32_t freeHeap = ESP.getFreeHeap(); + + // Print and update only when larger heap + if (maxFreeHeap > freeHeap) + { + maxFreeHeap = freeHeap; + + Serial.print("\nHEAP DATA - "); + Serial.print(hIn); + + Serial.print(" Max heap: "); + Serial.print(totalHeap); + Serial.print(" Free heap: "); + Serial.print(ESP.getFreeHeap()); + Serial.print(" Used heap: "); + Serial.println(totalHeap - freeHeap); + } +} + +void PrintStringSize(const char* cStr) +{ + Serial.print("\nOut String Length="); + Serial.println(strlen(cStr)); +} + +void drawGraph(AsyncWebServerRequest *request) +{ + char temp[80]; + + cStr[0] = '\0'; + + strcat(cStr, "\n"); + + PrintHeapData("Pre Send"); + + // Print only when cStr length too large and corrupting memory + if ( (strlen(cStr) >= CSTRING_SIZE)) + { + PrintStringSize(cStr); + } + + request->send(200, "image/svg+xml", cStr, false); + + PrintHeapData("Post Send"); +} + +void setup() +{ + Serial.begin(115200); + + while (!Serial && millis() < 5000); + + delay(200); + + Serial.print("\nStart Async_AdvancedWebServer_MemoryIssues_Send_CString on "); + Serial.print(BOARD_NAME); + Serial.print(" with "); + Serial.println(SHIELD_TYPE); + Serial.println(ASYNC_WEBSERVER_ESP32_ENC_VERSION); + + AWS_LOGWARN(F("Default SPI pinout:")); + AWS_LOGWARN1(F("MOSI:"), MOSI_GPIO); + AWS_LOGWARN1(F("MISO:"), MISO_GPIO); + AWS_LOGWARN1(F("SCK:"), SCK_GPIO); + AWS_LOGWARN1(F("CS:"), CS_GPIO); + AWS_LOGWARN1(F("INT:"), INT_GPIO); + AWS_LOGWARN1(F("SPI Clock (MHz):"), SPI_CLOCK_MHZ); + AWS_LOGWARN(F("=========================")); + + /////////////////////////////////// + + cStr = (char *) malloc(CSTRING_SIZE); // make a little larger than required + + if (cStr == NULL) + { + Serial.println("Unable top Allocate RAM"); + + for (;;); + } + + /////////////////////////////////// + + // To be called before ETH.begin() + ESP32_ENC_onEvent(); + + // start the ethernet connection and the server: + // Use DHCP dynamic IP and random mac + uint16_t index = millis() % NUMBER_OF_MAC; + + //bool begin(int MISO_GPIO, int MOSI_GPIO, int SCLK_GPIO, int CS_GPIO, int INT_GPIO, int SPI_CLOCK_MHZ, + // int SPI_HOST, uint8_t *ENC28J60_Mac = ENC28J60_Default_Mac); + //ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, SPI_HOST ); + ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, SPI_HOST, mac[index] ); + + // Static IP, leave without this line to get IP via DHCP + //bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = 0, IPAddress dns2 = 0); + ETH.config(myIP, myGW, mySN, myDNS); + + ESP32_ENC_waitForConnect(); + + /////////////////////////////////// + + + /////////////////////////////////// + + server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) + { + handleRoot(request); + }); + + server.on("/test.svg", HTTP_GET, [](AsyncWebServerRequest * request) + { + drawGraph(request); + }); + + server.on("/inline", [](AsyncWebServerRequest * request) + { + request->send(200, "text/plain", "This works as well"); + }); + + server.onNotFound(handleNotFound); + + server.begin(); + + Serial.print(F("HTTP EthernetWebServer is @ IP : ")); + Serial.println(ETH.localIP()); + + PrintHeapData("Pre Create Arduino String"); +} + +void heartBeatPrint() +{ + static int num = 1; + + Serial.print(F(".")); + + if (num == 80) + { + //Serial.println(); + PrintStringSize(cStr); + num = 1; + } + else if (num++ % 10 == 0) + { + Serial.print(F(" ")); + } +} + +void check_status() +{ + static unsigned long checkstatus_timeout = 0; + +#define STATUS_CHECK_INTERVAL 10000L + + // Send status report every STATUS_REPORT_INTERVAL (60) seconds: we don't need to send updates frequently if there is no status change. + if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0)) + { + heartBeatPrint(); + checkstatus_timeout = millis() + STATUS_CHECK_INTERVAL; + } +} + +void loop() +{ + check_status(); +} diff --git a/examples/Async_AdvancedWebServer_SendChunked/Async_AdvancedWebServer_SendChunked.ino b/examples/Async_AdvancedWebServer_SendChunked/Async_AdvancedWebServer_SendChunked.ino new file mode 100644 index 0000000..c35e05f --- /dev/null +++ b/examples/Async_AdvancedWebServer_SendChunked/Async_AdvancedWebServer_SendChunked.ino @@ -0,0 +1,301 @@ +/**************************************************************************************************************************** + Async_AdvancedWebServer_SendChunked.ino + + For ENC28J60 Ethernet in ESP32 (ESP32 + ENC28J60) + + AsyncWebServer_ESP32_ENC is a library for the Ethernet ENC28J60 in ESSP32 to run AsyncWebServer + + Based on and modified from ESPAsyncWebServer (https://github.com/me-no-dev/ESPAsyncWebServer) + Built by Khoi Hoang https://github.com/khoih-prog/AsyncWebServer_ESP32_ENC + Licensed under GPLv3 license + + Copyright (c) 2015, Majenko Technologies + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + Neither the name of Majenko Technologies nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************************************************************/ + +#if !( defined(ESP32) ) + #error This code is designed for (ESP32 + ENC28J60) to run on ESP32 platform! Please check your Tools->Board setting. +#endif + +#includeUptime: %d d %02d:%02d:%02d
\ +\ +\ +", BOARD_NAME, BOARD_NAME, day, hr % 24, min % 60, sec % 60); + + request->send(200, "text/html", temp); +} + +void handleNotFound(AsyncWebServerRequest *request) +{ + String message = "File Not Found\n\n"; + + message += "URI: "; + message += request->url(); + message += "\nMethod: "; + message += (request->method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += request->args(); + message += "\n"; + + for (uint8_t i = 0; i < request->args(); i++) + { + message += " " + request->argName(i) + ": " + request->arg(i) + "\n"; + } + + request->send(404, "text/plain", message); +} + +String out; + +void drawGraph(AsyncWebServerRequest *request) +{ + out.reserve(STRING_SIZE); + char temp[70]; + + out = String(); + + out += "\n"; + + AWS_LOGDEBUG1("Total length to send in chunks =", out.length()); + + AsyncWebServerResponse *response = request->beginChunkedResponse("image/svg+xml", [](uint8_t *buffer, size_t maxLen, + size_t filledLength) -> size_t + { + size_t len = min(maxLen, out.length() - filledLength); + memcpy(buffer, out.c_str() + filledLength, len); + + AWS_LOGDEBUG1("Bytes sent in chunk =", len); + + return len; + }); + + request->send(response); +} + + +void setup() +{ + Serial.begin(115200); + + while (!Serial && millis() < 5000); + + delay(200); + + Serial.print("\nStart Async_AdvancedWebServer_SendChunked on "); + Serial.print(BOARD_NAME); + Serial.print(" with "); + Serial.println(SHIELD_TYPE); + Serial.println(ASYNC_WEBSERVER_ESP32_ENC_VERSION); + + AWS_LOGWARN(F("Default SPI pinout:")); + AWS_LOGWARN1(F("MOSI:"), MOSI_GPIO); + AWS_LOGWARN1(F("MISO:"), MISO_GPIO); + AWS_LOGWARN1(F("SCK:"), SCK_GPIO); + AWS_LOGWARN1(F("CS:"), CS_GPIO); + AWS_LOGWARN1(F("INT:"), INT_GPIO); + AWS_LOGWARN1(F("SPI Clock (MHz):"), SPI_CLOCK_MHZ); + AWS_LOGWARN(F("=========================")); + + /////////////////////////////////// + + // To be called before ETH.begin() + ESP32_ENC_onEvent(); + + // start the ethernet connection and the server: + // Use DHCP dynamic IP and random mac + uint16_t index = millis() % NUMBER_OF_MAC; + + //bool begin(int MISO_GPIO, int MOSI_GPIO, int SCLK_GPIO, int CS_GPIO, int INT_GPIO, int SPI_CLOCK_MHZ, + // int SPI_HOST, uint8_t *ENC28J60_Mac = ENC28J60_Default_Mac); + //ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, SPI_HOST ); + ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, SPI_HOST, mac[index] ); + + // Static IP, leave without this line to get IP via DHCP + //bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = 0, IPAddress dns2 = 0); + //ETH.config(myIP, myGW, mySN, myDNS); + + ESP32_ENC_waitForConnect(); + + /////////////////////////////////// + + server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) + { + handleRoot(request); + }); + + server.on("/test.svg", HTTP_GET, [](AsyncWebServerRequest * request) + { + drawGraph(request); + }); + + server.on("/inline", [](AsyncWebServerRequest * request) + { + request->send(200, "text/plain", "This works as well"); + }); + + server.onNotFound(handleNotFound); + + server.begin(); + + Serial.print(F("AsyncWebServer is @ IP : ")); + Serial.println(ETH.localIP()); +} + +void heartBeatPrint() +{ + static int num = 1; + + Serial.print(F(".")); + + if (num == 80) + { + Serial.println(); + num = 1; + } + else if (num++ % 10 == 0) + { + Serial.print(F(" ")); + } +} + +void check_status() +{ + static unsigned long checkstatus_timeout = 0; + +#define STATUS_CHECK_INTERVAL 10000L + + // Send status report every STATUS_REPORT_INTERVAL (60) seconds: we don't need to send updates frequently if there is no status change. + if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0)) + { + heartBeatPrint(); + checkstatus_timeout = millis() + STATUS_CHECK_INTERVAL; + } +} + +void loop() +{ + check_status(); +} diff --git a/examples/Async_HelloServer/Async_HelloServer.ino b/examples/Async_HelloServer/Async_HelloServer.ino new file mode 100644 index 0000000..2ba8cc4 --- /dev/null +++ b/examples/Async_HelloServer/Async_HelloServer.ino @@ -0,0 +1,167 @@ +/**************************************************************************************************************************** + Async_HelloServer.h + + For ENC28J60 Ethernet in ESP32 (ESP32 + ENC28J60) + + AsyncWebServer_ESP32_ENC is a library for the Ethernet ENC28J60 in ESSP32 to run AsyncWebServer + + Based on and modified from ESPAsyncWebServer (https://github.com/me-no-dev/ESPAsyncWebServer) + Built by Khoi Hoang https://github.com/khoih-prog/AsyncWebServer_ESP32_ENC + Licensed under GPLv3 license + *****************************************************************************************************************************/ + +#if !( defined(ESP32) ) + #error This code is designed for (ESP32 + ENC28J60) to run on ESP32 platform! Please check your Tools->Board setting. +#endif + +#includee||Gk9)Bne^)=l!>a)S>s(({
zM8V7JJyZYOF1E`knM~UX2p53+gz1xb%5<3Gwp4t6SqdB7!oDx9s!AR;^1MI)AC@gW
zI~$Oc0ZnN2MGw$=S@8Z74Y6be0V$=a2{BmctQvR>Yu&!xvu1x3N`E1UVgN%Bz_oU>
z0a+82JAcxNVqc%nXf$w;#U%hJE_;Gd${wi6hCj+u4)*?aP4z3bOGDx?SDShUy9DeW#gq
z4*`=N&9GG|pex|;LVw-s?HW_g3%lZL)PMiXCM;$)R)m=X%BHcxiBt2uxH=a17sS=x
zeuoYRG7l>=pRj^(DR
G&kP+X9l`CVW$s(zj9
ztlgw>vxZ>skzHaZ9x%(lt=v4koj0ocW@l@~+t8C}M(%jfr5xFlq2l3@qHVN3aVi*p
z^zCJ!_v}2E&DYSK$;;GsA62n`erCWkn*9qpqNZ3Y9fq`G81vXDL%0RcyD04E&Ip{U
zH6vK+<6-eQoG+JpY`T*?BSYAxrXKIDQIngs4c*p%gGR2}Ew&y{&K!yiY~3~C%WNvT
zWA~JtYnq&PbDTB}-7Rf75dj2KYi>Plyp