|  | 
|  | 1 | +/**************************************************************************************************************************** | 
|  | 2 | +  Async_AdvancedWebServer_MemoryIssues_SendArduinoString.ino -  Dead simple AsyncWebServer for WT32_ETH01 | 
|  | 3 | +   | 
|  | 4 | +  For LAN8720 Ethernet in WT32_ETH01 (ESP32 + LAN8720) | 
|  | 5 | +
 | 
|  | 6 | +  AsyncWebServer_WT32_ETH01 is a library for the Ethernet LAN8720 in WT32_ETH01 to run AsyncWebServer | 
|  | 7 | +
 | 
|  | 8 | +  Based on and modified from ESPAsyncWebServer (https://github.com/me-no-dev/ESPAsyncWebServer) | 
|  | 9 | +  Built by Khoi Hoang https://github.com/khoih-prog/AsyncWebServer_WT32_ETH01 | 
|  | 10 | +  Licensed under GPLv3 license  | 
|  | 11 | +
 | 
|  | 12 | +  Copyright (c) 2015, Majenko Technologies | 
|  | 13 | +  All rights reserved. | 
|  | 14 | +
 | 
|  | 15 | +  Redistribution and use in source and binary forms, with or without modification, | 
|  | 16 | +  are permitted provided that the following conditions are met: | 
|  | 17 | +
 | 
|  | 18 | +  Redistributions of source code must retain the above copyright notice, this | 
|  | 19 | +  list of conditions and the following disclaimer. | 
|  | 20 | +
 | 
|  | 21 | +  Redistributions in binary form must reproduce the above copyright notice, this | 
|  | 22 | +  list of conditions and the following disclaimer in the documentation and/or | 
|  | 23 | +  other materials provided with the distribution. | 
|  | 24 | +
 | 
|  | 25 | +  Neither the name of Majenko Technologies nor the names of its | 
|  | 26 | +  contributors may be used to endorse or promote products derived from | 
|  | 27 | +  this software without specific prior written permission. | 
|  | 28 | +
 | 
|  | 29 | +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | 
|  | 30 | +  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 
|  | 31 | +  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
|  | 32 | +  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | 
|  | 33 | +  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 
|  | 34 | +  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 
|  | 35 | +  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | 
|  | 36 | +  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|  | 37 | +  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
|  | 38 | +  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  | 39 | + *****************************************************************************************************************************/ | 
|  | 40 | + | 
|  | 41 | +#if !( defined(ESP32) ) | 
|  | 42 | +  #error This code is designed for WT32_ETH01 to run on ESP32 platform! Please check your Tools->Board setting. | 
|  | 43 | +#endif | 
|  | 44 | + | 
|  | 45 | +#include <Arduino.h> | 
|  | 46 | + | 
|  | 47 | +#define _ASYNC_WEBSERVER_LOGLEVEL_       2 | 
|  | 48 | + | 
|  | 49 | +// Select the IP address according to your local network | 
|  | 50 | +IPAddress myIP(192, 168, 2, 232); | 
|  | 51 | +IPAddress myGW(192, 168, 2, 1); | 
|  | 52 | +IPAddress mySN(255, 255, 255, 0); | 
|  | 53 | + | 
|  | 54 | +// Google DNS Server IP | 
|  | 55 | +IPAddress myDNS(8, 8, 8, 8); | 
|  | 56 | + | 
|  | 57 | +#include <AsyncTCP.h> | 
|  | 58 | + | 
|  | 59 | +#include <AsyncWebServer_WT32_ETH01.h> | 
|  | 60 | + | 
|  | 61 | +// In bytes | 
|  | 62 | +#define STRING_SIZE                    40000 | 
|  | 63 | + | 
|  | 64 | +AsyncWebServer    server(80); | 
|  | 65 | + | 
|  | 66 | +int reqCount = 0;                // number of requests received | 
|  | 67 | + | 
|  | 68 | +#define BUFFER_SIZE         512 | 
|  | 69 | +char temp[BUFFER_SIZE]; | 
|  | 70 | + | 
|  | 71 | +void handleRoot(AsyncWebServerRequest *request) | 
|  | 72 | +{ | 
|  | 73 | +  int sec = millis() / 1000; | 
|  | 74 | +  int min = sec / 60; | 
|  | 75 | +  int hr = min / 60; | 
|  | 76 | +  int day = hr / 24; | 
|  | 77 | + | 
|  | 78 | +  snprintf(temp, BUFFER_SIZE - 1, | 
|  | 79 | +           "<html>\ | 
|  | 80 | +<head>\ | 
|  | 81 | +<meta http-equiv='refresh' content='60'/>\ | 
|  | 82 | +<title>AsyncWebServer-%s</title>\ | 
|  | 83 | +<style>\ | 
|  | 84 | +body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\ | 
|  | 85 | +</style>\ | 
|  | 86 | +</head>\ | 
|  | 87 | +<body>\ | 
|  | 88 | +<h2>AsyncWebServer_WT32_ETH01!</h2>\ | 
|  | 89 | +<h3>running on %s</h3>\ | 
|  | 90 | +<p>Uptime: %d d %02d:%02d:%02d</p>\ | 
|  | 91 | +<img src=\"/test.svg\" />\ | 
|  | 92 | +</body>\ | 
|  | 93 | +</html>", BOARD_NAME, BOARD_NAME, day, hr % 24, min % 60, sec % 60); | 
|  | 94 | + | 
|  | 95 | +  request->send(200, "text/html", temp); | 
|  | 96 | +} | 
|  | 97 | + | 
|  | 98 | +void handleNotFound(AsyncWebServerRequest *request) | 
|  | 99 | +{ | 
|  | 100 | +  String message = "File Not Found\n\n"; | 
|  | 101 | + | 
|  | 102 | +  message += "URI: "; | 
|  | 103 | +  message += request->url(); | 
|  | 104 | +  message += "\nMethod: "; | 
|  | 105 | +  message += (request->method() == HTTP_GET) ? "GET" : "POST"; | 
|  | 106 | +  message += "\nArguments: "; | 
|  | 107 | +  message += request->args(); | 
|  | 108 | +  message += "\n"; | 
|  | 109 | + | 
|  | 110 | +  for (uint8_t i = 0; i < request->args(); i++) | 
|  | 111 | +  { | 
|  | 112 | +    message += " " + request->argName(i) + ": " + request->arg(i) + "\n"; | 
|  | 113 | +  } | 
|  | 114 | + | 
|  | 115 | +  request->send(404, "text/plain", message); | 
|  | 116 | +} | 
|  | 117 | + | 
|  | 118 | +void PrintHeapData(String hIn) | 
|  | 119 | +{ | 
|  | 120 | +  static uint32_t maxFreeHeap = 0xFFFFFFFF; | 
|  | 121 | +  static uint32_t totalHeap = ESP.getHeapSize(); | 
|  | 122 | + | 
|  | 123 | +  uint32_t freeHeap  = ESP.getFreeHeap(); | 
|  | 124 | +   | 
|  | 125 | +  // Print and update only when larger heap | 
|  | 126 | +  if (maxFreeHeap > freeHeap) | 
|  | 127 | +  { | 
|  | 128 | +    maxFreeHeap = freeHeap; | 
|  | 129 | +   | 
|  | 130 | +    Serial.print("\nHEAP DATA - "); | 
|  | 131 | +    Serial.print(hIn); | 
|  | 132 | +     | 
|  | 133 | +    Serial.print("  Max heap: "); | 
|  | 134 | +    Serial.print(totalHeap); | 
|  | 135 | +    Serial.print("  Free heap: "); | 
|  | 136 | +    Serial.print(ESP.getFreeHeap()); | 
|  | 137 | +    Serial.print("  Used heap: "); | 
|  | 138 | +    Serial.println(totalHeap - freeHeap); | 
|  | 139 | +  } | 
|  | 140 | +} | 
|  | 141 | + | 
|  | 142 | +void PrintStringSize(String & out) | 
|  | 143 | +{  | 
|  | 144 | +  static uint32_t count = 0; | 
|  | 145 | + | 
|  | 146 | +  // Print only when cStr length too large and corrupting memory or every (20 * 5) s | 
|  | 147 | +  if ( (out.length() >= STRING_SIZE) || (++count > 20) ) | 
|  | 148 | +  { | 
|  | 149 | +    Serial.print("\nOut String Length="); | 
|  | 150 | +    Serial.println(out.length()); | 
|  | 151 | + | 
|  | 152 | +    count = 0; | 
|  | 153 | +  } | 
|  | 154 | +} | 
|  | 155 | + | 
|  | 156 | +void drawGraph(AsyncWebServerRequest *request) | 
|  | 157 | +{ | 
|  | 158 | +  String out; | 
|  | 159 | + | 
|  | 160 | +  out.reserve(STRING_SIZE); | 
|  | 161 | +  char temp[70]; | 
|  | 162 | + | 
|  | 163 | +  out += "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"1810\" height=\"150\">\n"; | 
|  | 164 | +  out += "<rect width=\"1810\" height=\"150\" fill=\"rgb(250, 230, 210)\" stroke-width=\"2\" stroke=\"rgb(0, 0, 0)\" />\n"; | 
|  | 165 | +  out += "<g stroke=\"blue\">\n"; | 
|  | 166 | +  int y = rand() % 130; | 
|  | 167 | + | 
|  | 168 | +  for (int x = 10; x < 5000; x += 10) | 
|  | 169 | +  { | 
|  | 170 | +    int y2 = rand() % 130; | 
|  | 171 | +    sprintf(temp, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke-width=\"2\" />\n", x, 140 - y, x + 10, 140 - y2); | 
|  | 172 | +    out += temp; | 
|  | 173 | +    y = y2; | 
|  | 174 | +  } | 
|  | 175 | +   | 
|  | 176 | +  out += "</g>\n</svg>\n"; | 
|  | 177 | + | 
|  | 178 | +  PrintHeapData("Pre Send"); | 
|  | 179 | + | 
|  | 180 | +  PrintStringSize(out); | 
|  | 181 | + | 
|  | 182 | +  request->send(200, "image/svg+xml", out); | 
|  | 183 | + | 
|  | 184 | +  PrintHeapData("Post Send"); | 
|  | 185 | +} | 
|  | 186 | + | 
|  | 187 | +void setup() | 
|  | 188 | +{ | 
|  | 189 | +  Serial.begin(115200); | 
|  | 190 | +  while (!Serial && millis() < 5000); | 
|  | 191 | + | 
|  | 192 | +  delay(200); | 
|  | 193 | + | 
|  | 194 | +  Serial.print("\nStart Async_AdvancedWebServer_MemoryIssues_SendArduinoString on "); Serial.print(BOARD_NAME); | 
|  | 195 | +  Serial.print(" with "); Serial.println(SHIELD_TYPE); | 
|  | 196 | +  Serial.println(ASYNC_WEBSERVER_WT32_ETH01_VERSION); | 
|  | 197 | + | 
|  | 198 | +  // To be called before ETH.begin() | 
|  | 199 | +  WT32_ETH01_onEvent(); | 
|  | 200 | + | 
|  | 201 | +  //bool begin(uint8_t phy_addr=ETH_PHY_ADDR, int power=ETH_PHY_POWER, int mdc=ETH_PHY_MDC, int mdio=ETH_PHY_MDIO,  | 
|  | 202 | +  //           eth_phy_type_t type=ETH_PHY_TYPE, eth_clock_mode_t clk_mode=ETH_CLK_MODE); | 
|  | 203 | +  //ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLK_MODE); | 
|  | 204 | +  ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER); | 
|  | 205 | + | 
|  | 206 | +  // Static IP, leave without this line to get IP via DHCP | 
|  | 207 | +  //bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = 0, IPAddress dns2 = 0); | 
|  | 208 | +  ETH.config(myIP, myGW, mySN, myDNS); | 
|  | 209 | + | 
|  | 210 | +  WT32_ETH01_waitForConnect(); | 
|  | 211 | + | 
|  | 212 | +  /////////////////////////////////// | 
|  | 213 | +  | 
|  | 214 | +  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) | 
|  | 215 | +  { | 
|  | 216 | +    handleRoot(request); | 
|  | 217 | +  }); | 
|  | 218 | + | 
|  | 219 | +  server.on("/test.svg", HTTP_GET, [](AsyncWebServerRequest * request) | 
|  | 220 | +  { | 
|  | 221 | +    drawGraph(request); | 
|  | 222 | +  }); | 
|  | 223 | + | 
|  | 224 | +  server.on("/inline", [](AsyncWebServerRequest * request) | 
|  | 225 | +  { | 
|  | 226 | +    request->send(200, "text/plain", "This works as well"); | 
|  | 227 | +  }); | 
|  | 228 | + | 
|  | 229 | +  server.onNotFound(handleNotFound); | 
|  | 230 | + | 
|  | 231 | +  server.begin(); | 
|  | 232 | + | 
|  | 233 | +  Serial.print(F("HTTP EthernetWebServer is @ IP : ")); | 
|  | 234 | +  Serial.println(ETH.localIP()); | 
|  | 235 | + | 
|  | 236 | +  PrintHeapData("Pre Create Arduino String"); | 
|  | 237 | +} | 
|  | 238 | + | 
|  | 239 | +void heartBeatPrint() | 
|  | 240 | +{ | 
|  | 241 | +  static int num = 1; | 
|  | 242 | + | 
|  | 243 | +  Serial.print(F(".")); | 
|  | 244 | + | 
|  | 245 | +  if (num == 80) | 
|  | 246 | +  { | 
|  | 247 | +    Serial.println(); | 
|  | 248 | +    num = 1; | 
|  | 249 | +  } | 
|  | 250 | +  else if (num++ % 10 == 0) | 
|  | 251 | +  { | 
|  | 252 | +    Serial.print(F(" ")); | 
|  | 253 | +  } | 
|  | 254 | +} | 
|  | 255 | + | 
|  | 256 | +void check_status() | 
|  | 257 | +{ | 
|  | 258 | +  static unsigned long checkstatus_timeout = 0; | 
|  | 259 | + | 
|  | 260 | +#define STATUS_CHECK_INTERVAL     10000L | 
|  | 261 | + | 
|  | 262 | +  // Send status report every STATUS_REPORT_INTERVAL (60) seconds: we don't need to send updates frequently if there is no status change. | 
|  | 263 | +  if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0)) | 
|  | 264 | +  { | 
|  | 265 | +    heartBeatPrint(); | 
|  | 266 | +    checkstatus_timeout = millis() + STATUS_CHECK_INTERVAL; | 
|  | 267 | +  } | 
|  | 268 | +} | 
|  | 269 | + | 
|  | 270 | +void loop() | 
|  | 271 | +{ | 
|  | 272 | +  check_status(); | 
|  | 273 | +} | 
0 commit comments