Search code examples
arduinoesp8266esp32arduino-c++arduino-esp32

ESP32 WiFi MODE_STM_AP. Dynamically change WiFi Station via Webinterface


Hello dear Stackoverflow Community,

I have the following problem. The project I am working on looks like this.

  1. ESP32 with AsyncWebserver and LittleFS
  2. ESP32 builds a soft AP at system startup (MODE_APSTA) including the STM (Station Mode function).
  3. the web interface can be used to search for networks within range. Once you have decided on a network, select it in the web interface and enter the corresponding password for the SSID.
  4. the password is sent to the ESP32 web server via Ajax GET request.
  5. the webserver saves the data in config files and restarts. If the ESP recognizes at startup that the config files are available, it should read the SSID and the password from there and connect to the network.
  6. the soft AP from the ESP should remain in place and usable.

Now to the problem: The ESP restarts, finds the files and should connect to the access point. But it does not. I have no idea where the problem is. I despair already for 2 days.

About the competent advice of this community I would be very grateful :)

#include <FS.h>
#include <LittleFS.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <WiFiMulti.h>

const char* soft_ap_ssid = "WeiFeiFugger";
const char* soft_ap_password = "1234567890";
DynamicJsonDocument output(1024);
String ap_config;
String pass_config;
AsyncWebServer server(80);
WiFiMulti wifiMulti;

void WiFiEvent(WiFiEvent_t event) {
  Serial.printf("[WiFi-event] event: %d\n", event);

  switch (event) {
    case SYSTEM_EVENT_WIFI_READY: 
      Serial.println("WiFi interface ready");
      break;
    case SYSTEM_EVENT_SCAN_DONE:
      Serial.println("Completed scan for access points");
      break;
    case SYSTEM_EVENT_STA_START:
      Serial.println("WiFi client started");
      break;
    case SYSTEM_EVENT_STA_STOP:
      Serial.println("WiFi clients stopped");
      break;
    case SYSTEM_EVENT_STA_CONNECTED:
      Serial.println("Connected to access point");
      break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
      Serial.println("Disconnected from WiFi access point");
      break;
    case SYSTEM_EVENT_STA_AUTHMODE_CHANGE:
      Serial.println("Authentication mode of access point has changed");
      break;
    case SYSTEM_EVENT_STA_GOT_IP:
      Serial.print("Obtained IP address: ");
      Serial.println(WiFi.localIP());
      break;
    case SYSTEM_EVENT_STA_LOST_IP:
      Serial.println("Lost IP address and IP address is reset to 0");
      break;
    case SYSTEM_EVENT_STA_WPS_ER_SUCCESS:
      Serial.println("WiFi Protected Setup (WPS): succeeded in enrollee mode");
      break;
    case SYSTEM_EVENT_STA_WPS_ER_FAILED:
      Serial.println("WiFi Protected Setup (WPS): failed in enrollee mode");
      break;
    case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT:
      Serial.println("WiFi Protected Setup (WPS): timeout in enrollee mode");
      break;
    case SYSTEM_EVENT_STA_WPS_ER_PIN:
      Serial.println("WiFi Protected Setup (WPS): pin code in enrollee mode");
      break;
    case SYSTEM_EVENT_AP_START:
      Serial.println("WiFi access point started");
      break;
    case SYSTEM_EVENT_AP_STOP:
      Serial.println("WiFi access point  stopped");
      break;
    case SYSTEM_EVENT_AP_STACONNECTED:
      Serial.println("Client connected");
      break;
    case SYSTEM_EVENT_AP_STADISCONNECTED:
      Serial.println("Client disconnected");
      break;
    case SYSTEM_EVENT_AP_STAIPASSIGNED:
      Serial.println("Assigned IP address to client");
      break;
    case SYSTEM_EVENT_AP_PROBEREQRECVED:
      Serial.println("Received probe request");
      break;
    case SYSTEM_EVENT_GOT_IP6:
      Serial.println("IPv6 is preferred");
      break;
    case SYSTEM_EVENT_ETH_START:
      Serial.println("Ethernet started");
      break;
    case SYSTEM_EVENT_ETH_STOP:
      Serial.println("Ethernet stopped");
      break;
    case SYSTEM_EVENT_ETH_CONNECTED:
      Serial.println("Ethernet connected");
      break;
    case SYSTEM_EVENT_ETH_DISCONNECTED:
      Serial.println("Ethernet disconnected");
      break;
    case SYSTEM_EVENT_ETH_GOT_IP:
      Serial.println("Obtained IP address");
      break;
    default: break;
}}

void WiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(IPAddress(info.got_ip.ip_info.ip.addr));
}

 
void setup(){

  Serial.begin(115200);

  WiFi.onEvent(WiFiEvent);
  
  WiFi.mode(WIFI_MODE_APSTA);
  WiFi.softAP(soft_ap_ssid, soft_ap_password);
  // Initialize LittleFS
  if(!LittleFS.begin()){
    Serial.println("An Error has occurred while mounting LittleFS");
    return;
  }


  if (LittleFS.exists("/connect_ap.txt") && LittleFS.exists("/connect_pass.txt")){
    Serial.println("AP Settings files exist");
    File apfile = LittleFS.open("/connect_ap.txt", "r");
    while(apfile.available()){
     ap_config = apfile.readString();
    }   
    apfile.close();
    File passfile = LittleFS.open("/connect_pass.txt", "r");
    while(passfile.available()){
     pass_config = passfile.readString();
    }   
    passfile.close();
    LittleFS.remove("/connect_pass.txt");
    LittleFS.remove("/connect_ap.txt");
    ap_config.replace(' ', NULL);
    pass_config.replace(' ', NULL);
    Serial.println(ap_config + " " + pass_config);
    wifiMulti.addAP(ap_config.c_str(), pass_config.c_str());
    if(wifiMulti.run() == WL_CONNECTED) {
        Serial.println("");
        Serial.println("WiFi connected");
        Serial.println("IP address: ");
        Serial.println(WiFi.localIP());
    }
    //WiFi.begin(ap_config.c_str(), pass_config.c_str());  
  }else{
    Serial.println("AP Setting files do not exist");
  }
  //WiFi.mode(WIFI_MODE_APSTA);
  //WiFi.softAP(soft_ap_ssid, soft_ap_password);
  //WiFi.begin();
  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(LittleFS, "/index.html", String(), false);
  });
  // Route for root / web page
  server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(LittleFS, "/favicon.ico", "image/x-icon");
  });  
  // Route to load bootstrap.css file
  server.on("/bootstrap.css", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(LittleFS, "/bootstrap.css", "text/css");
  });
  // Route to load bootstrap.js file
  server.on("/bootstrap.js", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(LittleFS, "/bootstrap.js", "text/javascript");
  });
  // Route to load jquery.js file
  server.on("/jquery.js", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(LittleFS, "/jquery.js", "text/javascript");
  });
  // Route to load styles.css file
  server.on("/styles.css", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(LittleFS, "/styles.css", "text/css");
  });
  server.on("/connectionInfo", HTTP_GET, [](AsyncWebServerRequest *request){
    String connectionInfo;
    connectionInfo = WiFi.status();
    request->send(200, "text/plain", connectionInfo);
  });
  server.on("/reboot", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", "Rebooting");
    ESP.restart();
  });
  // Route to set scan Networks
  server.on("/scanNetwork", HTTP_GET, [](AsyncWebServerRequest *request){
  String jsonOut = "{'accesspoints': [";
  int n = WiFi.scanNetworks();
  Serial.println("scan done");
  if (n == 0) {
      Serial.println("no networks found");
  } else {
    Serial.print(n);
    Serial.println(" networks found");
    for (int i = 0; i < n; ++i) {
      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print(WiFi.SSID(i));
      Serial.print(" (");
      Serial.print(WiFi.RSSI(i));
      Serial.print(")");
      Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN)?" [UNSECURED] ":" [SECURED] ");
      jsonOut += "{'ssid':'" + WiFi.SSID(i) + "', 'rssi':'" + WiFi.RSSI(i) + "', 'encryption':'" + ((WiFi.encryptionType(i) == WIFI_AUTH_OPEN)?"UNSECURED":"SECURED") + "'},"; 
      delay(10);
      
    }
  }
    jsonOut += "]}";
    Serial.println(jsonOut);
    request->send(200, "text/plain", jsonOut); 
  });

  // Route to connect to AP and scan network
  server.on("/connectAP", HTTP_GET, [](AsyncWebServerRequest *request){
    int paramsNr = request->params();
    Serial.println(paramsNr);
 
    String ssid_param = request->getParam("ssid")->value();
    String encryption_param = request->getParam("encryption")->value();
    String password_param = request->getParam("password")->value();
    Serial.println(ssid_param);
    Serial.println(encryption_param);
    Serial.println(password_param);
    File apfile = LittleFS.open("/connect_ap.txt", "w");
    apfile.print(ssid_param.c_str());
    delay(1);
    apfile.close();
    File passfile = LittleFS.open("/connect_pass.txt", "w");
    passfile.print(password_param.c_str());
    delay(1);
    passfile.close();
    //WiFi.disconnect();
    // Connect to Wi-Fi
    //WiFi.begin(ssid_param.c_str(), password_param.c_str());
    //if(password_param = ""){
    //  WiFi.begin(ssid_param.c_str());
    //}else{
    //  WiFi.begin(ssid_param.c_str(), password_param.c_str());      
    //}
    //IPAddress ip_recieved = WiFi.localIP();
    request->send(200, "text/plain", "Rebooting");//String(WiFi.localIP()
    delay(2000);
    ESP.restart();
  });
  

  // Start server
  server.begin();
}
 
void loop(){

}

Solution

  • SOLVED. It was an issue with the credential parsing in line "ap_config.replace(' ', NULL);". It deleted everything. So there was no AP SSID specified.