diff --git a/examples/Ethernet/Async_AdvancedWebServer_MemoryIssues_Send C String (NO SDRAM)/Async_AdvancedWebServer_MemoryIssues_Send C String (NO SDRAM).ino b/examples/Ethernet/Async_AdvancedWebServer_MemoryIssues_Send C String (NO SDRAM)/Async_AdvancedWebServer_MemoryIssues_Send C String (NO SDRAM).ino new file mode 100644 index 0000000..a5eb84d --- /dev/null +++ b/examples/Ethernet/Async_AdvancedWebServer_MemoryIssues_Send C String (NO SDRAM)/Async_AdvancedWebServer_MemoryIssues_Send C String (NO SDRAM).ino @@ -0,0 +1,309 @@ +/**************************************************************************************************************************** + Async_AdvancedWebServer_MemoryIssues_Send_CString.ino - Dead simple AsyncWebServer for STM32 LAN8720 or built-in LAN8742A Ethernet + For Portenta_H7 (STM32H7) with Vision-Shield Ethernet + Portenta_H7_AsyncWebServer is a library for the Portenta_H7 with with Vision-Shield Ethernet + Based on and modified from ESPAsyncWebServer (https://github.com/me-no-dev/ESPAsyncWebServer) + Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer + 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(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) ) + #error For Portenta_H7 only +#endif + +#define _PORTENTA_H7_ATCP_LOGLEVEL_ 1 +#define _PORTENTA_H7_AWS_LOGLEVEL_ 1 + +#define USE_ETHERNET_PORTENTA_H7 true + +#include +#include +#warning Using Portenta_Ethernet lib for Portenta_H7. + +#include + +// Enter a MAC address and IP address for your controller below. +#define NUMBER_OF_MAC 20 + +byte mac[][NUMBER_OF_MAC] = +{ + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x01 }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x02 }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x03 }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x04 }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x05 }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x06 }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x07 }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x08 }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x09 }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0A }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0B }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0C }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0D }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0E }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0F }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x10 }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x11 }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x12 }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x13 }, + { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x14 }, +}; +// Select the IP address according to your local network +IPAddress ip(192, 168, 2, 232); + +AsyncWebServer server(80); + +int reqCount = 0; // number of requests received + +#define LED_OFF HIGH +#define LED_ON LOW + + +#define BUFFER_SIZE 768 // a little larger in case required for header shift (destructive send) +char temp[BUFFER_SIZE]; + +void handleRoot(AsyncWebServerRequest *request) +{ + digitalWrite(LED_BUILTIN, LED_ON); + + int sec = millis() / 1000; + int min = sec / 60; + int hr = min / 60; + int day = hr / 24; + + snprintf(temp, BUFFER_SIZE - 1, + "\ +\ +\ +AsyncWebServer-%s\ +\ +\ +\ +

AsyncWebServer_Portenta_H7!

\ +

running on %s

\ +

Uptime: %d d %02d:%02d:%02d

\ +\ +\ +", BOARD_NAME, BOARD_NAME, day, hr % 24, min % 60, sec % 60); + + request->send(200, "text/html", temp, false); + + digitalWrite(LED_BUILTIN, LED_OFF); +} + +void handleNotFound(AsyncWebServerRequest *request) +{ + digitalWrite(LED_BUILTIN, LED_ON); + 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); + digitalWrite(LED_BUILTIN, LED_OFF); +} + +void PrintHeapData(String hIn){ + mbed_stats_heap_t heap_stats; + + Serial.print("HEAP DATA - "); + Serial.print(hIn); + + mbed_stats_heap_get(&heap_stats); + Serial.print(" Cur heap: "); + Serial.print(heap_stats.current_size); + Serial.print(" Res Size: "); + Serial.print(heap_stats.reserved_size); + Serial.print(" Max heap: "); + Serial.println(heap_stats.max_size); +} + +char cStr[41000]; + +void drawGraph(AsyncWebServerRequest *request) +{ + char temp[80]; + + //char * cStr = (char *)malloc(41000); // IF NO SDRAM available - use main RAM + // make a little larger than required - can malloc, or create an external (cStr[41000]) variable that can be reused + + if (cStr == NULL) { + Serial.println("Unable top Allocate RAM"); + for(;;); + } + + cStr[0] = '\0'; + + strcat(cStr, "\n"); + strcat(cStr, "\n"); + strcat(cStr, "\n"); + int y = rand() % 130; + + for (int x = 10; x < 5000; x += 10) + { + int y2 = rand() % 130; + sprintf(temp, "\n", x, 140 - y, x + 10, 140 - y2); + strcat(cStr, temp); + y = y2; + } + + strcat(cStr, "\n\n"); + + PrintHeapData("Pre Send"); + + Serial.print("Out String Length="); + Serial.println(strlen(cStr)); + + request->send(200, "image/svg+xml", cStr, false); + + //free(cStr); + + PrintHeapData("Post Send"); +} + + +void setup() +{ + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, LED_OFF); + + 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(PORTENTA_H7_ASYNC_TCP_VERSION); + Serial.println(PORTENTA_H7_ASYNC_WEBSERVER_VERSION); + + /////////////////////////////////// + + // start the ethernet connection and the server + // Use random mac + uint16_t index = millis() % NUMBER_OF_MAC; + + // Use Static IP + //Ethernet.begin(mac[index], ip); + // Use DHCP dynamic IP and random mac + Ethernet.begin(mac[index]); + + if (Ethernet.hardwareStatus() == EthernetNoHardware) + { + Serial.println("No Ethernet found. Stay here forever"); + + while (true) + { + delay(1); // do nothing, no point running without Ethernet hardware + } + } + + if (Ethernet.linkStatus() == LinkOFF) + { + Serial.println("Not connected Ethernet cable"); + } + + Serial.print(F("Using mac index = ")); + Serial.println(index); + + Serial.print(F("Connected! IP address: ")); + Serial.println(Ethernet.localIP()); + + /////////////////////////////////// + + 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(Ethernet.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(); +}