I'm experimenting with the ESP8266 chip on a Wemos D1 R2 board. I'm trying to write some code which will allow the user to input a username and password in an HTML form then get a response as to what happened with trying to connect to the WiFi as either they connected or the password was wrong. After I've turned setup Access Point and Station mode on the device using:
// The field here would be global so other functions can access it
ESP8266WebServer server(80);
server.on("/connect", handleConnect);
server.begin();
In my handleConnect function, I check the body of the request and attempt to login:
if(!server.hasArg("ssid") || !server.hasArg("password")) {
server.send(200, "text/html", "You didn't submit a ssid and password");
return;
}
auto ssid = server.arg("ssid");
auto password = server.arg("password");
WiFi.begin(ssid, password);
auto status = WiFi.waitForConnectionResult();
server.send(200, "text/html", String(status));
When the user inputs the correct password, the function returns the request in time and the request responds with 3 (the connection was successful). However, if the password is wrong, the request times out. I've also tried several approaches to either work-around or fix the problem such as:
Using a while loop and calling
WiFi.status()
and checking it and responding accordingly. This approach ends with the same request timeout if the password is wrong. An example of this would be:while(true) { delay(1000); auto status = WiFi.status(); if(status == WL_CONNECTED) { server.send(200, "text/html", "You're connected!"); } if(status == WL_CONNECT_FAILED) { server.send(200, "text/html", "You inputted the wrong password! Try again!"); } }
Registering another resource to specifically only return what state the WiFi is in and in the original connect function to send back HTML with some javascript in it which calls this other resource and do the decision making of what text to display client-side but this approach always returns 0 (when the WiFi is in process of changing between statuses, quoted from the docs)
server.on("/checkConnection", checkConnection); // other code void checkConnection() { server.send(WiFi.status()); }
- And finally, I have experimented with using a public field to save the state once it has finished in the main function where the original connection tried to be established and then use the checkConnection function to return this state and this SOMEWHAT works, however, the code is messy, hacky and there must be a better way of doing this otherwise this will have to be my solution until the libraries are updated to fix this or something like that:
// public field for the status
int status = 0;
// other code
void handleConnect() {
// checking ssid and password
WiFi.begin(ssid, password);
// use an interval with AJAX or this to get the connection state
server.send(200, "text/html", "Go to <a href='/checkConnection'>to check the connection</a>");
while(true) {
delay(1000);
auto s = WiFi.status();
status = s;
if(s = WL_CONNECTED) break;
}
}
void checkConnection() {
server.send(200, "text/html", status);
}
Has anyone encountered this problem and if so, is there a better way of solving it apart from using a public variable which just makes it a pain in the bum to work with? Thank you.
WIFI_AP_STA
, the wifi channels must match between the two. if your AP booted a different channel than the STA you're connecting to, you (afaik) won't be able to keep an http connection open during the AP's (unexpected/undocumented) channel change, no matter the password validity.