Skip to content
This repository was archived by the owner on Jan 29, 2023. It is now read-only.

Commit 9087dbc

Browse files
authored
v1.6.0 to save heap when sending large data
#### Releases v1.6.0 1. 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](khoih-prog/Portenta_H7_AsyncWebServer#8) 2. Add multiple examples to demo the new feature
1 parent e843031 commit 9087dbc

30 files changed

+3181
-688
lines changed

changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
## Table of contents
1212

1313
* [Changelog](#changelog)
14+
* [Releases v1.6.0](#releases-v160)
1415
* [Releases v1.5.0](#releases-v150)
1516
* [Releases v1.4.1](#releases-v141)
1617
* [Releases v1.4.0](#releases-v140)
@@ -25,6 +26,11 @@
2526

2627
## Changelog
2728

29+
#### Releases v1.6.0
30+
31+
1. 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)
32+
2. Add multiple examples to demo the new feature
33+
2834
#### Releases v1.5.0
2935

3036
1. Fix AsyncWebSocket bug
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
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

Comments
 (0)