From 5f6f3b90b0ea7cab49d0446a69df2b1610059bdb Mon Sep 17 00:00:00 2001 From: cottongin Date: Mon, 3 Aug 2026 10:49:58 -0400 Subject: [PATCH] feat: WiFi manager with station/AP mode and mDNS Co-authored-by: Cursor --- src/main.cpp | 13 +++---- src/wifi_manager.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++++ src/wifi_manager.h | 23 +++++++++++ 3 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 src/wifi_manager.cpp create mode 100644 src/wifi_manager.h diff --git a/src/main.cpp b/src/main.cpp index 30c2fe8..7d98ee6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,8 +2,10 @@ #include #include "config.h" #include "settings.h" +#include "wifi_manager.h" SettingsManager settingsManager; +WiFiManager wifiManager; void setup() { auto cfg = M5.config(); @@ -12,20 +14,17 @@ void setup() { Serial.begin(115200); Serial.println("[main] Immich Frame booting..."); - // Disable audio permanently pinMode(PIN_AUDIO_PWR_EN, OUTPUT); digitalWrite(PIN_AUDIO_PWR_EN, LOW); pinMode(PIN_SPK_EN, OUTPUT); digitalWrite(PIN_SPK_EN, LOW); settingsManager.begin(); - Settings settings = settingsManager.get(); + wifiManager.begin(settingsManager); - Serial.printf("[main] Provisioned: %s\n", settingsManager.isProvisioned() ? "yes" : "no"); - Serial.printf("[main] Immich URL: %s\n", settings.immich_url.c_str()); - Serial.printf("[main] Interval: %d min\n", settings.interval_min); - Serial.printf("[main] Free heap: %d, PSRAM: %d\n", - ESP.getFreeHeap(), ESP.getFreePsram()); + Serial.printf("[main] WiFi mode: %s, IP: %s\n", + wifiManager.isAPMode() ? "AP" : "Station", + wifiManager.getIP().c_str()); Serial.println("[main] Boot complete"); } diff --git a/src/wifi_manager.cpp b/src/wifi_manager.cpp new file mode 100644 index 0000000..7a6a464 --- /dev/null +++ b/src/wifi_manager.cpp @@ -0,0 +1,90 @@ +#include "wifi_manager.h" +#include +#include +#include "config.h" + +void WiFiManager::begin(SettingsManager& settings) { + _settings = &settings; + + if (!_settings->isProvisioned()) { + Serial.println("[wifi] Not provisioned — starting AP"); + startAP(); + return; + } + + startStation(); +} + +bool WiFiManager::isConnected() { + return WiFi.status() == WL_CONNECTED; +} + +bool WiFiManager::isAPMode() { + return _apMode; +} + +String WiFiManager::getIP() { + if (_apMode) { + return WiFi.softAPIP().toString(); + } + return WiFi.localIP().toString(); +} + +int WiFiManager::getRSSI() { + if (_apMode) return 0; + return WiFi.RSSI(); +} + +void WiFiManager::startAP() { + WiFi.disconnect(true); + WiFi.mode(WIFI_AP); + WiFi.softAP("PaperColor-Setup"); + _apMode = true; + Serial.printf("[wifi] AP started: PaperColor-Setup, IP: %s\n", + WiFi.softAPIP().toString().c_str()); +} + +void WiFiManager::startStation() { + Settings s = _settings->get(); + WiFi.disconnect(true); + WiFi.mode(WIFI_STA); + _apMode = false; + + Serial.printf("[wifi] Connecting to: %s\n", s.wifi_ssid.c_str()); + + for (_retryCount = 0; _retryCount < WIFI_MAX_RETRIES; _retryCount++) { + if (attemptConnection(s.wifi_ssid, s.wifi_pass)) { + Serial.printf("[wifi] Connected! IP: %s, RSSI: %d\n", + WiFi.localIP().toString().c_str(), WiFi.RSSI()); + WiFi.setSleep(WIFI_PS_MIN_MODEM); + setupMDNS("papercolor"); + return; + } + Serial.printf("[wifi] Attempt %d/%d failed\n", _retryCount + 1, WIFI_MAX_RETRIES); + } + + Serial.println("[wifi] All attempts failed — falling back to AP mode"); + startAP(); +} + +void WiFiManager::setupMDNS(const char* hostname) { + if (MDNS.begin(hostname)) { + MDNS.addService("http", "tcp", 80); + Serial.printf("[wifi] mDNS: %s.local\n", hostname); + } else { + Serial.println("[wifi] mDNS failed to start"); + } +} + +bool WiFiManager::attemptConnection(const String& ssid, const String& pass) { + WiFi.begin(ssid.c_str(), pass.c_str()); + + unsigned long start = millis(); + while (WiFi.status() != WL_CONNECTED) { + if (millis() - start > WIFI_CONNECT_TIMEOUT_MS) { + return false; + } + delay(100); + } + return true; +} diff --git a/src/wifi_manager.h b/src/wifi_manager.h new file mode 100644 index 0000000..403f0b7 --- /dev/null +++ b/src/wifi_manager.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include "settings.h" + +class WiFiManager { +public: + void begin(SettingsManager& settings); + bool isConnected(); + bool isAPMode(); + String getIP(); + int getRSSI(); + void startAP(); + void startStation(); + void setupMDNS(const char* hostname); + +private: + SettingsManager* _settings = nullptr; + bool _apMode = false; + int _retryCount = 0; + + bool attemptConnection(const String& ssid, const String& pass); +};