Files
esp8266-weather-clock-opens…/firmware/clock_ntp_ota_v1.9/wifi_manager.cpp
T
Alex PetrochenkoandClaude Opus 4.5 4a7e889052 refactor: split monolithic .ino into modular structure + improve boot UX
## Code Structure
- Split 2172-line .ino into 7 modules:
  - config.h - structs, enums, constants
  - globals.h - extern declarations, function prototypes
  - display.cpp - OLED display functions, Thanos dissolve effect
  - ntp_client.cpp - NTP sync, DST calculation
  - wifi_manager.cpp - WiFi connection management
  - weather.cpp - Open-Meteo API (async)
  - web_server.cpp - Web interface handlers
  - clock_ntp_ota_v1.9.ino - setup/loop, EEPROM, OTA (153 lines)

## Boot UX Improvements
- Remove meaningless "READY" screen
- Replace cryptic counter (0-7) with "WiFi..." + animated dots
- Show SSID + IP on connected screen
- Use yellow zone (Y 48-63) for status text
- Fix text centering on all boot screens
- Initialize lastBlinkTime/lastModeSwitch to prevent first-frame glitch

## Layout (dual-color display)
- Blue zone (Y 0-47): main content
- Yellow zone (Y 48-63): status/version
- Centering formula: width = n×5 + (n-1)×1 for size 1

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 09:05:45 +00:00

174 lines
4.8 KiB
C++

/*
* wifi_manager.cpp - WiFi connection management
* TJ-56-654 Weather Clock v1.9.2
*/
#include "globals.h"
#include <WiFiManager.h>
// Async WiFi - Process connection (call in loop)
void ICACHE_FLASH_ATTR processWiFiConnection() {
if (wifiConnState != WIFI_CONN_CONNECTING) return;
// Check connection status
if (WiFi.status() == WL_CONNECTED) {
wifiConnState = WIFI_CONN_CONNECTED;
wifiRetry.reset();
internetConnected = true;
Serial.println("\nWiFi connected!");
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
Serial.print("IP: ");
Serial.println(WiFi.localIP());
// Disable fallback AP if it was enabled
if (WiFi.getMode() == WIFI_AP_STA) {
Serial.println("Disabling fallback AP (back to STA mode)");
WiFi.softAPdisconnect(true);
WiFi.mode(WIFI_STA);
}
// Sync connected SSID to config
if (strlen(config.ssid) == 0) {
safeStringCopy(WiFi.SSID(), config.ssid, sizeof(config.ssid));
saveConfig();
}
showIP();
return;
}
// Check timeout for this attempt
if (millis() - wifiConnectStart > WIFI_TIMEOUT_MS) {
wifiRetry.scheduleRetry();
unsigned long nextRetryMs = wifiRetry.getBackoffDelay();
Serial.printf("\nWiFi connection failed. Retry in %lu seconds\n", nextRetryMs / 1000);
wifiConnState = WIFI_CONN_FAILED;
internetConnected = false;
showNoWiFi(nextRetryMs / 1000);
return;
}
// Still connecting
static unsigned long lastDot = 0;
if (millis() - lastDot > 500) {
Serial.print(".");
lastDot = millis();
}
}
// WiFi setup (SYNCHRONOUS in setup(), async reconnect in loop())
void ICACHE_FLASH_ATTR setupWiFi() {
Serial.println("WiFi Setup - Synchronous for initial connection");
WiFi.hostname(config.hostname);
WiFi.mode(WIFI_STA);
// Try 1: Use WiFi.begin() without params - uses SDK stored credentials
Serial.println("Trying SDK-stored credentials...");
WiFi.begin();
// SYNCHRONOUS wait for connection (max 10 seconds)
Serial.print("Connecting to WiFi");
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
showWiFiConnecting(attempts);
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi connected!");
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
Serial.print("IP: ");
Serial.println(WiFi.localIP());
Serial.print("Gateway: ");
Serial.println(WiFi.gatewayIP());
Serial.print("DNS: ");
Serial.println(WiFi.dnsIP());
safeStringCopy(WiFi.SSID(), config.ssid, sizeof(config.ssid));
saveConfig();
showIP();
wifiConnState = WIFI_CONN_CONNECTED;
return;
}
// Try 2: If we have EEPROM credentials, try those
if (strlen(config.ssid) > 0 && strlen(config.password) > 0) {
Serial.println("\nTrying EEPROM credentials...");
WiFi.begin(config.ssid, config.password);
attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
showWiFiConnecting(attempts);
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi connected via EEPROM credentials!");
showIP();
wifiConnState = WIFI_CONN_CONNECTED;
return;
}
}
// No stored credentials - use WiFiManager
if (strlen(config.ssid) == 0) {
Serial.println("\nNo saved credentials, using WiFiManager...");
WiFiManager wifiManager;
wifiManager.setConfigPortalTimeout(180);
// Show AP mode indicator
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(25, 15);
display.print("Setup Mode");
display.setTextSize(1);
display.setCursor(10, 35);
display.print("Connect to WiFi:");
display.setCursor(10, 48);
display.print("TJ56654-Setup");
display.display();
Serial.println("Attempting WiFiManager auto-connect...");
if (!wifiManager.autoConnect("TJ56654-Setup", "12345678")) {
Serial.println("WiFi connection failed. Starting fallback AP...");
WiFi.mode(WIFI_AP);
WiFi.softAP("TJ56654-Clock", "12345678");
Serial.print("Fallback AP IP: ");
Serial.println(WiFi.softAPIP());
wifiConnState = WIFI_CONN_CONNECTED;
return;
}
Serial.println("WiFi connected via WiFiManager!");
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
Serial.print("IP: ");
Serial.println(WiFi.localIP());
safeStringCopy(WiFi.SSID(), config.ssid, sizeof(config.ssid));
saveConfig();
showIP();
wifiConnState = WIFI_CONN_CONNECTED;
return;
}
// We have credentials but WiFi is not available
Serial.println("\nWiFi not available. Will retry in background.");
wifiConnState = WIFI_CONN_FAILED;
wifiRetry.scheduleRetry();
showNoWiFi(wifiRetry.getBackoffDelay() / 1000);
}