|
| 1 | +/* |
| 2 | +This example enables catch-all Captive portal for ESP32 Access-Point |
| 3 | +It will allow modern devices/OSes to detect that WiFi connection is |
| 4 | +limited and offer a user to access a banner web-page. |
| 5 | +There is no need to find and open device's IP address/URL, i.e. http://192.168.4.1/ |
| 6 | +This works for Android, Ubuntu, FireFox, Windows, maybe others... |
| 7 | +*/ |
| 8 | + |
| 9 | +#include <Arduino.h> |
1 | 10 | #include <WiFi.h>
|
2 | 11 | #include <DNSServer.h>
|
| 12 | +#include <WebServer.h> |
| 13 | + |
3 | 14 |
|
4 |
| -const byte DNS_PORT = 53; |
5 |
| -IPAddress apIP(8,8,4,4); // The default android DNS |
6 | 15 | DNSServer dnsServer;
|
7 |
| -WiFiServer server(80); |
| 16 | +WebServer server(80); |
| 17 | + |
| 18 | +static const char responsePortal[] = R"===( |
| 19 | +<!DOCTYPE html><html><head><title>ESP32 CaptivePortal</title></head><body> |
| 20 | +<h1>Hello World!</h1><p>This is a captive portal example page. All unknown http requests will |
| 21 | +be redirected here.</p></body></html> |
| 22 | +)==="; |
| 23 | + |
| 24 | +// index page handler |
| 25 | +void handleRoot() { |
| 26 | + server.send(200, "text/plain", "Hello from esp32!"); |
| 27 | +} |
8 | 28 |
|
9 |
| -String responseHTML = "" |
10 |
| - "<!DOCTYPE html><html><head><title>CaptivePortal</title></head><body>" |
11 |
| - "<h1>Hello World!</h1><p>This is a captive portal example. All requests will " |
12 |
| - "be redirected here.</p></body></html>"; |
| 29 | +// this will redirect unknown http req's to our captive portal page |
| 30 | +// based on this redirect various systems could detect that WiFi AP has a captive portal page |
| 31 | +void handleNotFound() { |
| 32 | + server.sendHeader("Location", "/portal"); |
| 33 | + server.send(302, "text/plain", "redirect to captive portal"); |
| 34 | +} |
13 | 35 |
|
14 |
| -void setup() { |
| 36 | +void setup() { |
| 37 | + Serial.begin(115200); |
15 | 38 | WiFi.mode(WIFI_AP);
|
16 | 39 | WiFi.softAP("ESP32-DNSServer");
|
17 |
| - WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); |
18 | 40 |
|
19 |
| - // if DNSServer is started with "*" for domain name, it will reply with |
20 |
| - // provided IP to all DNS request |
21 |
| - dnsServer.start(DNS_PORT, "*", apIP); |
| 41 | + // by default DNSServer is started serving any "*" domain name. It will reply |
| 42 | + // AccessPoint's IP to all DNS request (this is requred for Captive Portal detection) |
| 43 | + dnsServer.start(); |
| 44 | + |
| 45 | + // serve a simple root page |
| 46 | + server.on("/", handleRoot); |
| 47 | + |
| 48 | + // serve portal page |
| 49 | + server.on("/portal",[](){server.send(200, "text/html", responsePortal);}); |
22 | 50 |
|
| 51 | + // all unknown pages are redirected to captive portal |
| 52 | + server.onNotFound(handleNotFound); |
23 | 53 | server.begin();
|
24 | 54 | }
|
25 | 55 |
|
26 | 56 | void loop() {
|
27 |
| - dnsServer.processNextRequest(); |
28 |
| - WiFiClient client = server.available(); // listen for incoming clients |
29 |
| - |
30 |
| - if (client) { |
31 |
| - String currentLine = ""; |
32 |
| - while (client.connected()) { |
33 |
| - if (client.available()) { |
34 |
| - char c = client.read(); |
35 |
| - if (c == '\n') { |
36 |
| - if (currentLine.length() == 0) { |
37 |
| - client.println("HTTP/1.1 200 OK"); |
38 |
| - client.println("Content-type:text/html"); |
39 |
| - client.println(); |
40 |
| - client.print(responseHTML); |
41 |
| - break; |
42 |
| - } else { |
43 |
| - currentLine = ""; |
44 |
| - } |
45 |
| - } else if (c != '\r') { |
46 |
| - currentLine += c; |
47 |
| - } |
48 |
| - } |
49 |
| - } |
50 |
| - client.stop(); |
51 |
| - } |
| 57 | + server.handleClient(); |
| 58 | + delay(5); // give CPU some idle time |
52 | 59 | }
|
0 commit comments