- 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
142 lines
5.0 KiB
C++
142 lines
5.0 KiB
C++
// =============================================================================
|
||
// 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");
|
||
}
|