This repository has been archived by the owner on Jan 29, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Parameters.ino
479 lines (386 loc) · 17.4 KB
/
Parameters.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
/**
Example for the ESP32_SC_W6100 HTTP(S) Webserver
IMPORTANT NOTE:
To run this script, your need to
1) Make sure to have certificate data available. You will find a
shell script (create_cert.sh) and instructions to do so in the library folder
under extras/
This script will install an HTTPS Server on your ESP32_SC_W6100 with the following
functionalities:
- Show page on web server root that will display some SVG smileys.
Using a simple HTML form and GET parameters, you can change the colors
of those images.
- Provide the svg image with an optional GET parameter that allows to
modify the background color, URL: /images/awesome.svg
- Provide an example that shows how wildcard URL parameters get parsed
URL: /urlparam/some/thing
- 404 for everything else
*/
// Include certificate data (see note above)
#include "cert.h"
#include "private_key.h"
//////////////////////////////////////////////////
// For ESP32_SC_W6100
#define DEBUG_ETHERNET_WEBSERVER_PORT Serial
// Debug Level from 0 to 4
#define _ETHERNET_WEBSERVER_LOGLEVEL_ 3
//////////////////////////////////////////////////////////
// For ESP32-S3
// Optional values to override default settings
// Don't change unless you know what you're doing
//#define ETH_SPI_HOST SPI3_HOST
//#define SPI_CLOCK_MHZ 25
// Must connect INT to GPIOxx or not working
//#define INT_GPIO 4
//#define MISO_GPIO 13
//#define MOSI_GPIO 11
//#define SCK_GPIO 12
//#define CS_GPIO 10
// For ESP32_C3
// Optional values to override default settings
// Don't change unless you know what you're doing
//#define ETH_SPI_HOST SPI2_HOST
//#define SPI_CLOCK_MHZ 25
// Must connect INT to GPIOxx or not working
//#define INT_GPIO 10
//#define MISO_GPIO 5
//#define MOSI_GPIO 6
//#define SCK_GPIO 4
//#define CS_GPIO 7
//////////////////////////////////////////////////////////
#include <WebServer_ESP32_SC_W6100.h>
//////////////////////////////////////////////////
// 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, 0xFE, 0x01 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x02 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x03 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x04 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x05 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x06 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x07 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x08 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x09 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0A },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0B },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0C },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0D },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0E },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0F },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x10 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x11 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x12 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x13 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x14 },
};
// Select the IP address according to your local network
IPAddress myIP(192, 168, 2, 232);
IPAddress myGW(192, 168, 2, 1);
IPAddress mySN(255, 255, 255, 0);
// Google DNS Server IP
IPAddress myDNS(8, 8, 8, 8);
//////////////////////////////////////////////////
#include <HTTPS_Server_Generic.h>
// The HTTPS Server comes in a separate namespace. For easier use, include it here.
using namespace httpsserver;
// Create an SSL certificate object from the files included above
SSLCert cert = SSLCert(
example_crt_DER, example_crt_DER_len,
example_key_DER, example_key_DER_len
);
// Create an SSL-enabled server that uses the certificate
// The constructor takes some more parameters, but we go for default values here.
HTTPSServer secureServer = HTTPSServer(&cert);
// Handler functions
void handleRoot(HTTPRequest * req, HTTPResponse * res)
{
// We will deliver an HTML page
res->setHeader("Content-Type", "text/html");
// Write the response page
res->println("<!DOCTYPE html>");
res->println("<html>");
res->println("<head><title>Hello World!</title></head>");
res->println("<style>.info{font-style:italic}</style>");
res->println("<body>");
res->println("<h1>Query Parameters</h1>");
res->println("<p class=\"info\">The parameters after the question mark in your URL.</p>");
// Show a form to select a color to colorize the faces
// We pass the selection as get parameter "shades" to this very same page,
// so we can evaluate it below
res->println("<form method=\"GET\" action=\"/\">Show me faces in shades of ");
res->println("<select name=\"shades\">");
res->println("<option value=\"red\">red</option>");
res->println("<option value=\"green\">green</option>");
res->println("<option value=\"blue\">blue</option>");
res->println("<option value=\"yellow\">yellow</option>");
res->println("<option value=\"cyan\">cyan</option>");
res->println("<option value=\"magenta\">magenta</option>");
res->println("<option value=\"rainbow\">rainbow</option>");
res->println("</select>");
res->println("<button type=\"submit\">Go!</button>");
res->println("</form>");
// Get the params to check if the user did select something
ResourceParameters * params = req->getParams();
std::string paramName = "shades";
// Print 6 faces
for (int i = 0; i < 6; i++)
{
// Include the image of the handleSVG function with a specific color code
res->print("<img style=\"height:100px;width:100px\" src=\"images/awesome.svg?color=");
// Depending on the selection we show the images in a specific color shade
// Default is dark gray.
int r = 63, g = 63, b = 63;
std::string paramVal;
if (params->getQueryParameter(paramName, paramVal))
{
if (paramVal == "red" || paramVal == "magenta" || paramVal == "yellow" || paramVal == "rainbow")
{
r = 128 + random(0, 128);
}
if (paramVal == "green" || paramVal == "cyan" || paramVal == "yellow" || paramVal == "rainbow")
{
g = 128 + random(0, 128);
}
if (paramVal == "blue" || paramVal == "magenta" || paramVal == "cyan" || paramVal == "rainbow")
{
b = 128 + random(0, 128);
}
}
// Print the random color. As the HTTPResponse extends the Print interface, we can make use of that.
res->print(r, HEX);
res->print(g, HEX);
res->print(b, HEX);
res->print("\" alt=\"Awesome!\" />");
}
res->println("<p>You'll find another demo <a href=\"/queryparams?a=42&b&c=13&a=hello\">here</a>.</p>");
// Link to the path parameter demo
res->println("<h1>Path Parameters</h1>");
res->println("<p class=\"info\">The parameters derived from placeholders in your path, like /foo/bar.</p>");
res->println("<p>You'll find the demo <a href=\"/urlparam/foo/bar\">here</a>.</p>");
res->println("</body>");
res->println("</html>");
}
// This callback responds with an SVG image to a GET request. The icon is the "awesome face".
// (borrowed from https://commons.wikimedia.org/wiki/File:718smiley.svg)
//
// If the color query parameter is set (so the URL is like awesome.svg?color=fede58), the
// background of our awesome face is changed.
void handleSVG(HTTPRequest * req, HTTPResponse * res)
{
// Get access to the parameters
ResourceParameters * params = req->getParams();
// Set SVG content type
res->setHeader("Content-Type", "image/svg+xml");
// Set a default color
std::string fillColor = "fede58";
// Get request parameter (like awesome.svg?color=ff0000) and validate it
std::string colorParamName = "color";
// Check that the parameter is set and retrieve it.
// The getQueryParameter function will modify the second parameter, but only if the query
// parameter is set.
std::string requestColor;
if (params->getQueryParameter(colorParamName, requestColor))
{
// Check for correct length
if (requestColor.length() == 6)
{
bool colorOk = true;
// Check that we only have characters within [0-9a-fA-F]
for (int i = 1; i < 6 && colorOk; i++)
{
if (!(
(requestColor[i] >= '0' && requestColor[i] <= '9' ) ||
(requestColor[i] >= 'a' && requestColor[i] <= 'f' ) ||
(requestColor[i] >= 'A' && requestColor[i] <= 'F' )
))
{
colorOk = false;
}
}
// If validation was successful, replace the default color
if (colorOk)
{
fillColor = requestColor;
}
}
}
// Print the SVG to the response:
res->print("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");
res->print("<svg id=\"svg1923\" width=\"733\" xmlns=\"http://www.w3.org/2000/svg\" height=\"733\">");
res->print("<circle cy=\"366.5\" cx=\"366.5\" r=\"366.5\"/>");
res->print("<circle cy=\"366.5\" cx=\"366.5\" r=\"336.5\" fill=\"#");
// We insert the color from the parameter here
res->printStd(fillColor);
res->print("\"/>");
res->print("<path d=\"m325 665c-121-21-194-115-212-233v-8l-25-1-1-18h481c6 13 10 27 13 41 13 94-38 146-114 193-45 23-93 29-142 26z\"/>");
res->print("<path d=\"m372 647c52-6 98-28 138-62 28-25 46-56 51-87 4-20 1-57-5-70l-423-1c-2 56 39 118 74 157 31 34 72 54 116 63 11 2 38 2 49 0z\" fill=\"#871945\"/>");
res->print("<path d=\"m76 342c-13-26-13-57-9-85 6-27 18-52 35-68 21-20 50-23 77-18 15 4 28 12 39 23 18 17 30 40 36 67 4 20 4 41 0 60l-6 21z\"/>");
res->print("<path d=\"m234 323c5-6 6-40 2-58-3-16-4-16-10-10-14 14-38 14-52 0-15-18-12-41 6-55 3-3 5-5 5-6-1-4-22-8-34-7-42 4-57.6 40-66.2 77-3 17-1 53 4 59h145.2z\" fill=\"#fff\"/>");
res->print("<path d=\"m378 343c-2-3-6-20-7-29-5-28-1-57 11-83 15-30 41-52 72-60 29-7 57 0 82 15 26 17 45 49 50 82 2 12 2 33 0 45-1 10-5 26-8 30z\"/>");
res->print("<path d=\"m565 324c4-5 5-34 4-50-2-14-6-24-8-24-1 0-3 2-6 5-17 17-47 13-58-9-7-16-4-31 8-43 4-4 7-8 7-9 0 0-4-2-8-3-51-17-105 20-115 80-3 15 0 43 3 53z\" fill=\"#fff\"/>");
res->print("<path d=\"m504 590s-46 40-105 53c-66 15-114-7-114-7s14-76 93-95c76-18 126 49 126 49z\" fill=\"#f9bedd\"/>");
res->print("</svg>");
}
// This is a more generic demo for the query parameters. It makes use of the iterator
// interface to access them, which is useful if you do not know the parameter names in
// advance.
void handleQueryDemo(HTTPRequest * req, HTTPResponse * res)
{
// A word of warning: In this example, we use the query parameters and directly print
// them into the HTML output. We do this to simplify the demo. NEVER do this in a
// real application, as it allows cross-site-scripting.
res->setHeader("Content-Type", "text/html");
res->println("<!DOCTYPE html>");
res->println("<html>");
res->println("<head>");
res->println("<title>Query Parameter Demo</title>");
res->println("</head>");
res->println("<body>");
res->println("<p>The following query parameters have been set:</p>");
// Start a table to display the parameters
res->println("<table style=\"border:1px solid black collapse;\">");
res->println("<tr><th>Key</th><th>Value</th></tr>");
// Iterate over the parameters. For more information, read about the C++ standard template library,
// especially about vectors and iterators.
ResourceParameters *params = req->getParams();
for (auto it = params->beginQueryParameters(); it != params->endQueryParameters(); ++it)
{
res->print("<tr><td>");
// The iterator yields std::pairs of std::strings. The first value contains the parameter key
res->printStd((*it).first);
res->print("</td><td>");
// and the second value contains the parameter value
res->printStd((*it).second);
res->println("</td></tr>");
}
res->println("</table>");
// You can retrieve the total parameter count from the parameters instance:
res->print("<p>There are a total of ");
res->print(params->getQueryParameterCount());
res->print(" parameters, with ");
res->print(params->getQueryParameterCount(true));
res->println(" unique keys.</p>");
res->println("<p>Go <a href=\"/\">back to main page</a>.</p>");
res->println("</body>");
res->println("</html>");
}
// This is a simple handler function that will show the content of URL parameters.
// If you call for example /urlparam/foo/bar, you will get the parameter values
// "foo" and "bar" provided by the ResourceParameters.
void handlePathParam(HTTPRequest * req, HTTPResponse * res)
{
// Get access to the parameters
ResourceParameters * params = req->getParams();
// Set a simple content type
res->setHeader("Content-Type", "text/plain");
// The url pattern is: /urlparam/*/*
// This will make the content for the first parameter available on index 0,
// and the second wildcard as index 1.
// getPathParameter will - like getQueryParameter - write the value to the second parameter,
// and return true, if the index is valid. Otherwise it returns false and leaves the second
// parameter as it is.
std::string parameter1, parameter2;
// Print the first parameter value
if (params->getPathParameter(0, parameter1))
{
res->print("Parameter 1: ");
res->printStd(parameter1);
}
res->println();
// Print the second parameter value
if (params->getPathParameter(1, parameter2))
{
res->print("Parameter 2: ");
res->printStd(parameter2);
}
res->println("\n\nChange the parameters in the URL to see how they get parsed!");
}
// For details to this function, see the Static-Page example
void handle404(HTTPRequest * req, HTTPResponse * res)
{
req->discardRequestBody();
res->setStatusCode(404);
res->setStatusText("Not Found");
res->setHeader("Content-Type", "text/html");
res->println("<!DOCTYPE html>");
res->println("<html>");
res->println("<head><title>Not Found</title></head>");
res->println("<body><h1>404 Not Found</h1><p>The requested resource was not found on this server.</p></body>");
res->println("</html>");
}
void setup()
{
// For logging
Serial.begin(115200);
while (!Serial && millis() < 5000);
delay(500);
///////////////////////////////////////////////
Serial.print("\nStarting Parameters on " + String(ARDUINO_BOARD));
Serial.println(" with " + String(SHIELD_TYPE));
Serial.println(WEBSERVER_ESP32_SC_W6100_VERSION);
Serial.println(HTTPS_SERVER_GENERIC_VERSION);
///////////////////////////////////
// To be called before ETH.begin()
ESP32_W6100_onEvent();
// start the ethernet connection and the server:
// Use DHCP dynamic IP and random 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 *W6100_Mac = W6100_Default_Mac);
ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, ETH_SPI_HOST );
//ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, ETH_SPI_HOST, mac[millis() % NUMBER_OF_MAC] );
// 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_W6100_waitForConnect();
///////////////////////////////////
Serial.print(F("HTTPS EthernetWebServer is @ IP : "));
Serial.println(ETH.localIP());
Serial.print(F("To access, use https://"));
Serial.println(ETH.localIP());
///////////////////////////////////////////////
// For every resource available on the server, we need to create a ResourceNode
// The ResourceNode links URL and HTTP method to a handler function
ResourceNode * nodeRoot = new ResourceNode("/", "GET", &handleRoot);
ResourceNode * nodeSVG = new ResourceNode("/images/awesome.svg", "GET", &handleSVG);
ResourceNode * nodeQueryDemo = new ResourceNode("/queryparams", "GET", &handleQueryDemo);
ResourceNode * node404 = new ResourceNode("", "GET", &handle404);
// Path parameters
// If you want (for example) to return a specific instance of an object type by its ID
// you can use URLs like /led/1, led/2, ... - And you do not need to register one Resource
// Node per ID, but you can use wildcards in the route definition. The following route
// has two wildcards, and will match for example to /urlparam/foo/bar, where "foo" and "bar"
// are accessible parameters in the handler function.
// Note: The wildcards can only be used between slashes at the moment (so /urlparam* would
// not work).
ResourceNode * nodeURLParam = new ResourceNode("/urlparam/*/*", "GET", &handlePathParam);
// Add the root node to the server
secureServer.registerNode(nodeRoot);
// Add the SVG image
secureServer.registerNode(nodeSVG);
// Query parameter demo
secureServer.registerNode(nodeQueryDemo);
// Add the path parameter
// Note: The order of nodes may become important here. If you have one node for "/led" (e.g. list of LEDs)
// and one node for /led/* (LED details), you should register the non-parameterized version first. The server
// follows a first-match policy. If you would register the details node first, a call to /led/ will be targeted
// at the details handler function with an empty parameter, which is probably not what you want.
secureServer.registerNode(nodeURLParam);
// Add the 404 not found node to the server.
// The path is ignored for the default node.
secureServer.setDefaultNode(node404);
Serial.println("Starting server...");
secureServer.start();
if (secureServer.isRunning())
{
Serial.println("Server ready.");
}
}
void loop()
{
// This call will let the server do its work
secureServer.loop();
// Other code would go here...
delay(1);
}