Search code examples
arduinoesp8266nodemcuarduino-esp8266

Configure WiFi on ESP8266 uing WIFI_AP_STA mode


I am trying to program my NodeMCU (Lolin v3) board in such a way that I can use it to configure the WiFi settings without having to hard code the credentials. I know there is a WiFiManager Library, but I don't intend to use that since I need to do my own implementation, not use the UI that the library provides. The credentials provided by the user are stored in a file using SPIFFS, used to check whether to start the board in AP_STA mode or STA mode only.

Below is the logic I use:

void connectWiFi(String ssid, String password, boolean staOnly = false) {
  boolean state = true;
  int i = 0;
  if(staOnly)
    WiFi.mode(WIFI_STA);
  WiFi.begin(ssid.c_str(), password.c_str());
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    if (i > 10) {
      state = false;
      break;
    }
    i++;
  }
  return state;
}

void join() {
  String ssid = setupServer.arg("ssid");
  String password = setupServer.arg("password");
  result = connectWifi(ssid, password);
  if(result) {
    Serial.println("Connected");
    // **THIS IS THE PROBLEMATIC PART**
    setupServer.send(200, "text/plain", WiFi.localIP().toString());
    // save credentials to a file
    Serial.println("Conf saved");
    delay(2000);
    ESP.restart();
  } else
    setupServer.send(200, "text/plain", "fail");
  }

void setup() {
  Serial.begin(115200);
  WiFi.disconnect(true);
  boolean fileExists = SPIFFS.exists(WIFI_CONF_FILE);
  if(!fileExists) {
    WiFi.mode(WIFI_AP_STA);
    WiFi.softAP("AP", "password");
    IPAddress myIP = WiFi.softAPIP();
    setupServer = ESP8266WebServer(myIP, 8888);
    setupServer.on("/join", join);
    setupServer.begin();
  } else {
    // read file contents for ssid and password
    connectWifi(ssid, password, true);
    // do some work here
  }
}

void loop() {
  setupServer.handleClient();
}

So now when I do a fresh boot, the board enters AP_STA mode and starts with SSID AP. I connect to it and open http://192.169.4.1/join?ssid=mywifi&password=12345678 in the browser. Somehow the connection gets terminated and I get "Destination Unreachable" in my browser. But the serial monitor prints 'Connected' and 'Conf saved'.

I want to know why it isn't returning the success response to the browser. I need the localIP after it has connected to the WiFi. It returns the failed response correctly in case it fails. How can I ensure it will always return the IP address assigned to it back to the client that connected to it before restarting?

Any help is appreciated.

Thanks!


Solution

  • Looks like it is bound to happen as radio module is shared between two modes.

    Found the explaination for this issue here: https://github.com/esp8266/Arduino/issues/3282

    This is related to the fact that STA will switch to the channel of the AP it is trying to connect to, and SoftAP will have to switch to the same channel. So the client (PC or smartphone connected to the SoftAP) will have to reconnect to the SoftAP on its new channel. In most cases this causes TCP connections to be reset.