Public Access
Add ESP32 recovery app with WiFi setup portal
- New flash layout (partitions.csv): factory = recovery app, ota_0/ota_1 = clock firmware; esp32_usb uploads to ota_0 so it never overwrites it - src/recovery: WiFi + OTA + web page only. Opens the password protected 'FlipDot-Setup' AP with a captive portal when WiFi fails, lets you pick another WiFi (stored in NVS, used by both apps), start the clock or stay - Recovery is started when the clock firmware can't connect to WiFi, crashes 3 times, after 3 quick power cycles, from a new Home Assistant button, or by the bootloader when no clock firmware works - Shared NVS store and boot switching in src/esp32/system - Clock firmware keeps working on the old flash layout (falls back to OTA-only safe mode) - README: recovery app, one-time USB installation; tests: 65 total Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ddbdf7e65f
commit
4749f9e596
25 files changed
+979
-29
No files matched your search
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -247,6 +248,48 @@ void test_crash_count_cleared_after_running_long_enough()
|
||||
TEST_ASSERT_TRUE(shouldClearCrashCount(CRASH_FREE_TIME));
|
||||
}
|
||||
|
||||
void test_quick_power_cycles_request_recovery()
|
||||
{
|
||||
for (uint8_t count = 0; count < POWER_CYCLES_FOR_RECOVERY; count++)
|
||||
TEST_ASSERT_FALSE(powerCyclesRequestRecovery(count));
|
||||
TEST_ASSERT_TRUE(powerCyclesRequestRecovery(POWER_CYCLES_FOR_RECOVERY));
|
||||
}
|
||||
|
||||
void test_recovery_for_wifi_starts_clock_when_wifi_works()
|
||||
{
|
||||
TEST_ASSERT_FALSE(recoveryShouldStartMain(RecoveryReason::Wifi, 0, false, true));
|
||||
TEST_ASSERT_FALSE(recoveryShouldStartMain(RecoveryReason::Wifi, RECOVERY_TIME * 10, false, true));
|
||||
TEST_ASSERT_FALSE(recoveryShouldStartMain(RecoveryReason::Wifi, RECOVERY_MIN_TIME - 1, true, true));
|
||||
TEST_ASSERT_TRUE(recoveryShouldStartMain(RecoveryReason::Wifi, RECOVERY_MIN_TIME, true, true));
|
||||
}
|
||||
|
||||
void test_recovery_for_other_reasons_waits_recovery_time()
|
||||
{
|
||||
const RecoveryReason reasons[] = {RecoveryReason::Crash, RecoveryReason::Manual,
|
||||
RecoveryReason::PowerCycle, RecoveryReason::None};
|
||||
for (RecoveryReason reason : reasons)
|
||||
{
|
||||
TEST_ASSERT_FALSE(recoveryShouldStartMain(reason, RECOVERY_TIME - 1, true, true));
|
||||
TEST_ASSERT_TRUE(recoveryShouldStartMain(reason, RECOVERY_TIME, true, true));
|
||||
// The time counts, not the WiFi: an OTA upload over the setup WiFi is possible
|
||||
TEST_ASSERT_TRUE(recoveryShouldStartMain(reason, RECOVERY_TIME, false, true));
|
||||
}
|
||||
}
|
||||
|
||||
void test_recovery_never_starts_missing_clock_firmware()
|
||||
{
|
||||
TEST_ASSERT_FALSE(recoveryShouldStartMain(RecoveryReason::Wifi, RECOVERY_TIME, true, false));
|
||||
TEST_ASSERT_FALSE(recoveryShouldStartMain(RecoveryReason::Manual, RECOVERY_TIME, true, false));
|
||||
}
|
||||
|
||||
void test_every_recovery_reason_has_a_text()
|
||||
{
|
||||
for (uint8_t r = 0; r <= (uint8_t)RecoveryReason::PowerCycle; r++)
|
||||
TEST_ASSERT_TRUE(strlen(recoveryReasonText((RecoveryReason)r)) > 0);
|
||||
TEST_ASSERT_TRUE(strcmp(recoveryReasonText(RecoveryReason::Wifi),
|
||||
recoveryReasonText(RecoveryReason::Crash)) != 0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Status LED
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -434,6 +477,12 @@ int main()
|
||||
RUN_TEST(test_new_firmware_needs_time_and_wifi_to_be_accepted);
|
||||
RUN_TEST(test_crash_count_cleared_after_running_long_enough);
|
||||
|
||||
RUN_TEST(test_quick_power_cycles_request_recovery);
|
||||
RUN_TEST(test_recovery_for_wifi_starts_clock_when_wifi_works);
|
||||
RUN_TEST(test_recovery_for_other_reasons_waits_recovery_time);
|
||||
RUN_TEST(test_recovery_never_starts_missing_clock_firmware);
|
||||
RUN_TEST(test_every_recovery_reason_has_a_text);
|
||||
|
||||
RUN_TEST(test_led_off_while_display_off);
|
||||
RUN_TEST(test_led_blinks_slow_with_wifi_and_fast_without);
|
||||
|
||||
|
||||
Reference in new issue
Block a user