From d4efec4161425dbc1bdbd25705aae114a6dce7b4 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 17 Nov 2022 13:47:41 +1300 Subject: [PATCH] V0.3.0 (#2) * Update README.md * Tidy up and remove unused libs * 0.3.0 Dev --- README.md | 52 +++++++++++++++++++--------------- platformio.ini | 4 +-- src/main.cpp | 76 +++++++++++++++++++++++++++++++++++--------------- 3 files changed, 85 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 79cc62d..fe1ee1e 100644 --- a/README.md +++ b/README.md @@ -2,50 +2,57 @@ A ESP32 Captive Portal (think airport wifi sign in page) example that works on all devices (or that's the goal). -When you connect to the wifi "captive" password "12345678" it should take you straight to http://4.3.2.1/ and display some simple text. - -| Status | Issue | Version | Device Name | Browser | OS | -|--------|----------|---------|-------------------------|---------|-------------------------| -| ✅ | | V0.2.0 | Iphone XR | Default | iOS 16 | -| ✅ | | V0.2.0 | XPS15 9550 | Firefox | Win 11 Home | -| ✅ | | V0.2.0 | XPS15 9550 | Chrome | Win 11 Home | -| ✅ | | V0.2.0 | Samsung A53 | Default | Android 9 (OneUI1) | -| 🤷 | Cellular | V0.2.0 | Onplus 6 | Default | Android 11 (OxygenOS11) | -| ✅ | | V0.2.0 | XPS15 9575 | Edge | Win 10 Pro | -| ✅ | | V0.2.0 | XPS15 9570 | Edge | Win 10 Edu | -| ✅ | | V0.2.0 | Samsung S20 FE 5G | Default | Android 12 (OneUI4.1) | - +When you connect to the wifi "captive" password "12345678" it should take you straight to and display a green page with some simple text. + +| Status | Version | Connect | Popup | Serve Page | OS | Device Name | Browser | Notes | +|--------|-----------|---------|-------|------------|-------------------------|---------------------|---------|----------------------| +| ✅ | V0.3.0 | ✅ | ✅ | ✅ | Win 11 Home (22H2) | XPS15 9550 | Firefox | | +| ✅ | V0.3.0 | ✅ | ✅ | ✅ | Win 11 Home (22H2) | XPS15 9550 | Chrome | | +| ❌ | V0.3.0 | ❌ | ✅ | ✅ | Android 11 (OxygenOS11) | Oneplus 6 | Default | Cellular must be off | +| ✅ | V0.3.0 | ✅ | ✅ | ✅ | MacOSX (10.6.8) | Macbook Air (2011) | Safari | | +| ✅ | V0.3.0 | ✅ | ✅ | ✅ | Windows 7 Starter | Toshiba NB200 | IE | | +| ✅ | V0.3.0 | ✅ | ✅ | ✅ | iOS 9 (9.3.5) | iPad mini (2012) | Default | | +| ✅ | V0.3.0 | ✅ | ✅ | ✅ | Android 9 (OneUI1) | Samsung A53 | Default | | +| ✅ | V0.3.0 | ✅ | ✅ | ✅ | iOS 10 (10.3.3) | iPhone 5c | Default | | +| ✅ | V0.2.0 | ✅ | ✅ | ✅ | iOS 16 | iPhone XR | Default | | +| ❌ | V0.2.0 | ✅ | ❌ | ✅ | MacOS Monterey (12.5.1) | Macbook Pro 16 2019 | Chrome | | +| ❌ | V0.2.0 | ✅ | ❌ | ✅ | MacOS Monterey (12.5.1) | Macbook Pro 16 2019 | Safari | | +| ✅ | V0.1 | ✅ | ✅ | ✅ | Win 10 Pro | XPS15 9575 | Edge | | +| ✅ | V0.1 | ✅ | ✅ | ✅ | Win 10 Edu | XPS15 9570 | Edge | | +| ✅ | V0.1 | ✅ | ✅ | ✅ | Android 12 (OneUI4.1) | Samsung S20 FE 5G | Default | | ## Quickstart with ESP Home Flasher tool on Windows, MacOS and Linux -This is a simple GUI-based tool that can be downloaded from here: https://github.com/esphome/esphome-flasher/releases/ - -If running Windows, you will most likely need a driver from here: https://www.wemos.cc/en/latest/ch340_driver.html before your computer will show the COM port in ESPhome Flasher. +This is a simple GUI-based tool that can be downloaded from here: +If running Windows, you will most likely need a driver from here: before your computer will show the COM port in ESPhome Flasher. ## Did it work? -If you test this code on a device (even if it works) it would be really helpful if you fill out the form here: https://forms.gle/ArLPTnwRA3QGTKyc6 +If you test this code on a device (even if it works) it would be really helpful if you fill out the form here: +## Known Bugs/limitations with current version -## Known Bugs with current version - Oneplus 6 phone (Oxygen OS 11) sometimes gets stuck on setting client side IP address when cellular is on - +- On older devices you may need to open a web browser for it to display +- max of 4 clients connected at the same time +- MacOS post macOS Big Sur no pop up ### Further testing required -- If you have a lot of tabs open in Windows 11 (and probably other desktop OS) it increases the load on the ESP32 DNS server. + +- If you have a lot of tabs open in Windows 11 (and probably other OS) it increases the load on the ESP32 DNS server. - HTML Webpage being served multiple times - Other ESP32 chip variants (all testing so far is on the ESP32 D0WDQ6 chip in the ESP32S module) - Test increasing the max clients connected up from 4 to max supported 10 - ### Future Dev Options to look into (Help or suggestions are appreciated): + - Set client DHCP IP address range in private space (currently clients must accept DHCP Server Range: 4.3.2.2 to 4.3.2.12) - Support integrating the DHCP or IPv6 Router Advertisement (RA) options for Captive Portals on iOS 14+ and macOS Big Sur+ https://developer.apple.com/news/?id=q78sq5rv - Port https://github.com/Aircoookie/WLED-WebInstaller - ### Compile yourself using PlatformIO highly recommended + - Make sure Git client is installed on your system. - Download and install Visual Studio Code by Microsoft. - Open VS Code and go to the Extensions manager (the icon with the stacked blocks in the left bar) @@ -53,3 +60,4 @@ If you test this code on a device (even if it works) it would be really helpful - Download the source code by executing git clone https://github.com/CDFER/Captive-Portal-ESP32.git. in some folder. - In VS Code Go to File -> Open Folder and open that root folder (the one that contains platformio.ini, NOT the src folder) - Upload to the esp32 using the right arrow button in the bottom left corner of vs code + diff --git a/platformio.ini b/platformio.ini index 0099c12..c335974 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,10 +16,8 @@ framework = arduino lib_deps = https://github.com/me-no-dev/AsyncTCP ESP Async WebServer -monitor_speed = 115200 # default esp32 check_skip_packages = yes # fixes inspect in platformio board_build.partitions = huge_app.csv # not required, increases Flash size for program -board_build.filesystem = littlefs [env:myrelease] #Low flash and ram usage, no debugging build_type = release @@ -29,6 +27,8 @@ build_flags = [env:mydebug] build_type = debug +monitor_speed = 115200 # default esp32 +monitor_filters = esp32_exception_decoder build_flags = -DCORE_DEBUG_LEVEL=5 # verbose debug info output on serial -DUSE_SERIAL=true #enables the use of the serial port diff --git a/src/main.cpp b/src/main.cpp index de77e4b..c7c17ce 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,13 +1,11 @@ #include #include #include //Used for mpdu_rx_disable android workaround -#include #include //https://github.com/me-no-dev/AsyncTCP using the latest dev version from @me-no-dev #include //ESP Async WebServer using the latest stable version from @me-no-dev #define DEBUG_SERIAL if(USE_SERIAL)Serial //don't touch, enable serial in platformio.ini - // Dependency Graph // |-- AsyncTCP @ 1.1.1+sha.ca8ac5f // |-- ESP Async WebServer @ 1.2.3 @@ -16,29 +14,57 @@ // | |-- WiFi @ 2.0.0 // |-- DNSServer @ 2.0.0 // | |-- WiFi @ 2.0.0 -// |-- WiFi @ 2.0.0 //Pre reading on the fundamentals of captive portals https://textslashplain.com/2022/06/24/captive-portals/ +const char * ssid = "captive"; //FYI The SSID can't have a space in it. +const char * password = "12345678"; + +#define MAX_CLIENTS 4 +#define WIFI_CHANNEL 6 //2.4ghz channel 6 + + +const IPAddress localIP(4, 3, 2, 1); // the IP address the web server, Samsung requires the IP to be in public space +const IPAddress gatewayIP(4, 3, 2, 1); // IP address of the network +const IPAddress subnetMask(255,255,255,0); + +const String localIPURL = "http://4.3.2.1"; + +const char index_html[] PROGMEM = R"=====( + + + ESP32 Captive Portal + + + + +

Hello World!

+

This is a captive portal example. All requests will be redirected here

+ + +)====="; + DNSServer dnsServer; AsyncWebServer server(80); -void setup(){ //the order of the code is really important and it is critical the the android workaround is after the dns and sofAP setup +void setup(){ //the order of the code is important and it is critical the the android workaround is after the dns and sofAP setup #if USE_SERIAL == true Serial.begin(115200); while (!Serial); - Serial.println("\n\nCaptive Test, compiled " __DATE__ " " __TIME__ "by CD_FER"); + Serial.println("\n\nCaptive Test, V0.3.0dev compiled " __DATE__ " " __TIME__ " by CD_FER"); #endif WiFi.mode(WIFI_AP); - WiFi.softAPConfig(IPAddress(4, 3, 2, 1), IPAddress(4, 3, 2, 1), IPAddress(255, 255, 255, 0)); //Samsung requires the IP to be in public space - WiFi.softAP("captive", "12345678", 6, 0, 4); //2.4ghz channel 6, do broadcast SSID (0), 4 max clients, FYI The SSID in SoftAP can't have a space in it. + WiFi.softAPConfig(localIP, gatewayIP, subnetMask); //Samsung requires the IP to be in public space + WiFi.softAP(ssid, password, WIFI_CHANNEL, 0, MAX_CLIENTS); - dnsServer.setErrorReplyCode(DNSReplyCode::NoError); //not sure if this is necessary dnsServer.setTTL(300); //set 5min client side cache for DNS - // if DNSServer is started with "*" for domain name, it will reply with provided IP to all DNS request - dnsServer.start(53, "*", WiFi.softAPIP()); + dnsServer.start(53, "*", localIP); //if DNSServer is started with "*" for domain name, it will reply with provided IP to all DNS request //ampdu_rx_disable android workaround see https://github.com/espressif/arduino-esp32/issues/4423 esp_wifi_stop(); @@ -49,39 +75,42 @@ void setup(){ //the order of the code is really important and it is critical the esp_wifi_init(&my_config); //set the new config esp_wifi_start(); //Restart WiFi - delay(100); //this seems to be necessary don't ask me why + delay(100); //this is necessary don't ask me why //Required - server.on("/connecttest.txt",[](AsyncWebServerRequest *request){request->redirect("http://logout.net/");}); //windows 11 captive portal workaround + server.on("/connecttest.txt",[](AsyncWebServerRequest *request){request->redirect("http://logout.net");}); //windows 11 captive portal workaround - //Probably not Required, but might speed things up? - server.on("/canonical.html",[](AsyncWebServerRequest *request){request->redirect("http://4.3.2.1/");}); //firefox captive portal call home + //Probably not all are Required, but some are. Others might speed things up? + server.on("/canonical.html",[](AsyncWebServerRequest *request){request->redirect(localIPURL);}); //firefox captive portal call home server.on("/chrome-variations/seed",[](AsyncWebServerRequest *request){request->send(200);}); //chrome captive portal call home - server.on("/redirect",[](AsyncWebServerRequest *request){request->redirect("http://4.3.2.1/");}); //microsoft redirect + server.on("/redirect",[](AsyncWebServerRequest *request){request->redirect(localIPURL);}); //microsoft redirect server.on("/success.txt",[](AsyncWebServerRequest *request){request->send(200);}); //firefox captive portal call home server.on("/wpad.dat",[](AsyncWebServerRequest *request){request->send(404);}); //Honestly don't understand what this is but a 404 stops win 10 keep calling this repeatedly and panicking the esp32 :) - server.on("/generate_204",[](AsyncWebServerRequest *request){request->redirect("http://4.3.2.1/");}); //chromium? android? captive portal redirect + server.on("/generate_204",[](AsyncWebServerRequest *request){request->redirect(localIPURL);}); //chromium? android? captive portal redirect server.on("/service/update2/json",[](AsyncWebServerRequest *request){request->send(200);}); //firefox? server.on("/chat",[](AsyncWebServerRequest *request){request->send(404);}); //No stop asking Whatsapp, there is no internet connection + server.on("/startpage",[](AsyncWebServerRequest *request){request->redirect(localIPURL);}); + //return 404 to webpage icon server.on("/favicon.ico",[](AsyncWebServerRequest *request){request->send(404);}); //webpage icon //Serve Basic HTML Page WARNING IOS (and maybe macos) WILL NOT POP UP IF THIS PAGE CONTAINS THE WORD "Success" https://www.esp8266.com/viewtopic.php?f=34&t=4398 - server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ - AsyncWebServerResponse *response = request->beginResponse(200, "text/html", "ESP32 Captive Portal

This is a captive portal example. All requests will " - "be redirected here.

"); + server.on("/", HTTP_ANY, [](AsyncWebServerRequest *request){ + AsyncWebServerResponse *response = request->beginResponse(200, "text/html", index_html); response->addHeader("Cache-Control", "public,max-age=31536000"); request->send(response); - DEBUG_SERIAL.println("Served Basic HTML Page with 1 year Cache header"); + DEBUG_SERIAL.println("Served Basic HTML Page"); + }); server.onNotFound([](AsyncWebServerRequest *request){ - request->redirect("http://4.3.2.1/"); - DEBUG_SERIAL.print("server.onnotfound "); + request->redirect(localIPURL); + DEBUG_SERIAL.print("onnotfound "); DEBUG_SERIAL.print(request->host()); //This gives some insight into whatever was being requested on the serial monitor + DEBUG_SERIAL.print(" "); DEBUG_SERIAL.print(request->url()); - DEBUG_SERIAL.print(" sent redirect to http://4.3.2.1/\n"); + DEBUG_SERIAL.print(" sent redirect to " + localIPURL +"\n"); }); server.begin(); @@ -94,4 +123,5 @@ void setup(){ //the order of the code is really important and it is critical the void loop(){ dnsServer.processNextRequest(); + delay(1); } \ No newline at end of file