- WiFiManager als Pointer, lazy new in begin() verhindert Crash durch globale Konstruktoren vor Arduino-Framework-Init - WiFi.mode(WIFI_STA) vor Credentials-Pruefung; getWiFiSSID(true) statt WiFi.SSID() (erfordert gestarteten Stack) - Credentials vorhanden: WiFi.begin() non-blocking, Ergebnis in loop() - Keine Credentials: setConfigPortalBlocking(false) + process() in loop() - Nach 3 Fehlversuchen: startConfigPortal() automatisch - onConnect(): stopWebPortal() vor AsyncWebServer-Start (Port-80-Konflikt) - main.cpp: LaserTracker startet vor WiFi (Prioritaet 1) - MQTT + WebServer: Lazy-Init beim ersten WiFi-Connect - Display rate-limited: W 500ms-Blinker, Minuten 60s, Sekunden 1s, M bei Aenderung - Manuell getestet: LaserTracker laeuft sofort, WiFi non-blocking verifiziert
97 lines
3.7 KiB
C++
97 lines
3.7 KiB
C++
#pragma once
|
||
|
||
// =============================================================================
|
||
// wifi_connector.h – WiFi-Verbindungsmanagement via WiFiManager
|
||
// Projekt: MQTT-Display LaserCutter
|
||
//
|
||
// Design-Prinzip: begin() ist vollständig NON-BLOCKING.
|
||
// LaserTracker und Display laufen sofort nach begin() – kein Warten auf WiFi.
|
||
//
|
||
// Zwei Startszenarien:
|
||
// 1) Credentials gespeichert → WiFi.begin() direkt, Ergebnis in loop() prüfen
|
||
// 2) Keine Credentials → Captive Portal sofort async öffnen, loop() ruft
|
||
// wm.process() auf bis User Daten eingibt
|
||
//
|
||
// Verwendung:
|
||
// wifi.onStatusChange(myCallback); // optional, vor begin()
|
||
// wifi.begin(); // KEhrt sofort zurück (non-blocking)
|
||
// // in loop():
|
||
// wifi.loop(); // Reconnect + Portal-Processing
|
||
// if (wifi.isConnected()) { ... }
|
||
// =============================================================================
|
||
|
||
#include <Arduino.h>
|
||
#include <WiFi.h>
|
||
#include <WiFiManager.h>
|
||
#include "config.h"
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Verbindungsstatus
|
||
// ---------------------------------------------------------------------------
|
||
enum class WifiStatus {
|
||
DISCONNECTED, // Nicht verbunden, kein AP aktiv
|
||
AP_ACTIVE, // Konfigurations-Portal läuft (AP-Modus)
|
||
CONNECTING, // Verbindungsversuch läuft
|
||
CONNECTED // Verbunden mit WLAN
|
||
};
|
||
|
||
// Callback-Typ: wird bei Statusänderungen aufgerufen
|
||
using WifiStatusCallback = void (*)(WifiStatus newStatus);
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// WifiConnector
|
||
// ---------------------------------------------------------------------------
|
||
class WifiConnector {
|
||
public:
|
||
WifiConnector();
|
||
|
||
// Optionaler AP-Passwortschutz (Standard: kein Passwort)
|
||
void setApPassword(const char* password);
|
||
|
||
// Callback vor begin() registrieren
|
||
void onStatusChange(WifiStatusCallback cb);
|
||
|
||
// WiFi starten – NICHT blockierend, kehrt sofort zurück.
|
||
// Hat das Gerät Credentials: startet WiFi.begin() im Hintergrund.
|
||
// Hat es keine Credentials: öffnet Captive Portal asynchron.
|
||
void begin();
|
||
|
||
// In loop() aufrufen: Portal-Processing + Verbindungscheck + Reconnect.
|
||
// Darf niemals lange blockieren.
|
||
void loop();
|
||
|
||
// Aktuellen Status abfragen
|
||
WifiStatus getStatus() const { return _status; }
|
||
bool isConnected() const { return _status == WifiStatus::CONNECTED; }
|
||
bool isPortalActive() const { return _portalRunning; }
|
||
IPAddress getIP() const { return WiFi.localIP(); }
|
||
String getSSID() const { return WiFi.SSID(); }
|
||
int8_t getRSSI() const { return WiFi.RSSI(); }
|
||
|
||
// Debug-Ausgabe auf Serial
|
||
void printToSerial() const;
|
||
|
||
// Gespeicherte WiFi-Credentials löschen (zwingt den AP beim nächsten Start)
|
||
void resetCredentials();
|
||
|
||
private:
|
||
WiFiManager* _wm; // lazy-konstruiert in begin() (nicht global!)
|
||
WifiStatusCallback _cb;
|
||
WifiStatus _status;
|
||
char _apPassword[32];
|
||
uint32_t _lastReconnectMs; // Zeitstempel letzter Reconnect-Versuch
|
||
bool _portalRunning; // Captive Portal aktiv
|
||
uint8_t _failCount; // Anzahl fehlgeschlagener Verbindungsversuche
|
||
|
||
void setStatus(WifiStatus s);
|
||
void onConnect(); // NTP + Log bei jedem Verbindungsaufbau
|
||
|
||
// Callbacks für WiFiManager (static nötig, C-Funktionszeiger)
|
||
static WifiConnector* _instance;
|
||
static void _onApStarted();
|
||
static void _onApStopped();
|
||
};
|
||
|
||
// Globale Instanz
|
||
extern WifiConnector wifiConnector;
|