feat: triple power-cycle factory reset (no FTDI needed)
Power-cycle the device 3 times within 10 seconds to trigger factory reset: - Clears WiFi credentials (SSID + password) in EEPROM - Shows "FACTORY RESET / WiFi: TJ56654-Setup / Pass: 12345678" on display - Reboots into WiFiManager AP mode for reconfiguration Counter stored at EEPROM offset 480 (well past Config ~260 bytes). Clears automatically after 10s of stable operation. Prevents the need for FTDI/USB recovery when credentials are corrupted. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
e9dc158a4e
commit
5b8a58715e
@@ -110,6 +110,64 @@ void ICACHE_FLASH_ATTR safeStringCopy(const String& src, char* dest, size_t maxL
|
||||
dest[maxLen - 1] = '\0';
|
||||
}
|
||||
|
||||
// ============ Triple power-cycle factory reset ============
|
||||
//
|
||||
// How it works: on each boot we increment a counter in EEPROM.
|
||||
// If the device runs for >10s the counter is cleared back to 0.
|
||||
// 3 quick power cycles before the 10s window = factory reset:
|
||||
// clears WiFi credentials, reboots into WiFiManager AP mode.
|
||||
|
||||
void ICACHE_FLASH_ATTR checkFactoryReset() {
|
||||
EEPROM.begin(512);
|
||||
ResetCounter rc;
|
||||
EEPROM.get(RESET_COUNTER_ADDR, rc);
|
||||
|
||||
if (rc.magic != RESET_COUNTER_MAGIC) {
|
||||
rc.magic = RESET_COUNTER_MAGIC;
|
||||
rc.count = 0;
|
||||
}
|
||||
|
||||
rc.count++;
|
||||
Serial.printf("Boot counter: %d/%d (power-cycle %d more times within 10s to factory reset)\n",
|
||||
rc.count, RESET_COUNTER_TRIPS, RESET_COUNTER_TRIPS - rc.count);
|
||||
|
||||
if (rc.count >= RESET_COUNTER_TRIPS) {
|
||||
Serial.println("!!! FACTORY RESET triggered !!!");
|
||||
rc.count = 0;
|
||||
EEPROM.put(RESET_COUNTER_ADDR, rc);
|
||||
EEPROM.commit();
|
||||
EEPROM.end();
|
||||
|
||||
// Clear WiFi credentials only — keep other settings
|
||||
memset(config.ssid, 0, sizeof(config.ssid));
|
||||
memset(config.password, 0, sizeof(config.password));
|
||||
saveConfig();
|
||||
|
||||
// Show reset screen
|
||||
display.clearDisplay();
|
||||
display.setTextColor(SSD1306_WHITE);
|
||||
display.setTextSize(2);
|
||||
display.setCursor(8, 4);
|
||||
display.println("FACTORY");
|
||||
display.setCursor(8, 24);
|
||||
display.println("RESET!");
|
||||
display.setTextSize(1);
|
||||
display.setCursor(2, 48);
|
||||
display.println("WiFi: TJ56654-Setup");
|
||||
display.setCursor(2, 57);
|
||||
display.println("Pass: 12345678");
|
||||
display.display();
|
||||
|
||||
delay(4000);
|
||||
ESP.restart();
|
||||
return;
|
||||
}
|
||||
|
||||
EEPROM.put(RESET_COUNTER_ADDR, rc);
|
||||
EEPROM.commit();
|
||||
EEPROM.end();
|
||||
}
|
||||
|
||||
// ============ EEPROM functions ============
|
||||
|
||||
void ICACHE_FLASH_ATTR loadConfig() {
|
||||
@@ -219,6 +277,9 @@ void setup() {
|
||||
// Load configuration
|
||||
loadConfig();
|
||||
|
||||
// Check for triple power-cycle factory reset (must be after display+config init)
|
||||
checkFactoryReset();
|
||||
|
||||
// Setup WiFi
|
||||
setupWiFi();
|
||||
|
||||
@@ -325,6 +386,18 @@ void loop() {
|
||||
fetchWeatherAsync();
|
||||
}
|
||||
|
||||
// Clear factory-reset boot counter after 10s of normal operation
|
||||
static bool resetCounterCleared = false;
|
||||
if (!resetCounterCleared && millis() > RESET_COUNTER_WINDOW) {
|
||||
EEPROM.begin(512);
|
||||
ResetCounter rc = { RESET_COUNTER_MAGIC, 0 };
|
||||
EEPROM.put(RESET_COUNTER_ADDR, rc);
|
||||
EEPROM.commit();
|
||||
EEPROM.end();
|
||||
resetCounterCleared = true;
|
||||
Serial.println("Boot counter cleared — stable operation confirmed");
|
||||
}
|
||||
|
||||
// Update weather periodically (static flag avoids millis() > 10000 rollover trap)
|
||||
static bool weatherBootReady = false;
|
||||
if (!weatherBootReady && millis() > 10000UL) weatherBootReady = true;
|
||||
|
||||
Reference in New Issue
Block a user