The Captive WiFi Portal has been updated.
I've got the LED pulsing continuously, and the HTML of the web page has an embedded SVG file.
I can't work out how to include the ON/OFF buttons yet, as the HTML in the Portal is presented before the setup inside a block like this
Embedding an SVG image was easier than I thought. All you have to do is put the XML code from the svg file between <svg> ... </svg> tags.
I was able to open the SVG of a file I had in Visual Studio Code and copy the raw XML.
#include <DNSServer.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include "ESPAsyncWebServer.h"
#include <Adafruit_NeoPixel.h>
DNSServer dnsServer;
AsyncWebServer server(80);
String user_name;
String proficiency;
bool name_received = false;
bool proficiency_received = false;
//Sed up the LED
int led = 18; // the PWM pin the LED is attached to
int brightness = 0; // how bright the LED is
int fadeAmount = 5; // how many points to fade the LED by
// How many internal neopixels do we have? some boards have more than one!
#define NUMPIXELS 1
Adafruit_NeoPixel pixels(NUMPIXELS, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);
// Auxiliar variables to store the current output state
String NeoPixelColor = "red";
String output26State = "off";
// Assign output variables to GPIO pins
const int output26 = 26;
// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html><head>
<title>Captive Portal Demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}
.button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;
text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}
.button2 {background-color: #AF4C50;}</style>
</head><body>
<h1>Welcome to The Internet</h1>
<br><br>
<p>The Internet is online</p>
<br><br>
<p><B>DO NOT DROP THE INTERNET</B></p>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/"
width="162.6481"
height="131.60365"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.48.4 r9939"
version="1.0"
sodipodi:docname="specman-2thumbs.svg"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4142136"
inkscape:cx="66.493527"
inkscape:cy="82.80098"
inkscape:document-units="px"
inkscape:current-layer="layer2"
width="228.89px"
height="228.89008px"
inkscape:window-width="1366"
inkscape:window-height="745"
inkscape:window-x="-8"
inkscape:window-y="-8"
showgrid="false"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-522.96998,-264.37834)">
<path
inkscape:connector-curvature="0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 536.17537,313.47567 23.72461,5.26226"
id="path3152" />
<path
inkscape:connector-curvature="0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 548.78306,296.71428 17.46696,11.43071"
id="path3154" />
<path
inkscape:connector-curvature="0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 563.51063,284.42356 15.16233,15.80899"
id="path3156" />
<path
inkscape:connector-curvature="0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 581.81535,272.03727 3.6329,21.69714"
id="path3158" />
<path
inkscape:connector-curvature="0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 601.01676,265.62834 -1.21365,25.5116"
id="path3160" />
<path
inkscape:connector-curvature="0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 619.70372,267.55072 -5.6875,19.62983"
id="path3162" />
<path
inkscape:connector-curvature="0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 637.82687,272.01504 -11.94834,17.79663"
id="path3164" />
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.6008954;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path2160"
sodipodi:cx="490.47076"
sodipodi:cy="244.74196"
sodipodi:rx="107.56804"
sodipodi:ry="86.843918"
d="m 598.0388,244.74196 c 0,47.96257 -48.15985,86.84392 -107.56804,86.84392 -59.40818,0 -107.56803,-38.88135 -107.56803,-86.84392 0,-47.96257 48.15985,-86.84392 107.56803,-86.84392 59.40819,0 107.56804,38.88135 107.56804,86.84392 z"
transform="matrix(0.3573021,-0.2275734,0.2526576,0.3966856,362.81748,335.45959)" />
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.15332937;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3134"
sodipodi:cx="557"
sodipodi:cy="311.59448"
sodipodi:rx="16"
sodipodi:ry="16.5"
d="m 573,311.59448 c 0,9.1127 -7.16344,16.5 -16,16.5 -8.83656,0 -16,-7.3873 -16,-16.5 0,-9.1127 7.16344,-16.5 16,-16.5 8.83656,0 16,7.3873 16,16.5 z"
transform="matrix(0.66195777,-0.43024315,0.42161517,0.67550415,84.022503,343.51634)" />
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3136"
sodipodi:cx="593"
sodipodi:cy="316.09448"
sodipodi:rx="9"
sodipodi:ry="11"
d="m 602,316.09448 c 0,6.07513 -4.02944,11 -9,11 -4.97056,0 -9,-4.92487 -9,-11 0,-6.07513 4.02944,-11 9,-11 4.97056,0 9,4.92487 9,11 z"
transform="matrix(0.8434483,-0.5372104,0.5372104,0.8434483,-56.561173,354.02408)" />
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3138"
sodipodi:cx="559"
sodipodi:cy="317.09448"
sodipodi:rx="6"
sodipodi:ry="6"
d="m 565,317.09448 c 0,3.31371 -2.68629,6 -6,6 -3.31371,0 -6,-2.68629 -6,-6 0,-3.31371 2.68629,-6 6,-6 3.31371,0 6,2.68629 6,6 z"
transform="matrix(0.8434483,-0.5372104,0.5372104,0.8434483,-52.504963,346.67495)" />
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3140"
sodipodi:cx="594"
sodipodi:cy="320.09448"
sodipodi:rx="4"
sodipodi:ry="4"
d="m 598,320.09448 c 0,2.20914 -1.79086,4 -4,4 -2.20914,0 -4,-1.79086 -4,-4 0,-2.20914 1.79086,-4 4,-4 2.20914,0 4,1.79086 4,4 z"
transform="matrix(0.8434483,-0.5372104,0.5372104,0.8434483,-63.544403,354.50048)" />
<path
inkscape:connector-curvature="0"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 587.27637,344.798 c 7.5499,18.99764 53.32665,-8.88788 41.02273,-24.94265"
id="path3142"
sodipodi:nodetypes="cc" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="spex"
transform="translate(-42.467034,0)">
<g
id="g3834"
inkscape:transform-center-y="6.9492243"
transform="translate(-231.63385,-325.61837)">
<path
sodipodi:nodetypes="csssssscsc"
inkscape:connector-curvature="0"
id="rect3016"
d="m 309.92368,377.34669 c 0.16434,0.77209 0.38786,1.52249 0.67664,2.28343 l 0.84264,2.22043 c 3.11216,8.20078 12.38701,12.2339 20.79562,9.04286 l 3.79449,-1.43999 c 8.40861,-3.19103 12.67254,-12.36206 9.56038,-20.56284 l -0.84264,-2.22043 c -0.28878,-0.76094 -0.61942,-1.47068 -1.00866,-2.15743 -0.91368,-3.32758 -10.60562,-1.75272 -16.10825,0.24197 -5.79886,2.10208 -19.56865,9.37964 -17.71022,12.592 z"
style="fill:#f9f9f9;fill-opacity:0.21637424;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<rect
transform="matrix(0.93494003,-0.35480579,0.35480578,0.93494003,0,0)"
y="461.66455"
x="149.74968"
height="6.1890011"
width="5.6407523"
id="rect3021"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
style="fill:#f9f9f9;fill-opacity:0.21637424;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 382.3489,349.86163 c 0.38927,0.68673 0.71988,1.39648 1.00865,2.15743 l 0.84264,2.22042 c 3.11216,8.20078 -1.15176,17.37181 -9.56037,20.56284 l -3.7945,1.44 c -8.40861,3.19103 -17.68346,-0.84209 -20.79562,-9.04287 l -0.84264,-2.22043 c -0.28877,-0.76094 -0.51226,-1.51135 -0.67663,-2.28343 -1.52403,-3.09595 6.77256,-8.34767 12.21314,-10.50588 5.73347,-2.27439 20.86463,-5.96462 21.60533,-2.32808 z"
id="path3023"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csssssscsc" />
<rect
transform="matrix(-0.93494003,0.35480579,0.35480578,0.93494003,0,0)"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3025"
width="5.6407523"
height="6.1890011"
x="-239.46594"
y="461.66455" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="rect3027"
d="m 343.60543,363.39377 c 1.86816,0.61701 3.43149,0.43077 4.28493,-1.62611 l 1.34193,3.53609 c -1.88821,-0.66983 -3.2085,0.15684 -4.28493,1.62612 z"
style="fill:#ffffff;fill-opacity:0;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" />
</g>
<path
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 176.64891,31.409261 c -0.47333,4.885951 -1.70961,10.946289 6.99683,25.202804 -8.51638,-1.547864 -25.23345,-0.992063 -31.71459,1.041623 -4.36201,1.368736 -7.79963,4.556089 -7.30104,9.100539 0.33296,3.03471 2.25343,5.484505 4.84639,6.636034 l 0.33819,2.509335 c -1.8196,1.381125 -2.90285,3.628399 -2.63458,6.073557 0.27861,2.539412 1.92847,4.613589 4.12667,5.520371 0.008,0.0031 -0.91905,1.711823 0.031,-0.0034 l 0.17749,1.943254 c -0.0477,0.467471 -2.79292,0.362862 -2.27114,4.570887 0.52175,4.208058 5.37926,4.577658 6.06928,5.506318 -5.06742,14.144447 29.29326,6.411587 36.45201,6.021847 6.8945,0.0293 12.27852,-5.680577 12.09517,-12.110087 L 202.972,62.11375 c -0.12297,-4.312764 -2.73403,-7.961615 -6.51573,-9.816697 -3.51452,-3.189714 -11.89122,-9.684811 -0.51149,-26.635494 1.71884,-2.560293 0.19925,-7.25678 -6.69822,-7.125152 -8.03931,0.153418 -11.84741,5.128463 -12.59766,12.872856 z"
id="rect3057"
inkscape:connector-curvature="0"
sodipodi:nodetypes="scssccsccczcccccsss" />
<path
sodipodi:nodetypes="scssccsccczcccccsss"
inkscape:connector-curvature="0"
id="path3838"
d="m 65.394507,54.717635 c 2.075804,4.448325 5.262557,9.749333 1.809502,26.093345 7.512502,-4.299643 23.457763,-9.35119 30.246082,-9.595555 4.568759,-0.164464 8.872599,1.693863 9.918239,6.144398 0.69824,2.971999 -0.2952,5.922044 -2.35563,7.87245 l 0.51809,2.478449 c 2.17605,0.695167 3.9468,2.452481 4.5094,4.84711 0.5843,2.486932 -0.27931,4.992605 -2.04921,6.580624 -0.007,0.0055 1.43735,1.307284 -0.0302,0.0075 l 0.48079,1.891184 c 0.20088,0.42479 2.75403,-0.58942 3.6656,3.5517 0.9116,4.14113 -3.5445,6.10965 -3.88529,7.21528 9.49477,11.64447 -25.477573,15.81444 -32.356415,17.83462 -6.489963,2.3271 -13.47008,-1.26015 -15.441616,-7.38267 L 50.819401,92.443774 c -1.322476,-4.106837 -0.0779,-8.41761 2.868561,-11.427757 2.249443,-4.17925 7.980249,-13.096271 -8.40134,-25.280994 -2.474339,-1.840423 -2.608143,-6.774817 3.938293,-8.951189 7.630165,-2.536659 12.879512,0.883437 16.169735,7.934176 z"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:transform-center-x="17.070774"
inkscape:transform-center-y="-17.110181" />
</g>
</svg>
</body></html>)rawliteral";
class CaptiveRequestHandler : public AsyncWebHandler {
public:
CaptiveRequestHandler() {}
virtual ~CaptiveRequestHandler() {}
bool canHandle(AsyncWebServerRequest *request){
//request->addInterestingHeader("ANY");
return true;
}
void handleRequest(AsyncWebServerRequest *request) {
request->send_P(200, "text/html", index_html);
}
};
void setupServer(){
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html);
Serial.println("Client Connected");
});
server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
String inputMessage;
String inputParam;
if (request->hasParam("name")) {
inputMessage = request->getParam("name")->value();
inputParam = "name";
user_name = inputMessage;
Serial.println(inputMessage);
name_received = true;
}
if (request->hasParam("proficiency")) {
inputMessage = request->getParam("proficiency")->value();
inputParam = "proficiency";
proficiency = inputMessage;
Serial.println(inputMessage);
proficiency_received = true;
}
request->send(200, "text/html", "The values entered by you have been successfully sent to the device <br><a href=\"/\">Return to Home Page</a>");
});
}
void setup() {
// put your setup code here, to run once:
//your other setup stuff...
Serial.begin(115200);
Serial.println();
Serial.println("Setting up AP Mode");
WiFi.mode(WIFI_AP);
WiFi.softAP("The_Internet");
Serial.print("AP IP address: ");Serial.println(WiFi.softAPIP());
Serial.println("Setting up Async WebServer");
setupServer();
Serial.println("Starting DNS Server");
dnsServer.start(53, "*", WiFi.softAPIP());
server.addHandler(new CaptiveRequestHandler()).setFilter(ON_AP_FILTER);//only when requested from AP
//more handlers...
server.begin();
Serial.println("All Done!");
// declare pin 18 to be an output for the LED:
pinMode(led, OUTPUT);
#if defined(NEOPIXEL_POWER)
// If this board has a power control pin, we must set it to output and high
// in order to enable the NeoPixels. We put this in an #if defined so it can
// be reused for other boards without compilation errors
pinMode(NEOPIXEL_POWER, OUTPUT);
digitalWrite(NEOPIXEL_POWER, HIGH);
#endif
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
pixels.setBrightness(20); // not so bright
// set color red
pixels.fill(0xFF0000);
pixels.show();
// set the brightness of pin 9:
analogWrite(led, brightness);
}
void loop(){
analogWrite(led, brightness);
dnsServer.processNextRequest();
if(name_received && proficiency_received){
Serial.print("Hello ");Serial.println(user_name);
Serial.print("You have stated your proficiency to be ");Serial.println(proficiency);
name_received = false;
proficiency_received = false;
Serial.println("We'll wait for the next client now");
}
//do the fade
// change the brightness for next time through the loop:
brightness = brightness + fadeAmount;
delay(50);
// reverse the direction of the fading at the ends of the fade:
if (brightness <= 0 || brightness >= 255) {
fadeAmount = -fadeAmount;
delay(50);
}
}