Cod*_*eat 7 c++ wifi access-point arduino-esp8266
例子:
我不知道你怎么称呼这个功能,所以我试着解释一下。例如,当您将手机连接到公共 WiFi 热点/接入点时,您会收到来自操作系统的消息,要求您接受条款/条件或您需要登录才能使用连接。当您单击此消息时,它会打开/a 浏览器并启动登录页面。
他们怎么做到的?这是 https 功能吗?
更新:(1)
它被称为俘虏门户:
强制门户技术强制网络上的 HTTP 客户端在正常使用 Internet 之前查看特殊网页(通常用于身份验证)。强制门户将 Web 浏览器转变为身份验证设备。这是通过拦截大多数数据包来完成的,无论地址或端口如何,直到用户打开浏览器并尝试访问网络。届时,浏览器将被重定向到可能需要身份验证和/或付款的网页,或者只是显示可接受的使用政策并要求用户同意。强制门户用于许多 Wi-Fi 热点,也可用于控制有线访问(例如公寓、酒店房间、商务中心、“开放式”以太网插孔)。
情况:
我想用 ESP(ESP32/ESP8266)做同样的事情,因为我开发了一个可以通过 WiFi 配置的设备。当用户连接到设备并且不必先打开浏览器、输入 IP 地址等时,这将是非常用户友好的。只需一条消息,用户可以点击它,就会启动一个主页。
在 AP 模式下,我打开了 DNS 并将所有内容重定向到主页,但这不是最佳解决方案(有时也不起作用)。为了让您了解我在做什么,这里有一些代码,我的库的一部分:
bool suStartAccessPointNetwork( String sSSIDNetworkName, String sSSIDPassword,
IPAddress sStaticIpAddress,
uint16_t iDnsPort = 0,
uint8_t iTries = 20,
uint16_t iDelay = 500
)
{
WiFi.disconnect();
suSetNetworkAccessPointMode();
delay( 1000 );
WiFi.softAPConfig( sStaticIpAddress,
sStaticIpAddress,
IPAddress( 255, 255, 255, 0 )
);
SU_WIFI_AP_ESTABLISHED = WiFi.softAP( sSSIDNetworkName.c_str(), sSSIDPassword.c_str() );
if( iDnsPort > 0 )
{
static SUDNSServer* pDnsServer = NULLPTR;
if( !pDnsServer )
{ pDnsServer = new SUDNSServer(); }
// modify TTL, default is 60 seconds
pDnsServer->setTTL(60);
// set which return code will be used for all other domains (e.g. sending
// ServerFailure instead of NonExistentDomain will reduce number of queries
// sent by clients)
// default is DNSReplyCode::NonExistentDomain
pDnsServer->setErrorReplyCode( DNSReplyCode::NoError );
pDnsServer->start( iDnsPort,
//SCDMS_MDNS_ACCESS_NAME,
"*",
sStaticIpAddress
);
Serial.print("DNS server started at " );
Serial.println( sStaticIpAddress );
suSetDnsServer( pDnsServer );
}
Serial.print("[AP]:");
bool bConnected = false;
if( iTries == 0 )
{ ++iTries; }
// Try to connect, give WiFi 10 seconds to launch a network as access point.
while( !(bConnected = suIsNetworkEstablished()) && (iTries--) )
{
Serial.print('.');
//Serial.print(WiFi.status());
delay(500);
}
if( bConnected )
{ SU_WIFI_AP_ESTABLISHED = bConnected; }
Serial.println( bConnected?" ((o))":" o?" );
return bConnected;
}
Run Code Online (Sandbox Code Playgroud)
题:
我怎样才能实现上面例子中描述的这样的功能?有任何想法吗?有可能吗?
更新 2:
@gre_gor 提出了我在知道服务名称后也发现的相同示例(另请参见更新 1)。像示例中那样实现 Url 路径等,但不能按上述方式工作。好的,尝试了完整示例,结果相同,没有操作系统弹出窗口/消息,没有重定向。在浏览器中输入 IP 地址,这是有效的,但是我已经有了。
我尝试过的扩展演示之一:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <ESP8266mDNS.h>
#include <EEPROM.h>
/*
This example serves a "hello world" on a WLAN and a SoftAP at the same time.
The SoftAP allow you to configure WLAN parameters at run time. They are not setup in the sketch but saved on EEPROM.
Connect your computer or cell phone to wifi network ESP_ap with password 12345678. A popup may appear and it allow you to go to WLAN config. If it does not then navigate to http://192.168.4.1/wifi and config it there.
Then wait for the module to connect to your wifi and take note of the WLAN IP it got. Then you can disconnect from ESP_ap and return to your regular WLAN.
Now the ESP8266 is in your network. You can reach it through http://192.168.x.x/ (the IP you took note of) or maybe at http://esp8266.local too.
This is a captive portal because through the softAP it will redirect any http request to http://192.168.4.1/
*/
/* Set these to your desired softAP credentials. They are not configurable at runtime */
#ifndef APSSID
#define APSSID "ESP_ap"
#define APPSK "12345678"
#endif
const char *softAP_ssid = APSSID;
const char *softAP_password = APPSK;
/* hostname for mDNS. Should work at least on windows. Try http://esp8266.local */
const char *myHostname = "esp8266";
/* Don't set this wifi credentials. They are configurated at runtime and stored on EEPROM */
char ssid[32] = "";
char password[32] = "";
// DNS server
const byte DNS_PORT = 53;
DNSServer dnsServer;
// Web server
ESP8266WebServer server(80);
/* Soft AP network parameters */
IPAddress apIP(192, 168, 4, 1);
IPAddress netMsk(255, 255, 255, 0);
/** Should I connect to WLAN asap? */
boolean connect;
/** Last time I tried to connect to WLAN */
unsigned long lastConnectTry = 0;
/** Current WLAN status */
unsigned int status = WL_IDLE_STATUS;
/** Is this an IP? */
boolean isIp(String str) {
for (size_t i = 0; i < str.length(); i++) {
int c = str.charAt(i);
if (c != '.' && (c < '0' || c > '9')) {
return false;
}
}
return true;
}
/** IP to String? */
String toStringIp(IPAddress ip) {
String res = "";
for (int i = 0; i < 3; i++) {
res += String((ip >> (8 * i)) & 0xFF) + ".";
}
res += String(((ip >> 8 * 3)) & 0xFF);
return res;
}
/** Load WLAN credentials from EEPROM */
void loadCredentials() {
EEPROM.begin(512);
EEPROM.get(0, ssid);
EEPROM.get(0 + sizeof(ssid), password);
char ok[2 + 1];
EEPROM.get(0 + sizeof(ssid) + sizeof(password), ok);
EEPROM.end();
if (String(ok) != String("OK")) {
ssid[0] = 0;
password[0] = 0;
}
Serial.println("Recovered credentials:");
Serial.println(ssid);
Serial.println(strlen(password) > 0 ? "********" : "<no password>");
}
/** Store WLAN credentials to EEPROM */
void saveCredentials() {
EEPROM.begin(512);
EEPROM.put(0, ssid);
EEPROM.put(0 + sizeof(ssid), password);
char ok[2 + 1] = "OK";
EEPROM.put(0 + sizeof(ssid) + sizeof(password), ok);
EEPROM.commit();
EEPROM.end();
}
/** Handle root or redirect to captive portal */
void handleRoot() {
if (captivePortal()) { // If caprive portal redirect instead of displaying the page.
return;
}
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
String Page;
Page += F(
"<html><head></head><body>"
"<h1>HELLO WORLD!!</h1>");
if (server.client().localIP() == apIP) {
Page += String(F("<p>You are connected through the soft AP: ")) + softAP_ssid + F("</p>");
} else {
Page += String(F("<p>You are connected through the wifi network: ")) + ssid + F("</p>");
}
Page += F(
"<p>You may want to <a href='/wifi'>config the wifi connection</a>.</p>"
"</body></html>");
server.send(200, "text/html", Page);
}
/** Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */
boolean captivePortal() {
if (!isIp(server.hostHeader()) && server.hostHeader() != (String(myHostname) + ".local")) {
Serial.println("Request redirected to captive portal");
server.sendHeader("Location", String("http://") + toStringIp(server.client().localIP()), true);
server.send(302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
server.client().stop(); // Stop is needed because we sent no content length
return true;
}
return false;
}
/** Wifi config page handler */
void handleWifi() {
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
String Page;
Page += F(
"<html><head></head><body>"
"<h1>Wifi config</h1>");
if (server.client().localIP() == apIP) {
Page += String(F("<p>You are connected through the soft AP: ")) + softAP_ssid + F("</p>");
} else {
Page += String(F("<p>You are connected through the wifi network: ")) + ssid + F("</p>");
}
Page +=
String(F(
"\r\n<br />"
"<table><tr><th align='left'>SoftAP config</th></tr>"
"<tr><td>SSID ")) +
String(softAP_ssid) +
F("</td></tr>"
"<tr><td>IP ") +
toStringIp(WiFi.softAPIP()) +
F("</td></tr>"
"</table>"
"\r\n<br />"
"<table><tr><th align='left'>WLAN config</th></tr>"
"<tr><td>SSID ") +
String(ssid) +
F("</td></tr>"
"<tr><td>IP ") +
toStringIp(WiFi.localIP()) +
F("</td></tr>"
"</table>"
"\r\n<br />"
"<table><tr><th align='left'>WLAN list (refresh if any missing)</th></tr>");
Serial.println("scan start");
int n = WiFi.scanNetworks();
Serial.println("scan done");
if (n > 0) {
for (int i = 0; i < n; i++) {
Page += String(F("\r\n<tr><td>SSID ")) + WiFi.SSID(i) + ((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? F(" ") : F(" *")) + F(" (") + WiFi.RSSI(i) + F(")</td></tr>");
}
} else {
Page += F("<tr><td>No WLAN found</td></tr>");
}
Page += F(
"</table>"
"\r\n<br /><form method='POST' action='wifisave'><h4>Connect to network:</h4>"
"<input type='text' placeholder='network' name='n'/>"
"<br /><input type='password' placeholder='password' name='p'/>"
"<br /><input type='submit' value='Connect/Disconnect'/></form>"
"<p>You may want to <a href='/'>return to the home page</a>.</p>"
"</body></html>");
server.send(200, "text/html", Page);
server.client().stop(); // Stop is needed because we sent no content length
}
/** Handle the WLAN save form and redirect to WLAN config page again */
void handleWifiSave() {
Serial.println("wifi save");
server.arg("n").toCharArray(ssid, sizeof(ssid) - 1);
server.arg("p").toCharArray(password, sizeof(password) - 1);
server.sendHeader("Location", "wifi", true);
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
server.send(302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
server.client().stop(); // Stop is needed because we sent no content length
saveCredentials();
connect = strlen(ssid) > 0; // Request WLAN connect with new credentials if there is a SSID
}
void handleNotFound() {
if (captivePortal()) { // If caprive portal redirect instead of displaying the error page.
return;
}
String message = F("File Not Found\n\n");
message += F("URI: ");
message += server.uri();
message += F("\nMethod: ");
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += F("\nArguments: ");
message += server.args();
message += F("\n");
for (uint8_t i = 0; i < server.args(); i++) {
message += String(F(" ")) + server.argName(i) + F(": ") + server.arg(i) + F("\n");
}
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
server.send(404, "text/plain", message);
}
void setup() {
delay(1000);
Serial.begin(9600);
Serial.println();
Serial.println("Configuring access point...");
/* You can remove the password parameter if you want the AP to be open. */
WiFi.softAPConfig(apIP, apIP, netMsk);
WiFi.softAP(softAP_ssid, softAP_password);
delay(500); // Without delay I've seen the IP address blank
Serial.print("AP IP address: ");
Serial.println(WiFi.softAPIP());
/* Setup the DNS server redirecting all the domains to the apIP */
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
dnsServer.start(DNS_PORT, "*", apIP);
/* Setup web pages: root, wifi config pages, SO captive portal detectors and not found. */
server.on("/", handleRoot);
server.on("/wifi", handleWifi);
server.on("/wifisave", handleWifiSave);
server.on("/generate_204", handleRoot); //Android captive portal. Maybe not needed. Might be handled by notFound handler.
server.on("/fwlink", handleRoot); //Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
server.onNotFound(handleNotFound);
server.begin(); // Web server start
Serial.println("HTTP server started");
loadCredentials(); // Load WLAN credentials from network
connect = strlen(ssid) > 0; // Request WLAN connect if there is a SSID
}
void connectWifi() {
Serial.println("Connecting as wifi client...");
WiFi.disconnect();
WiFi.begin(ssid, password);
int connRes = WiFi.waitForConnectResult();
Serial.print("connRes: ");
Serial.println(connRes);
}
void loop() {
if (connect) {
Serial.println("Connect requested");
connect = false;
connectWifi();
lastConnectTry = millis();
}
{
unsigned int s = WiFi.status();
if (s == 0 && millis() > (lastConnectTry + 60000)) {
/* If WLAN disconnected and idle try to connect */
/* Don't set retry time too low as retry interfere the softAP operation */
connect = true;
}
if (status != s) { // WLAN status change
Serial.print("Status: ");
Serial.println(s);
status = s;
if (s == WL_CONNECTED) {
/* Just connected to WLAN */
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Setup MDNS responder
if (!MDNS.begin(myHostname)) {
Serial.println("Error setting up MDNS responder!");
} else {
Serial.println("mDNS responder started");
// Add service to MDNS-SD
MDNS.addService("http", "tcp", 80);
}
} else if (s == WL_NO_SSID_AVAIL) {
WiFi.disconnect();
}
}
if (s == WL_CONNECTED) {
MDNS.update();
}
}
// Do work:
//DNS
dnsServer.processNextRequest();
//HTTP
server.handleClient();
}
Run Code Online (Sandbox Code Playgroud)
发现这个:https : //www.esp8266.com/viewtopic.php?f=6&t=15993
eduperez 的这篇文章:
“Android 设备具有硬编码的 Google DNS,它们将始终使用 8.8.8.8和 8.8.4.4,尽管 DHPC 服务器可能会告诉它们使用什么。您需要配置网关以将所有传出流量重定向到端口 53 到您的域名系统。”
这给出了想法,使用8.8.8.8 作为 IP-address 和 DNS-server address。多田!奇迹般有效!
所以这个草图会起作用:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <ESP8266mDNS.h>
#include <EEPROM.h>
/*
This example serves a "hello world" on a WLAN and a SoftAP at the same time.
The SoftAP allow you to configure WLAN parameters at run time. They are not setup in the sketch but saved on EEPROM.
Connect your computer or cell phone to wifi network ESP_ap with password 12345678. A popup may appear and it allow you to go to WLAN config. If it does not then navigate to http://192.168.4.1/wifi and config it there.
Then wait for the module to connect to your wifi and take note of the WLAN IP it got. Then you can disconnect from ESP_ap and return to your regular WLAN.
Now the ESP8266 is in your network. You can reach it through http://192.168.x.x/ (the IP you took note of) or maybe at http://esp8266.local too.
This is a captive portal because through the softAP it will redirect any http request to http://192.168.4.1/
*/
/* Set these to your desired softAP credentials. They are not configurable at runtime */
#ifndef APSSID
#define APSSID "TheGeekMan"
#define APPSK "12345678"
#endif
const char *softAP_ssid = APSSID;
const char *softAP_password = APPSK;
/* hostname for mDNS. Should work at least on windows. Try http://esp8266.local */
const char *myHostname = "thegeekman";
/* Don't set this wifi credentials. They are configurated at runtime and stored on EEPROM */
char ssid[32] = "";
char password[32] = "";
// DNS server
const byte DNS_PORT = 53;
DNSServer dnsServer;
// Web server
ESP8266WebServer server(80);
/* Soft AP network parameters */
//IPAddress apIP(192, 168, 4, 1);
IPAddress apIP(8, 8, 8, 8);
IPAddress netMsk(255, 255, 255, 0);
/** Should I connect to WLAN asap? */
boolean connect;
/** Last time I tried to connect to WLAN */
unsigned long lastConnectTry = 0;
/** Current WLAN status */
unsigned int status = WL_IDLE_STATUS;
/** Is this an IP? */
boolean isIp(String str) {
for (size_t i = 0; i < str.length(); i++) {
int c = str.charAt(i);
if (c != '.' && (c < '0' || c > '9')) {
return false;
}
}
return true;
}
/** IP to String? */
String toStringIp(IPAddress ip) {
String res = "";
for (int i = 0; i < 3; i++) {
res += String((ip >> (8 * i)) & 0xFF) + ".";
}
res += String(((ip >> 8 * 3)) & 0xFF);
return res;
}
/** Load WLAN credentials from EEPROM */
void loadCredentials() {
EEPROM.begin(512);
EEPROM.get(0, ssid);
EEPROM.get(0 + sizeof(ssid), password);
char ok[2 + 1];
EEPROM.get(0 + sizeof(ssid) + sizeof(password), ok);
EEPROM.end();
if (String(ok) != String("OK")) {
ssid[0] = 0;
password[0] = 0;
}
Serial.println("Recovered credentials:");
Serial.println(ssid);
Serial.println(strlen(password) > 0 ? "********" : "<no password>");
}
/** Store WLAN credentials to EEPROM */
void saveCredentials() {
EEPROM.begin(512);
EEPROM.put(0, ssid);
EEPROM.put(0 + sizeof(ssid), password);
char ok[2 + 1] = "OK";
EEPROM.put(0 + sizeof(ssid) + sizeof(password), ok);
EEPROM.commit();
EEPROM.end();
}
/** Handle root or redirect to captive portal */
void handleRoot() {
if (captivePortal()) { // If caprive portal redirect instead of displaying the page.
return;
}
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
String Page;
Page += F(
"<html><head></head><body>"
"<h1>HELLO WORLD!!</h1>");
if (server.client().localIP() == apIP) {
Page += String(F("<p>You are connected through the soft AP: ")) + softAP_ssid + F("</p>");
} else {
Page += String(F("<p>You are connected through the wifi network: ")) + ssid + F("</p>");
}
Page += F(
"<p>You may want to <a href='/wifi'>config the wifi connection</a>.</p>"
"</body></html>");
server.send(200, "text/html", Page);
}
/** Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */
boolean captivePortal() {
if (!isIp(server.hostHeader()) && server.hostHeader() != (String(myHostname) + ".local")) {
Serial.println("Request redirected to captive portal");
server.sendHeader("Location", String("http://") + toStringIp(server.client().localIP()), true);
server.send(302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
server.client().stop(); // Stop is needed because we sent no content length
return true;
}
return false;
}
/** Wifi config page handler */
void handleWifi() {
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
String Page;
Page += F(
"<html><head></head><body>"
"<h1>Wifi config</h1>");
if (server.client().localIP() == apIP) {
Page += String(F("<p>You are connected through the soft AP: ")) + softAP_ssid + F("</p>");
} else {
Page += String(F("<p>You are connected through the wifi network: ")) + ssid + F("</p>");
}
Page +=
String(F(
"\r\n<br />"
"<table><tr><th align='left'>SoftAP config</th></tr>"
"<tr><td>SSID ")) +
String(softAP_ssid) +
F("</td></tr>"
"<tr><td>IP ") +
toStringIp(WiFi.softAPIP()) +
F("</td></tr>"
"</table>"
"\r\n<br />"
"<table><tr><th align='left'>WLAN config</th></tr>"
"<tr><td>SSID ") +
String(ssid) +
F("</td></tr>"
"<tr><td>IP ") +
toStringIp(WiFi.localIP()) +
F("</td></tr>"
"</table>"
"\r\n<br />"
"<table><tr><th align='left'>WLAN list (refresh if any missing)</th></tr>");
Serial.println("scan start");
int n = WiFi.scanNetworks();
Serial.println("scan done");
if (n > 0) {
for (int i = 0; i < n; i++) {
Page += String(F("\r\n<tr><td>SSID ")) + WiFi.SSID(i) + ((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? F(" ") : F(" *")) + F(" (") + WiFi.RSSI(i) + F(")</td></tr>");
}
} else {
Page += F("<tr><td>No WLAN found</td></tr>");
}
Page += F(
"</table>"
"\r\n<br /><form method='POST' action='wifisave'><h4>Connect to network:</h4>"
"<input type='text' placeholder='network' name='n'/>"
"<br /><input type='password' placeholder='password' name='p'/>"
"<br /><input type='submit' value='Connect/Disconnect'/></form>"
"<p>You may want to <a href='/'>return to the home page</a>.</p>"
"</body></html>");
server.send(200, "text/html", Page);
server.client().stop(); // Stop is needed because we sent no content length
}
/** Handle the WLAN save form and redirect to WLAN config page again */
void handleWifiSave() {
Serial.println("wifi save");
server.arg("n").toCharArray(ssid, sizeof(ssid) - 1);
server.arg("p").toCharArray(password, sizeof(password) - 1);
server.sendHeader("Location", "wifi", true);
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
server.send(302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
server.client().stop(); // Stop is needed because we sent no content length
saveCredentials();
connect = strlen(ssid) > 0; // Request WLAN connect with new credentials if there is a SSID
}
void handleNotFound() {
if (captivePortal()) { // If caprive portal redirect instead of displaying the error page.
return;
}
String message = F("File Not Found\n\n");
message += F("URI: ");
message += server.uri();
message += F("\nMethod: ");
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += F("\nArguments: ");
message += server.args();
message += F("\n");
for (uint8_t i = 0; i < server.args(); i++) {
message += String(F(" ")) + server.argName(i) + F(": ") + server.arg(i) + F("\n");
}
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
server.send(404, "text/plain", message);
}
void setup() {
delay(1000);
Serial.begin(9600);
Serial.println();
Serial.println("Configuring access point...");
/* You can remove the password parameter if you want the AP to be open. */
WiFi.softAPConfig(apIP, apIP, netMsk);
WiFi.softAP(softAP_ssid, softAP_password);
delay(500); // Without delay I've seen the IP address blank
Serial.print("AP IP address: ");
Serial.println(WiFi.softAPIP());
/* Setup the DNS server redirecting all the domains to the apIP */
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
dnsServer.start(DNS_PORT, "*", apIP);
/* Setup web pages: root, wifi config pages, SO captive portal detectors and not found. */
server.on("/", handleRoot);
server.on("/wifi", handleWifi);
server.on("/wifisave", handleWifiSave);
server.on("/generate_204", handleRoot); //Android captive portal. Maybe not needed. Might be handled by notFound handler.
server.on("/fwlink", handleRoot); //Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
server.onNotFound(handleNotFound);
server.begin(); // Web server start
Serial.println("HTTP server started");
loadCredentials(); // Load WLAN credentials from network
connect = strlen(ssid) > 0; // Request WLAN connect if there is a SSID
}
void connectWifi() {
Serial.println("Connecting as wifi client...");
WiFi.disconnect();
WiFi.begin(ssid, password);
int connRes = WiFi.waitForConnectResult();
Serial.print("connRes: ");
Serial.println(connRes);
}
void loop() {
if (connect) {
Serial.println("Connect requested");
connect = false;
connectWifi();
lastConnectTry = millis();
}
{
unsigned int s = WiFi.status();
if (s == 0 && millis() > (lastConnectTry + 60000)) {
/* If WLAN disconnected and idle try to connect */
/* Don't set retry time too low as retry interfere the softAP operation */
connect = true;
}
if (status != s) { // WLAN status change
Serial.print("Status: ");
Serial.println(s);
status = s;
if (s == WL_CONNECTED) {
/* Just connected to WLAN */
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Setup MDNS responder
if (!MDNS.begin(myHostname)) {
Serial.println("Error setting up MDNS responder!");
} else {
Serial.println("mDNS responder started");
// Add service to MDNS-SD
MDNS.addService("http", "tcp", 80);
}
} else if (s == WL_NO_SSID_AVAIL) {
WiFi.disconnect();
}
}
if (s == WL_CONNECTED) {
MDNS.update();
}
}
// Do work:
//DNS
dnsServer.processNextRequest();
//HTTP
server.handleClient();
}
Run Code Online (Sandbox Code Playgroud)