#include "WiFiManager.hpp" namespace cyd { WiFiManager::WiFiManager(SettingsManager& settings) : settings_(settings) { } void WiFiManager::begin() { WiFi.disconnect(true); delay(100); if (settings_.hasWifiCredentials()) { Serial.printf("WiFiManager: loaded SSID '%s', connecting...\n", settings_.getWifiSsid().c_str()); startStation_(); } else { Serial.println("WiFiManager: no credentials stored, starting setup AP"); startAccessPoint_(); } } void WiFiManager::update() { switch (state_) { case State::Uninitialized: break; case State::Connecting: if (WiFi.status() == WL_CONNECTED) { Serial.printf("WiFiManager: connected, IP %s\n", WiFi.localIP().toString().c_str()); state_ = State::StationConnected; if (modeCallback_) { modeCallback_(false); } return; } if (millis() - connectStartMillis_ > kConnectTimeoutMs) { Serial.println("WiFiManager: station connection timeout"); WiFi.disconnect(true); state_ = State::StationFailed; startAccessPoint_(); } break; case State::StationConnected: if (WiFi.status() != WL_CONNECTED) { Serial.println("WiFiManager: station lost connection, retrying"); state_ = State::Connecting; connectStartMillis_ = millis(); WiFi.reconnect(); } break; case State::AccessPoint: case State::FallbackToAp: if (apRunning_) { dnsServer_.processNextRequest(); } break; case State::StationFailed: // Should have transitioned to AP above. break; } } String WiFiManager::getIpAddress() const { if (isApMode()) { return WiFi.softAPIP().toString(); } if (state_ == State::StationConnected) { return WiFi.localIP().toString(); } return "0.0.0.0"; } void WiFiManager::enterSetupMode() { if (state_ == State::StationConnected || state_ == State::Connecting) { WiFi.disconnect(true); } startAccessPoint_(); } void WiFiManager::configureAndConnect(const String& ssid, const String& pass) { settings_.setWifiSsid(ssid); settings_.setWifiPass(pass); settings_.save(); stopAccessPoint_(); startStation_(); } void WiFiManager::startStation_() { state_ = State::Connecting; connectStartMillis_ = millis(); WiFi.mode(WIFI_STA); WiFi.begin(settings_.getWifiSsid().c_str(), settings_.getWifiPass().c_str()); if (modeCallback_) { modeCallback_(false); } } void WiFiManager::startAccessPoint_() { state_ = State::AccessPoint; WiFi.mode(WIFI_AP); WiFi.softAP(kApSsid, kApPass); IPAddress ip = WiFi.softAPIP(); Serial.printf("WiFiManager: AP '%s' started at %s\n", kApSsid, ip.toString().c_str()); // DNS redirect: any hostname requested while connected to the AP resolves // to the CYD. The HTTP server in ApiServer serves the setup page at /. dnsServer_.start(53, "*", ip); apRunning_ = true; if (modeCallback_) { modeCallback_(true); } } void WiFiManager::stopAccessPoint_() { apRunning_ = false; dnsServer_.stop(); WiFi.softAPdisconnect(true); } } // namespace cyd