From e81cd1f7f5291ee04d68b1b5fd1b711a5c0fc48c Mon Sep 17 00:00:00 2001 From: Nick Reynolds Date: Mon, 19 Sep 2022 17:38:10 +0100 Subject: [PATCH 1/3] Add captive portal functionality, update examples and documentation. --- README.md | 10 +++++++++ examples/gui-generic-api/gui-generic-api.ino | 2 +- examples/gui/gui.ino | 3 +-- examples/tabbedGui/tabbedGui.ino | 2 +- keywords.txt | 1 + src/ESPUI.cpp | 22 ++++++++++++++++++-- src/ESPUI.h | 1 + 7 files changed, 35 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9e5799e..04824ea 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ The Library runs on any kind of **ESP8266** and **ESP32** (NodeMCU, AI Thinker, * [Grouped controls](#grouped-controls) * [Wide controls](#wide-controls) * [Graph (Experimental)](#graph--experimental-) + * [Captive Portal](#captive-portal) - [Notes for Development](#notes-for-development) - [Contribute](#contribute) @@ -643,6 +644,15 @@ Graph points are saved in the browser in **localstorage** to be persistant, clea _There are many issues with the graph component currently and work is ongoing. Consider helping us out with development!_ +### Captive Portal + +You can set ESPUI to redirect all unknown URLs it is asked for to the 'root' the local HTTP server instead of responding with an HTTP code 404. This turns it into a simple 'captive portal'. Note you must also set up the ESP to be a DNS server that responds to all DNS requests with the IP address of the ESP for this to be effective and this is only useful when the ESP is acting as a WiFi hotspot in AP mode. All the example sketches will work as captive portals if not connected to a local WiFi network as a station. + +``` +ESPUI.captivePortal == true; +``` + + # Notes for Development If you want to work on the HTML/CSS/JS files, do make changes in the _data_ diff --git a/examples/gui-generic-api/gui-generic-api.ino b/examples/gui-generic-api/gui-generic-api.ino index 44f0119..9885bf8 100644 --- a/examples/gui-generic-api/gui-generic-api.ino +++ b/examples/gui-generic-api/gui-generic-api.ino @@ -199,7 +199,7 @@ void setup(void) if (WiFi.status() != WL_CONNECTED) { Serial.print("\n\nCreating hotspot"); - + ESPUI.captivePortal = true; //Configure ESPUI to be a captive portal only if the ESP is acting as a hotspot WiFi.mode(WIFI_AP); delay(100); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); diff --git a/examples/gui/gui.ino b/examples/gui/gui.ino index c7d390c..32f05c4 100644 --- a/examples/gui/gui.ino +++ b/examples/gui/gui.ino @@ -189,7 +189,7 @@ void setup(void) if (WiFi.status() != WL_CONNECTED) { Serial.print("\n\nCreating hotspot"); - + ESPUI.captivePortal = true; //Configure ESPUI to be a captive portal only if the ESP is acting as a hotspot WiFi.mode(WIFI_AP); delay(100); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); @@ -256,7 +256,6 @@ void setup(void) * since it is transmitted in cleartext. Just add a string as username and * password, for example begin("ESPUI Control", "username", "password") */ - ESPUI.begin("ESPUI Control"); } diff --git a/examples/tabbedGui/tabbedGui.ino b/examples/tabbedGui/tabbedGui.ino index b02ae4b..1cbd3d6 100644 --- a/examples/tabbedGui/tabbedGui.ino +++ b/examples/tabbedGui/tabbedGui.ino @@ -197,7 +197,7 @@ void setup(void) if (WiFi.status() != WL_CONNECTED) { Serial.print("\n\nCreating hotspot"); - + ESPUI.captivePortal = true; //Configure ESPUI to be a captive portal only if the ESP is acting as a hotspot WiFi.mode(WIFI_AP); delay(100); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); diff --git a/keywords.txt b/keywords.txt index 1ce2287..cb4ea35 100644 --- a/keywords.txt +++ b/keywords.txt @@ -25,6 +25,7 @@ beginLITTLEFS KEYWORD2 print KEYWORD2 updateSwitcher KEYWORD2 updateSlider KEYWORD2 +captivePortal KEYWORD2 ####################################### # Instances (KEYWORD2) diff --git a/src/ESPUI.cpp b/src/ESPUI.cpp index bacd91f..8dcd9d5 100644 --- a/src/ESPUI.cpp +++ b/src/ESPUI.cpp @@ -1351,7 +1351,16 @@ void ESPUIClass::beginLITTLEFS(const char* _title, const char* username, const c request->send(200, "text/plain", String(ESP.getFreeHeap()) + " In LITTLEFS mode"); }); - server->onNotFound([](AsyncWebServerRequest* request) { request->send(404); }); + server->onNotFound([this](AsyncWebServerRequest* request) { + if(captivePortal == true) + { + request->redirect("/"); + } + else + { + request->send(404); + } + }); server->begin(); @@ -1496,7 +1505,16 @@ void ESPUIClass::begin(const char* _title, const char* username, const char* pas request->send(200, "text/plain", String(ESP.getFreeHeap()) + " In Memorymode"); }); - server->onNotFound([](AsyncWebServerRequest* request) { request->send(404); }); + server->onNotFound([this](AsyncWebServerRequest* request) { + if(captivePortal == true) + { + request->redirect("/"); + } + else + { + request->send(404); + } + }); server->begin(); diff --git a/src/ESPUI.h b/src/ESPUI.h index 5016a83..6d9f0df 100644 --- a/src/ESPUI.h +++ b/src/ESPUI.h @@ -236,6 +236,7 @@ public: unsigned int jsonUpdateDocumentSize; unsigned int jsonInitialDocumentSize; bool sliderContinuous; + bool captivePortal = false; void setVerbosity(Verbosity verbosity); void begin(const char* _title, const char* username = nullptr, const char* password = nullptr, From 90ba90a717f3c779a81512a1c29ee12465ab620f Mon Sep 17 00:00:00 2001 From: Nick Reynolds Date: Tue, 20 Sep 2022 15:29:34 +0100 Subject: [PATCH 2/3] Make captive portal redirect on by default. --- src/ESPUI.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ESPUI.h b/src/ESPUI.h index 6d9f0df..668d02f 100644 --- a/src/ESPUI.h +++ b/src/ESPUI.h @@ -236,7 +236,7 @@ public: unsigned int jsonUpdateDocumentSize; unsigned int jsonInitialDocumentSize; bool sliderContinuous; - bool captivePortal = false; + bool captivePortal = true; void setVerbosity(Verbosity verbosity); void begin(const char* _title, const char* username = nullptr, const char* password = nullptr, From 79b9acf9f4f542c02d7caec168546088888ca597 Mon Sep 17 00:00:00 2001 From: Nick Reynolds Date: Wed, 21 Sep 2022 08:58:05 +0100 Subject: [PATCH 3/3] Changes per suggestions by maintainer (Lukas Bachschwell). --- README.md | 6 ++++-- examples/gui-generic-api/gui-generic-api.ino | 2 +- examples/gui/gui.ino | 2 +- examples/tabbedGui/tabbedGui.ino | 2 +- keywords.txt | 2 +- src/ESPUI.cpp | 4 ++-- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 04824ea..f4d5978 100644 --- a/README.md +++ b/README.md @@ -646,10 +646,12 @@ _There are many issues with the graph component currently and work is ongoing. C ### Captive Portal -You can set ESPUI to redirect all unknown URLs it is asked for to the 'root' the local HTTP server instead of responding with an HTTP code 404. This turns it into a simple 'captive portal'. Note you must also set up the ESP to be a DNS server that responds to all DNS requests with the IP address of the ESP for this to be effective and this is only useful when the ESP is acting as a WiFi hotspot in AP mode. All the example sketches will work as captive portals if not connected to a local WiFi network as a station. +ESPUI will redirect all unknown URLs it is asked for to the 'root' of the local HTTP server instead of responding with an HTTP code 404. This makes it act as a simple 'captive portal'. Note you must also set up the ESP to be a DNS server that responds to all DNS requests with the IP address of the ESP. This only effective when the ESP is acting as a WiFi hotspot in AP mode and assigning itself as the DNS server to connected clients. + +All the example sketches include the DNS related code and will work as captive portals when used as a hotspot. In the event you wish to disable this feature you can do so by removing the DNS server code and adding the code below. ``` -ESPUI.captivePortal == true; +ESPUI.captivePortal = false; ``` diff --git a/examples/gui-generic-api/gui-generic-api.ino b/examples/gui-generic-api/gui-generic-api.ino index 9885bf8..44f0119 100644 --- a/examples/gui-generic-api/gui-generic-api.ino +++ b/examples/gui-generic-api/gui-generic-api.ino @@ -199,7 +199,7 @@ void setup(void) if (WiFi.status() != WL_CONNECTED) { Serial.print("\n\nCreating hotspot"); - ESPUI.captivePortal = true; //Configure ESPUI to be a captive portal only if the ESP is acting as a hotspot + WiFi.mode(WIFI_AP); delay(100); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); diff --git a/examples/gui/gui.ino b/examples/gui/gui.ino index 32f05c4..2356fd6 100644 --- a/examples/gui/gui.ino +++ b/examples/gui/gui.ino @@ -189,7 +189,7 @@ void setup(void) if (WiFi.status() != WL_CONNECTED) { Serial.print("\n\nCreating hotspot"); - ESPUI.captivePortal = true; //Configure ESPUI to be a captive portal only if the ESP is acting as a hotspot + WiFi.mode(WIFI_AP); delay(100); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); diff --git a/examples/tabbedGui/tabbedGui.ino b/examples/tabbedGui/tabbedGui.ino index 1cbd3d6..b02ae4b 100644 --- a/examples/tabbedGui/tabbedGui.ino +++ b/examples/tabbedGui/tabbedGui.ino @@ -197,7 +197,7 @@ void setup(void) if (WiFi.status() != WL_CONNECTED) { Serial.print("\n\nCreating hotspot"); - ESPUI.captivePortal = true; //Configure ESPUI to be a captive portal only if the ESP is acting as a hotspot + WiFi.mode(WIFI_AP); delay(100); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); diff --git a/keywords.txt b/keywords.txt index cb4ea35..84cd7eb 100644 --- a/keywords.txt +++ b/keywords.txt @@ -25,7 +25,7 @@ beginLITTLEFS KEYWORD2 print KEYWORD2 updateSwitcher KEYWORD2 updateSlider KEYWORD2 -captivePortal KEYWORD2 +captivePortal LITERAL1 ####################################### # Instances (KEYWORD2) diff --git a/src/ESPUI.cpp b/src/ESPUI.cpp index 8dcd9d5..c6f3577 100644 --- a/src/ESPUI.cpp +++ b/src/ESPUI.cpp @@ -1352,7 +1352,7 @@ void ESPUIClass::beginLITTLEFS(const char* _title, const char* username, const c }); server->onNotFound([this](AsyncWebServerRequest* request) { - if(captivePortal == true) + if(captivePortal) { request->redirect("/"); } @@ -1506,7 +1506,7 @@ void ESPUIClass::begin(const char* _title, const char* username, const char* pas }); server->onNotFound([this](AsyncWebServerRequest* request) { - if(captivePortal == true) + if(captivePortal) { request->redirect("/"); }