2

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.

  • 1. waitForConnectionResult probably doesn't handle errors like you want. 2. WL_CONNECT_FAILED means other things too, so wouldn't you just want to look for anything beside 'connected'? 3. The AP must use the same channel as the STA, so i don't see how this can keep an http connection open while/if that changes. – dandavis Oct 11 '17 at 11:26
  • @dandavis Thanks for replying. Firstly, waitForConnectResult is documented as to wait for the final result of the network and then return the connection state. Secondly, thank you for heads up on the other meanings of the WL_CONNECT_FAILED. I sort of asummed that it may have had some other meanings but now I know but in this case we're assuming the ssid is correct and only the password is wrong. Finally, the esp8266 has a WiFi mode called WIFI_AP_STA which allows the device to be an access point and a station, very handy if you want to do something like this so I don't think that is the cause. – Cam Oct 11 '17 at 20:42
  • yes, in 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. – dandavis Oct 11 '17 at 21:47
1
WifiMulti wifiMulti;//declare global.
wifiMulti.addAP(ssid,pass);//instead of WiFi.begin();
int i = 0;
//add below to wait for connection.
while (i < 20)
  {
    if (wifiMulti.run() == WL_CONNECTED)
    {
      return (20);
    }
    delay(500);
    Serial.println(WiFi.status());
    i++;
  }
0

Make the WiFi.begin outside the WebServer handler. In the handler store the ssid and password into variables and send a response. In loop() then make the WiFi.begin. For the result, pool from the browser with javascript.

Example

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.