ESP85266 AP/STA mode

Ich habe versucht einen AP/STA mode so zu programieren das ich ein Capture Portal und gleichzeitigs Auto WPS benutzen kann aber ich bekomme es nicht hin.
ich würde gerne beides berei stellen können.
endweder man verbindet sich mit dem Capture Portal oder man drückt die WPS Taste am router.

Mein Code:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <EEPROM.h>

// ==== AP/Captive Portal ====
const IPAddress apIP(192, 168, 1, 1);
const char* apSSID = "ESP8266 SETUP";
DNSServer dnsServer;
ESP8266WebServer server(80);

// ==== WiFi Credentials ====
char cfgssid[64];
char cfgpassword[64];

// ==== WPS und Config ====
bool wpsActive = false;
bool configMode = true; // Konfigurationsmodus aktiv

// ==== UI/Scan State ====
String ssidList;

// ============================ Hilfsfunktionen ============================
void saveWiFiCredentials(const String& ssid, const String& psk) {
  int i = 0;
  for (i = 0; i < 256; ++i) {
    char c = (i < (int)ssid.length()) ? ssid[i] : 0;
    EEPROM.write(i, c);
    if (!c) break;
  }
  for (i = 0; i < 256; ++i) {
    char c = (i < (int)psk.length()) ? psk[i] : 0;
    EEPROM.write(256 + i, c);
    if (!c) break;
  }
  EEPROM.commit();
}

void loadWiFiCredentials() {
  int i = 0;
  for (i = 0; i < 256; ++i) {
    char c = (char)EEPROM.read(i);
    if (c == 0) break;
    if (i < (int)sizeof(cfgssid) - 1) cfgssid[i] = c;
  }
  cfgssid[min(i, (int)sizeof(cfgssid) - 1)] = 0;

  for (i = 0; i < 256; ++i) {
    char c = (char)EEPROM.read(i + 256);
    if (c == 0) break;
    if (i < (int)sizeof(cfgpassword) - 1) cfgpassword[i] = c;
  }
  cfgpassword[min(i, (int)sizeof(cfgpassword) - 1)] = 0;
}

void buildSsidList() {
  ssidList = "";
  Serial.println("Scanne verfügbare WiFi-Netzwerke...");
  
  // WiFi-Scan im AP_STA Modus
  int n = WiFi.scanNetworks();
  Serial.print("Gefundene Netzwerke: "); Serial.println(n);
  
  if (n == 0) {
    ssidList = "<option value=\"\">Keine Netzwerke gefunden</option>";
  } else {
    for (int i = 0; i < n; ++i) {
      String ssid = WiFi.SSID(i);
      if (ssid.length() > 0) { // Leere SSIDs ignorieren
        ssidList += "<option value=\"";
        ssidList += ssid;
        ssidList += "\">";
        ssidList += ssid;
        ssidList += " (";
        ssidList += WiFi.RSSI(i);
        ssidList += " dBm)";
        ssidList += "</option>";
      }
    }
  }
}

// ============================ Captive Portal & WPS ============================

String urlDecode(String input) {
  String s = input;
  s.replace("%20", " ");
  s.replace("+", " ");
  return s;
}

String htmlPage(String title, String body) {
  String s = "<!DOCTYPE html><html><head><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><title>";
  s += title;
  s += "</title></head><body>";
  s += body;
  s += "</body></html>";
  return s;
}

void startCaptivePortal() {
  if (!configMode) return; // Nur im Konfigurationsmodus starten
  
  // AP starten ohne WiFi-Modus zu ändern (bleibt AP_STA)
  WiFi.softAP(apSSID);
  delay(200);
  WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
  dnsServer.start(53, "*", apIP);

  // SSID-Liste für Captive Portal erstellen
  buildSsidList();

  // Hauptseite mit WPS-Status und manueller Konfiguration
  server.on("/", HTTP_GET, []() {
    if (!configMode) {
      server.send(200, "text/html", htmlPage("Konfiguration beendet", "<h1>WiFi bereits konfiguriert</h1>"));
      return;
    }
    
    String s = "<h1>ESP8266 SETUP</h1>";
    s += "<div style='margin: 20px 0;'>";
    s += "<a href=\"/settings\" class='button3'>⚙️ Manuelle Wi-Fi Einstellungen</a>";
    s += "</div>";
    s += "<style>";
    s += "html {background-color: #000; color: #fff; display:flex;justify-content:center;align-items:center; font-family: Arial;}";
    s += ".button3 {color:#fff;padding:15px 30px;border:none;font-size:16px;background:linear-gradient(to bottom,#bced7f,#99e43c);text-decoration:none;display:inline-block;margin:10px;border-radius:5px;}";
    s += "h1 {text-align: center;}";
    s += "</style>";
    server.send(200, "text/html", htmlPage("ESP8266 Setup", s));
  });

  // Manuelle WiFi-Einstellungen
  server.on("/settings", HTTP_GET, []() {
    if (!configMode) {
      server.send(200, "text/html", htmlPage("Konfiguration beendet", "<h1>WiFi bereits konfiguriert</h1>"));
      return;
    }
    
    String s = "<h1>Wi-Fi Einstellungen</h1>";
    s += "<form method=\"get\" action=\"/setap\">";
    s += "<p>SSID auswählen:</p>";
    s += "<select name=\"ssid\" style='width:100%;padding:10px;margin:10px 0;'>" + ssidList + "</select>";
    s += "<p>Passwort:</p>";
    s += "<input name=\"pass\" type=\"password\" style='width:100%;padding:10px;margin:10px 0;'>";
    s += "<p><input type=\"submit\" value=\"Verbinden\" style='padding:15px 30px;font-size:16px;background:linear-gradient(to bottom,#bced7f,#99e43c);border:none;color:#fff;'></p>";
    s += "</form>";
    s += "<p><a href='/'>← Zurück zur Hauptseite</a></p>";
    s += "<style>html {background-color: #000; color: #fff; padding: 20px; font-family: Arial;} a {color: #99e43c;}</style>";
    server.send(200, "text/html", htmlPage("Wi-Fi Einstellungen", s));
  });

  // WiFi-Verbindung testen und speichern
  server.on("/setap", HTTP_GET, []() {
    if (!configMode) {
      server.send(200, "text/html", htmlPage("Konfiguration beendet", "<h1>WiFi bereits konfiguriert</h1>"));
      return;
    }
    
    String ssid = urlDecode(server.arg("ssid"));
    String pass = urlDecode(server.arg("pass"));
    
    String s = "<h1>Verbindung wird getestet...</h1>";
    s += "<p>Versuche Verbindung zu: " + ssid + "</p>";
    s += "<div id='status'>Bitte warten...</div>";
    s += "<script>";
    s += "setTimeout(function(){";
    s += "document.getElementById('status').innerHTML = 'Verbindung läuft...';";
    s += "}, 2000);";
    s += "</script>";
    s += "<style>html {background-color: #000; color: #fff; text-align: center; font-family: Arial;}</style>";
    server.send(200, "text/html", htmlPage("Verbindung testen", s));
    
    // Verbindung im AP_STA Modus testen
    WiFi.begin(ssid.c_str(), pass.c_str());
    unsigned long startAttemptTime = millis();
    bool connected = false;
    
    while (millis() - startAttemptTime < 15000) {
      if (WiFi.status() == WL_CONNECTED) {
        connected = true;
        break;
      }
      delay(500);
      if (configMode) { // Nur bedienen wenn noch im Konfigurationsmodus
        server.handleClient();
        dnsServer.processNextRequest();
      }
    }
    
    if (connected) {
      Serial.println("Manuelle WiFi-Verbindung erfolgreich!");
      Serial.print("Verbunden mit: "); Serial.println(ssid);
      Serial.print("IP-Adresse: "); Serial.println(WiFi.localIP());
      
      // Konfigurationsmodus beenden
      configMode = false;
      wpsActive = false;
      
      // WiFi-Credentials speichern
      saveWiFiCredentials(ssid, pass);
      
      // Captive Portal und DNS Server stoppen
      server.stop();
      dnsServer.stop();
      WiFi.softAPdisconnect(true);
      
      Serial.println("Konfigurationsmodus beendet - WPS und Captive Portal deaktiviert");
      delay(2000);
      ESP.restart();
    } else {
      // Fehlgeschlagen - zurück zur Einstellungsseite
      WiFi.disconnect();
      server.sendHeader("Location", String("http://") + apIP.toString() + "/settings", true);
      server.send(302, "text/plain", "");
    }
  });

  server.onNotFound([]() {
    if (configMode) {
      server.sendHeader("Location", String("http://") + apIP.toString() + "/", true);
      server.send(302, "text/plain", "");
    } else {
      server.send(404, "text/plain", "Not Found");
    }
  });

  server.begin();
  Serial.println("Captive Portal gestartet. Verbinde dich mit '" + String(apSSID) + "' und öffne 192.168.1.1");
}

void startWPS() {
  if (!configMode || WiFi.status() == WL_CONNECTED) {
    return;
  }
  
  if (!wpsActive) {
    Serial.println("Starte WPS...");
    Serial.println("WPS läuft dauerhaft bis zur erfolgreichen Verbindung");
    
    // WPS im AP_STA Modus starten (Push Button Mode)
    WiFi.beginWPSConfig();
    wpsActive = true;
    Serial.println("WPS aktiviert - drücke WPS-Button am Router innerhalb von 2 Minuten");
  }
}

void checkWPS() {
  if (!configMode) return;
  
  int status = WiFi.status();
  Serial.print("WiFi Status während WPS: "); Serial.println(status);
  
  if (status == WL_CONNECTED) {
    String newSSID = WiFi.SSID();
    if (newSSID.length() > 0) {
      Serial.println("WPS erfolgreich - Konfiguration gespeichert!");
      Serial.print("Verbunden mit: "); Serial.println(newSSID);
      Serial.print("IP-Adresse: "); Serial.println(WiFi.localIP());
      
      // Konfigurationsmodus beenden
      configMode = false;
      wpsActive = false;
      
      // WiFi-Credentials speichern, inkl. PSK wenn verfügbar
      String psk = WiFi.psk();
      saveWiFiCredentials(newSSID, psk.length() > 0 ? psk : "");
      
      // Captive Portal und DNS Server stoppen
      server.stop();
      dnsServer.stop();
      WiFi.softAPdisconnect(true);
      
      Serial.println("Konfigurationsmodus beendet - WPS und Captive Portal deaktiviert");
      delay(2000);
      ESP.restart();
    } else {
      Serial.println("WPS SSID leer - Verbindung ungültig");
    }
  } else if (status == WL_NO_SSID_AVAIL || status == WL_CONNECT_FAILED) {
    // WPS fehlgeschlagen, versuche neu zu starten
    if (wpsActive) {
      Serial.println("WPS fehlgeschlagen, starte neu in 10 Sekunden...");
      wpsActive = false;
      delay(10000);
      startWPS(); // Neu starten
    }
  }
}

void tryConnectSTA() {
  if (strlen(cfgssid) > 0) {
    Serial.print("Versuche Verbindung mit gespeichertem SSID: "); 
    Serial.println(cfgssid);
    WiFi.begin(cfgssid, cfgpassword);
    unsigned long startAttemptTime = millis();
    while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 10000) {
      delay(500);
      Serial.print(".");
    }
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("\nVerbunden mit gespeicherten Credentials!");
      Serial.print("IP-Adresse: "); Serial.println(WiFi.localIP());
      configMode = false;
    } else {
      Serial.println("\nVerbindung mit gespeicherten Credentials fehlgeschlagen");
      configMode = true;
    }
  } else {
    Serial.println("Keine WiFi-Credentials gespeichert");
    Serial.println("Starte Konfigurationsmodus: WPS + Captive Portal");
    configMode = true;
    startWPS(); // WPS automatisch starten
  }
}

// ============================ Setup & Loop ============================

void setup() {
  Serial.begin(115200);
  EEPROM.begin(512);
  delay(10);
  loadWiFiCredentials();
  
  WiFi.mode(WIFI_AP_STA);
  
  tryConnectSTA(); // Zuerst versuchen zu verbinden
   
  if (configMode) {
    startWPS(); // WPS sofort starten
    startCaptivePortal(); // Captive Portal starten
    
    // Konfigurationsmodus: Warten bis WiFi verbunden ist
    Serial.println("Warte auf WiFi-Konfiguration...");
    while (configMode) {
      server.handleClient();
      dnsServer.processNextRequest();
      checkWPS();
      delay(500); // Etwas längere Pause für WPS (bis zu 2 Min pro Versuch)
    }
    
    Serial.println("WiFi konfiguriert - starte normalen Betrieb");
    delay(2000); // Kurz warten vor Neustart
    ESP.restart(); // Neustart für sauberen Übergang
  }
  
  // Hier angekommen bedeutet: WiFi ist verbunden, normaler Betrieb kann starten
  Serial.println("Setup abgeschlossen - WiFi verbunden");
  Serial.print("SSID: "); Serial.println(WiFi.SSID());
  Serial.print("IP: "); Serial.println(WiFi.localIP());
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) {

    Serial.println("WiFi-Verbindung verloren - versuche Reconnect");
    WiFi.reconnect();
    delay(5000);
  }
  delay(1000);
}

Endschuldigung dafür das in meinem Text viele fehler sind.
Leide leider an Legasthenie.

Hoffendlich kann mir jemand helfen oder hat eine gute Idee wie ich es umsetzen kann.
Vielen Dank

Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden.
Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.

mfg ein Moderator.

ich finde es nicht im deutschen teil des forums

????
image

Klick mal hier: ESP85266 AP/STA mode

Wie sagte einst Boris Becker: "Ich bin drin !!!" :slight_smile:

Bin ich da schon drin, oder was? Ich bin drin. Das ist ja einfach.

ja ich bin nun drin .
hat den jemand eine lösung für mein problem ?
vieleich nur an ansatz den ich übersegen habe.