MQTT-Display-LaserCutter/src/wifi_connector.cpp
MaPaLo76 c63cace1ae feat(wifi): implement WiFiManager connection handling
- include/wifi_connector.h: WifiConnector class with WifiStatus enum,
  onStatusChange callback, begin/loop/reset methods
- src/wifi_connector.cpp: autoConnect with AP timeout and restart,
  reconnect logic on connection loss, printToSerial diagnostics
- src/main.cpp: call wifiConnector.begin() and loop()
- test_sketches/test_wifi.cpp: first-connect via captive portal,
  auto-reconnect after reboot, BOOT-button (3s) resets credentials
- platformio.ini: add test-wifi environment
- Implementation-Plan.md: mark tasks 3.1-3.3 complete
2026-02-22 13:50:07 +01:00

142 lines
5.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// =============================================================================
// wifi_connector.cpp WiFi-Verbindungsmanagement via WiFiManager
// =============================================================================
#include "wifi_connector.h"
// Globale Instanz
WifiConnector wifiConnector;
// Static-Member Initialisierung
WifiConnector* WifiConnector::_instance = nullptr;
// ---------------------------------------------------------------------------
WifiConnector::WifiConnector()
: _cb(nullptr)
, _status(WifiStatus::DISCONNECTED)
, _lastConnectedMs(0)
{
_apPassword[0] = '\0';
_instance = this;
}
// ---------------------------------------------------------------------------
void WifiConnector::setApPassword(const char* password) {
strlcpy(_apPassword, password, sizeof(_apPassword));
}
// ---------------------------------------------------------------------------
void WifiConnector::onStatusChange(WifiStatusCallback cb) {
_cb = cb;
}
// ---------------------------------------------------------------------------
void WifiConnector::setStatus(WifiStatus s) {
if (s == _status) return;
_status = s;
if (_cb) _cb(s);
}
// ---------------------------------------------------------------------------
void WifiConnector::_onApStarted() {
if (_instance) {
_instance->setStatus(WifiStatus::AP_ACTIVE);
LOG_I("WIFI", "Konfigurations-Portal gestartet AP: %s", WIFI_AP_NAME);
LOG_I("WIFI", "Verbinde mit AP und oeffne http://192.168.4.1");
}
}
void WifiConnector::_onApStopped() {
if (_instance) {
LOG_I("WIFI", "Konfigurations-Portal beendet");
}
}
// ---------------------------------------------------------------------------
void WifiConnector::begin() {
LOG_I("WIFI", "Starte WiFiManager (AP: %s, Timeout: %d s)",
WIFI_AP_NAME, WIFI_AP_TIMEOUT_S);
setStatus(WifiStatus::CONNECTING);
WiFiManager wm;
// Callbacks registrieren
wm.setAPCallback([](WiFiManager*) { WifiConnector::_onApStarted(); });
wm.setSaveConfigCallback([]() { WifiConnector::_onApStopped(); });
// Portal-Timeout: nach WIFI_AP_TIMEOUT_S Sekunden ohne Konfiguration → Neustart
wm.setConfigPortalTimeout(WIFI_AP_TIMEOUT_S);
// Debug-Ausgabe des WiFiManagers unterdrücken (nutzen eigene Logs)
wm.setDebugOutput(false);
// Verbinden blockiert bis Erfolg oder Timeout
bool connected = (_apPassword[0] != '\0')
? wm.autoConnect(WIFI_AP_NAME, _apPassword)
: wm.autoConnect(WIFI_AP_NAME);
if (connected) {
setStatus(WifiStatus::CONNECTED);
_lastConnectedMs = millis();
LOG_I("WIFI", "Verbunden mit: %s", WiFi.SSID().c_str());
LOG_I("WIFI", "IP-Adresse : %s", WiFi.localIP().toString().c_str());
LOG_I("WIFI", "RSSI : %d dBm", WiFi.RSSI());
} else {
LOG_E("WIFI", "Timeout starte ESP32 neu ...");
delay(1000);
ESP.restart();
}
}
// ---------------------------------------------------------------------------
void WifiConnector::loop() {
if (_status == WifiStatus::CONNECTED && WiFi.status() != WL_CONNECTED) {
LOG_E("WIFI", "Verbindung verloren versuche Reconnect ...");
setStatus(WifiStatus::DISCONNECTED);
}
if (_status == WifiStatus::DISCONNECTED) {
setStatus(WifiStatus::CONNECTING);
// WiFi.reconnect() reicht bei kurzen Unterbrechungen
WiFi.reconnect();
uint32_t start = millis();
while (WiFi.status() != WL_CONNECTED && millis() - start < 15000) {
delay(500);
}
if (WiFi.status() == WL_CONNECTED) {
setStatus(WifiStatus::CONNECTED);
LOG_I("WIFI", "Reconnect erfolgreich IP: %s",
WiFi.localIP().toString().c_str());
} else {
LOG_E("WIFI", "Reconnect fehlgeschlagen starte neu ...");
delay(1000);
ESP.restart();
}
}
}
// ---------------------------------------------------------------------------
void WifiConnector::printToSerial() const {
LOG_I("WIFI", "=== WiFi-Status ===");
switch (_status) {
case WifiStatus::DISCONNECTED: LOG_I("WIFI", " Status : DISCONNECTED"); break;
case WifiStatus::AP_ACTIVE: LOG_I("WIFI", " Status : AP_ACTIVE (%s)", WIFI_AP_NAME); break;
case WifiStatus::CONNECTING: LOG_I("WIFI", " Status : CONNECTING"); break;
case WifiStatus::CONNECTED:
LOG_I("WIFI", " Status : CONNECTED");
LOG_I("WIFI", " SSID : %s", WiFi.SSID().c_str());
LOG_I("WIFI", " IP : %s", WiFi.localIP().toString().c_str());
LOG_I("WIFI", " RSSI : %d dBm", WiFi.RSSI());
break;
}
LOG_I("WIFI", "===================");
}
// ---------------------------------------------------------------------------
void WifiConnector::resetCredentials() {
WiFiManager wm;
wm.resetSettings();
LOG_I("WIFI", "WiFi-Credentials geloescht AP wird beim naechsten Start geoeffnet");
}