Switching between AP and STA modes on Wifi ESP32

Hey!

HARDWARE:

  • ESP32 DEVKIT DOIT V1

I'm trying to create this functionality: My controller needs to try and connect to some WiFi's in STA mode at the beginning, then if it doesn't manage to do that, it boots up a website in AP mode, and every time someone puts something into the fields on the website, it starts STA mode and tries to reconnect again to that new one (and the old ones), if it doesn't manage to, it should boot up the website again! So on and so on. When it does manage to connect in STA mode, it should end AP mode so the AP is no longer visible. And then if it disconnects again, it should boot up AP mode.

TL;DR Boots in STA and checks predefined WiFi's, if none work changes to AP and waits for user input when it gets user input it tries to connect to the new SSID. This goes in a loop. When it's connected, if the router turns off, it should boot up AP mode again.

#include <WiFi.h>
#include <WiFiMulti.h>
#include <WebServer.h>

const char* ssid_ap = "SSID";
const char* password_ap = "PASS";

IPAddress local_ip(192, 168, 1, 1);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

WebServer server(80);
boolean connected = false;

WiFiMulti wifiMulti;
int connection_attempt = 0;

unsigned long previousMillis = 0;
const long interval = 10000;

void setup()
{
  Serial.begin(115200);
  delay(10);

  wifiMulti.addAP("RandomAP1, "pwd121212121");
  wifiMulti.addAP("RandomAP", "pwd31213122");

  if (wifiMulti.run() != WL_CONNECTED) {
    WiFi.softAP(ssid_ap, password_ap);
    WiFi.softAPConfig(local_ip, gateway, subnet);
    Serial.print("Connect to My access point: ");
    Serial.println(ssid_ap);

    server.on("/", handle_root);
    server.begin();
    Serial.println("HTTP server started");
  }
}

void loop()
{
  unsigned long currentMillis = millis();

  if (!connected) {
    server.handleClient();
  }
  
  if (WiFi.status() != WL_CONNECTED) {
    connected = false;
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      
    if (wifiMulti.run() != WL_CONNECTED) {
        WiFi.mode(WIFI_MODE_AP); //I BELIEVE THIS IS THE PROBLEM
        connection_attempt++;
        if (connection_attempt == 10) {
          wifiMulti.addAP("AndroidAP", "REDACTED");
        }
        if (connection_attempt == 20) {
          wifiMulti.addAP("TechnicolorDR", "REDACTED");
        }
        Serial.println("WiFi not connected!");
      }
    }
  }
  if (WiFi.status() == WL_CONNECTED) {
    if (!connected) {
      WiFi.mode(WIFI_MODE_STA); //I BELIEVE THIS IS THE PROBLEM
      Serial.println("WiFi has been connected!");
    }
    connected = true;
  }
}

void handle_root() {
  String HTML = "HTML BELOW";
  server.send(200, "text/html", HTML);
}

Huge HTML in a string in the code:

<!DOCTYPE HTML> \
<html> \
 \
<head> \
 <meta name=\"viewport\" http-equiv=\"content-type\" content=\"width = device-width, initial-scale = 1.0, maximum-scale = 1.0, user-scalable=0\"> \
  <title>WiFi Touch Lamp Setup</title> \
  <style> \
  body { \
    background-color: #0067B3; \
    font-family: Arial, Helvetica, Sans-Serif; \
    Color: #FFFFFF; \
  } \
  </style> \
</head> \
 \
<body> \
  <center> \
    <h1 style=\"color:#FFFFFF; font-family:verdana;font-family: verdana;padding-top: 10px;padding-bottom: 10px;font-size: 36px\\\">WiFi Touch Lamp</h1> \
    <h2 style=\"color:#FFFFFF;font-family: Verdana;font: caption;font-size: 27px;padding-top: 10px;padding-bottom: 10px;\\\">Type In Your WiFi Credentials</h2> \
    <FORM action=\"/\" method=\"post\"> \
      <div style=\"padding-left:100px;text-align:left;display:inline-block;min-width:150px;\"> \
        <a href=\"#pass\" onclick=\"c(this)\" style=\"text-align:left\"></a> \
      </div> \
      <div style=\"display:inline-block;min-width:260px;\"><span class=\"q\" style=\"text-align:right\"></span></div> \
      <P> \
        <label style=\"font-family:Times New Roman\">SSID</label> \
        
 \
        <input maxlength=\"30px\" id=\"ssid\" type=\"text\" name=\"ssid\" placeholder=\"Enter WiFi SSID\" style=\"width: 400px; padding: 5px 10px ; margin: 8px 0; border : 2px solid #3498db; border-radius: 4px; box-sizing:border-box\\\"> \
        
 </P> \
      <P> \
        <label style=\"font-family:Times New Roman\">PASSWORD</label> \
        
 \
        <input maxlength=\"30px\" type=\"text\" id=\"pass\" name=\"pass\" placeholder=\"Enter WiFi PASSWORD\" style=\"width: 400px; padding: 5px 10px ; margin: 8px 0; border : 2px solid #3498db; border-radius: 4px; box-sizing:border-box\"> \
        
 \
        <INPUT type=\"submit\"> \
        <INPUT type=\"reset\"> \
        <style> \
        input[type=\"reset\"] { \
          background-color: #3498DB; \
          border: none; \
          color: white; \
          padding: 15px 48px; \
          text-align: center; \
          text-decoration: none; \
          display: inline-block; \
          font-size: 16px; \
        } \
         \
        input[type=\"submit\"] { \
          background-color: #3498DB; \
          border: none; \
          color: white; \
          padding: 15px 48px; \
          text-align: center; \
          text-decoration: none; \
          display: inline-block; \
          font-size: 16px; \
        } \
        </style> \
    </FORM> \
    
 \
    <P> \
      <label style=\"font-family:Times New Roman\">SSID's:</label> \
      
 \
      <label style=\"font-family:Times New Roman\">ssid_test</label> \
    </P> \
    <script> \
    function c(l) { \
      document.getElementById('ssid').value = l.innerText || l.textContent; \
      document.getElementById('pass').focus(); \
    } \
    </script> \
  </center> \
</body> \
 \
</html>

The way it currently works is instead of adding a user inputted SSID and PASS, it adds them after 10 and 20 seconds respectively, so I could test out disconnecting one or the other

Bump.