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

Commit 1ef95e5

Browse files
authored
Merge pull request #8 from salasidis/main
Added example files
2 parents 8297aa2 + 4d1045d commit 1ef95e5

File tree

7 files changed

+980
-178
lines changed

7 files changed

+980
-178
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,21 @@
1212
---
1313
---
1414

15+
16+
*****
17+
Added a destructive C string interface to send
18+
19+
if called with
20+
request->send(200, textPlainStr, ArduinoStr); // no difference
21+
request->send(200, textPlainStr, cStr); // no differfence
22+
request->send(200, textPlainStr, cStr, false); // this will have to be a cString with enough space to fit the header, it will be memmoved as required, header added, and sent, without creating any large arduino Strings that consume heap
23+
24+
in my application max heap size went from 375k to 66k (which is the lowest possible wit the variables and otehr data I am using)
25+
26+
Seems to work, let me know what you think
27+
28+
29+
1530
## Table of contents
1631

1732
* [Table of contents](#table-of-contents)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
/****************************************************************************************************************************
2+
Async_AdvancedWebServer_MemoryIssues_Send_CString.ino - Dead simple AsyncWebServer for STM32 LAN8720 or built-in LAN8742A Ethernet
3+
4+
For Portenta_H7 (STM32H7) with Vision-Shield Ethernet
5+
6+
Portenta_H7_AsyncWebServer is a library for the Portenta_H7 with with Vision-Shield Ethernet
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/Portenta_H7_AsyncWebServer
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(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) )
42+
#error For Portenta_H7 only
43+
#endif
44+
45+
#define _PORTENTA_H7_ATCP_LOGLEVEL_ 1
46+
#define _PORTENTA_H7_AWS_LOGLEVEL_ 1
47+
48+
#define USE_ETHERNET_PORTENTA_H7 true
49+
50+
#include <Portenta_Ethernet.h>
51+
#include <Ethernet.h>
52+
#warning Using Portenta_Ethernet lib for Portenta_H7.
53+
54+
#include <Portenta_H7_AsyncWebServer.h>
55+
56+
#include "SDRAM.h"
57+
58+
// Enter a MAC address and IP address for your controller below.
59+
#define NUMBER_OF_MAC 20
60+
61+
byte mac[][NUMBER_OF_MAC] =
62+
{
63+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x01 },
64+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x02 },
65+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x03 },
66+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x04 },
67+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x05 },
68+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x06 },
69+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x07 },
70+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x08 },
71+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x09 },
72+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0A },
73+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0B },
74+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0C },
75+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0D },
76+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0E },
77+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0F },
78+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x10 },
79+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x11 },
80+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x12 },
81+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x13 },
82+
{ 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x14 },
83+
};
84+
// Select the IP address according to your local network
85+
IPAddress ip(192, 168, 2, 232);
86+
87+
AsyncWebServer server(80);
88+
89+
int reqCount = 0; // number of requests received
90+
91+
#define LED_OFF HIGH
92+
#define LED_ON LOW
93+
94+
95+
#define BUFFER_SIZE 768 // a little larger in case required for header shift (destructive send)
96+
char temp[BUFFER_SIZE];
97+
98+
void handleRoot(AsyncWebServerRequest *request)
99+
{
100+
digitalWrite(LED_BUILTIN, LED_ON);
101+
102+
int sec = millis() / 1000;
103+
int min = sec / 60;
104+
int hr = min / 60;
105+
int day = hr / 24;
106+
107+
snprintf(temp, BUFFER_SIZE - 1,
108+
"<html>\
109+
<head>\
110+
<meta http-equiv='refresh' content='5'/>\
111+
<title>AsyncWebServer-%s</title>\
112+
<style>\
113+
body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\
114+
</style>\
115+
</head>\
116+
<body>\
117+
<h2>AsyncWebServer_Portenta_H7!</h2>\
118+
<h3>running on %s</h3>\
119+
<p>Uptime: %d d %02d:%02d:%02d</p>\
120+
<img src=\"/test.svg\" />\
121+
</body>\
122+
</html>", BOARD_NAME, BOARD_NAME, day, hr % 24, min % 60, sec % 60);
123+
124+
request->send(200, "text/html", temp, false);
125+
126+
digitalWrite(LED_BUILTIN, LED_OFF);
127+
}
128+
129+
void handleNotFound(AsyncWebServerRequest *request)
130+
{
131+
digitalWrite(LED_BUILTIN, LED_ON);
132+
String message = "File Not Found\n\n";
133+
134+
message += "URI: ";
135+
message += request->url();
136+
message += "\nMethod: ";
137+
message += (request->method() == HTTP_GET) ? "GET" : "POST";
138+
message += "\nArguments: ";
139+
message += request->args();
140+
message += "\n";
141+
142+
for (uint8_t i = 0; i < request->args(); i++)
143+
{
144+
message += " " + request->argName(i) + ": " + request->arg(i) + "\n";
145+
}
146+
147+
request->send(404, "text/plain", message);
148+
digitalWrite(LED_BUILTIN, LED_OFF);
149+
}
150+
151+
void PrintHeapData(String hIn){
152+
mbed_stats_heap_t heap_stats;
153+
154+
Serial.print("HEAP DATA - ");
155+
Serial.print(hIn);
156+
157+
mbed_stats_heap_get(&heap_stats);
158+
Serial.print(" Cur heap: ");
159+
Serial.print(heap_stats.current_size);
160+
Serial.print(" Res Size: ");
161+
Serial.print(heap_stats.reserved_size);
162+
Serial.print(" Max heap: ");
163+
Serial.println(heap_stats.max_size);
164+
}
165+
166+
167+
char *cStr;
168+
169+
170+
void drawGraph(AsyncWebServerRequest *request)
171+
{
172+
char temp[80];
173+
174+
cStr[0] = '\0';
175+
176+
strcat(cStr, "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"1810\" height=\"150\">\n");
177+
strcat(cStr, "<rect width=\"1810\" height=\"150\" fill=\"rgb(250, 230, 210)\" stroke-width=\"2\" stroke=\"rgb(0, 0, 0)\" />\n");
178+
strcat(cStr, "<g stroke=\"blue\">\n");
179+
int y = rand() % 130;
180+
181+
for (int x = 10; x < 5000; x += 10)
182+
{
183+
int y2 = rand() % 130;
184+
sprintf(temp, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke-width=\"2\" />\n", x, 140 - y, x + 10, 140 - y2);
185+
strcat(cStr, temp);
186+
y = y2;
187+
}
188+
189+
strcat(cStr, "</g>\n</svg>\n");
190+
191+
PrintHeapData("Pre Send");
192+
193+
Serial.print("Out String Length=");
194+
Serial.println(strlen(cStr));
195+
196+
request->send(200, "image/svg+xml", cStr, false);
197+
198+
PrintHeapData("Post Send");
199+
}
200+
201+
202+
void setup()
203+
{
204+
pinMode(LED_BUILTIN, OUTPUT);
205+
digitalWrite(LED_BUILTIN, LED_OFF);
206+
207+
Serial.begin(115200);
208+
while (!Serial && millis() < 5000);
209+
210+
delay(200);
211+
212+
Serial.print("\nStart Async_AdvancedWebServer_MemoryIssues_Send_CString on "); Serial.print(BOARD_NAME);
213+
Serial.print(" with "); Serial.println(SHIELD_TYPE);
214+
Serial.println(PORTENTA_H7_ASYNC_TCP_VERSION);
215+
Serial.println(PORTENTA_H7_ASYNC_WEBSERVER_VERSION);
216+
217+
SDRAM.begin();
218+
219+
cStr = (char *)SDRAM.malloc(100000); // make a little larger than required
220+
221+
if (cStr == NULL) {
222+
Serial.println("Unable top Allocate RAM");
223+
for(;;);
224+
}
225+
226+
///////////////////////////////////
227+
228+
// start the ethernet connection and the server
229+
// Use random mac
230+
uint16_t index = millis() % NUMBER_OF_MAC;
231+
232+
// Use Static IP
233+
//Ethernet.begin(mac[index], ip);
234+
// Use DHCP dynamic IP and random mac
235+
Ethernet.begin(mac[index]);
236+
237+
if (Ethernet.hardwareStatus() == EthernetNoHardware)
238+
{
239+
Serial.println("No Ethernet found. Stay here forever");
240+
241+
while (true)
242+
{
243+
delay(1); // do nothing, no point running without Ethernet hardware
244+
}
245+
}
246+
247+
if (Ethernet.linkStatus() == LinkOFF)
248+
{
249+
Serial.println("Not connected Ethernet cable");
250+
}
251+
252+
Serial.print(F("Using mac index = "));
253+
Serial.println(index);
254+
255+
Serial.print(F("Connected! IP address: "));
256+
Serial.println(Ethernet.localIP());
257+
258+
///////////////////////////////////
259+
260+
server.on("/", HTTP_GET, [](AsyncWebServerRequest * request)
261+
{
262+
handleRoot(request);
263+
});
264+
265+
server.on("/test.svg", HTTP_GET, [](AsyncWebServerRequest * request)
266+
{
267+
drawGraph(request);
268+
});
269+
270+
server.on("/inline", [](AsyncWebServerRequest * request)
271+
{
272+
request->send(200, "text/plain", "This works as well");
273+
});
274+
275+
server.onNotFound(handleNotFound);
276+
277+
server.begin();
278+
279+
Serial.print(F("HTTP EthernetWebServer is @ IP : "));
280+
Serial.println(Ethernet.localIP());
281+
282+
283+
PrintHeapData("Pre Create Arduino String");
284+
285+
}
286+
287+
void heartBeatPrint()
288+
{
289+
static int num = 1;
290+
291+
Serial.print(F("."));
292+
293+
if (num == 80)
294+
{
295+
Serial.println();
296+
num = 1;
297+
}
298+
else if (num++ % 10 == 0)
299+
{
300+
Serial.print(F(" "));
301+
}
302+
}
303+
304+
void check_status()
305+
{
306+
static unsigned long checkstatus_timeout = 0;
307+
308+
#define STATUS_CHECK_INTERVAL 10000L
309+
310+
// Send status report every STATUS_REPORT_INTERVAL (60) seconds: we don't need to send updates frequently if there is no status change.
311+
if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0))
312+
{
313+
heartBeatPrint();
314+
checkstatus_timeout = millis() + STATUS_CHECK_INTERVAL;
315+
}
316+
}
317+
318+
void loop()
319+
{
320+
check_status();
321+
}

0 commit comments

Comments
 (0)