add recovery firmware with OTA updater and recovery web interface

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
proddy
2026-10-06 22:57:25 +02:00
co-authored by Cursor
parent 1375f87163
commit 6411b6ffbd
59 changed files with 3595 additions and 339 deletions
+64 -1
View File
@@ -73,6 +73,10 @@ board_upload.flash_size = 16MB
board_build.app_partition_name = app0
platform = https://github.com/tasmota/platform-espressif32/releases/download/2026.05.50/platform-espressif32.zip ; Tasmota Arduino Core 3.3.8 based on IDF 5.5.4.260407
; platform = https://github.com/tasmota/platform-espressif32/releases/download/2026.09.50/platform-espressif32.zip ; Tasmota Arduino Core 3.3.12 based on IDF 5.5.5
build_flags =
${common.build_flags}
-D EMSESP_HAS_RECOVERY ; installs and falls back to the recovery firmware in the factory partition
-D OTA_UPDATER_ANY_PARTITION ; so the recovery firmware can be uploaded into the factory partition
; 32MB Flash variants
[espressif32_base_32M]
@@ -163,12 +167,69 @@ build_flags =
; XIAO ESP32C - 512KB SRAM & 4MB Flash - https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/
[env:c6_xiao_4M]
extends = espressif32_base_4M
board_build.app_partition_name = app0
board = seeed_xiao_esp32c6
build_flags =
${common.build_flags}
-DEMSESP_EN_ONLY
; Crash test builds for the bootloader rollback and the recovery fallback. Install with the web upload, not over
; serial, since a serial flash boots the recovery. Change EMSESP_CRASH_TEST to pick the test:
; 1 crashes on every start, so the bootloader rolls back to the previous firmware
; 2 runs normally until it's confirmed after 2 minutes, then crashes on every start. After 5 crashes in a row
; it switches to the recovery firmware. Without one it keeps crashing until reflashed over serial
[env:crashtest_s3_16M_P]
extends = env:s3_16M_P
build_flags =
${espressif32_base_16M.build_flags}
-D EMSESP_CRASH_TEST=1
custom_fw_name = EMS-ESP-CrashTest
; EMS-ESP Recovery - a small app for the factory (boot) partition with an access point and a firmware upload page.
; Only for boards with a factory partition (16MB). Sources are in ./recovery, the WebUI is built from ./interface.
; build: pio run -e recovery_s3_16M_P
; flash into the boot partition: pio run -e recovery_s3_16M_P -t upload
; run it from app0 like a normal app instead, add an [env:recovery_s3_16M_P] section to pio_local.ini with custom_app_offset =
; develop the WebUI with a mock: cd interface && pnpm recovery
[recovery_base]
extends = espressif32_base_16M
board_build.app_partition_name = boot
build_src_filter = -<*> +<../recovery/>
build_flags =
${factory_settings.build_flags}
-std=gnu++20 -Os
-D OTA_UPDATER_ANY_PARTITION
-D CONFIG_ASYNC_TCP_RUNNING_CORE=1
-D CONFIG_ASYNC_TCP_STACK_SIZE=8192
build_unflags =
${common.core_unbuild_flags}
lib_ldf_mode = chain
lib_deps =
bblanchon/ArduinoJson @ 7.4.3
ESP32Async/AsyncTCP @ 3.5.0
ESP32Async/ESPAsyncWebServer @ 3.12.1
extra_scripts =
pre:scripts/build_recovery_interface.py
post:scripts/set_app_desc.py
post:scripts/rename_fw.py
post:scripts/upload_factory.py
upload_protocol = esptool
custom_app_offset = 0x10000
custom_fw_name = EMS-ESP-Recovery
custom_version_file = recovery/recovery_version.h
custom_version_define = RECOVERY_VERSION
[env:recovery_s_16M]
extends = recovery_base
board = s_16M
[env:recovery_s_16M_P]
extends = recovery_base
board = s_16M_P
[env:recovery_s3_16M_P]
extends = recovery_base
board = s3_16M_P
; foundation for building and testing natively, standalone without an ESP32
; use the `standalone` environment instead of `native` for testing
[env:native]
@@ -199,6 +260,7 @@ build_src_filter =
-<../lib/uuid-syslog>
-<../lib/eModbus>
-<../lib/OneWire>
-<../lib/OtaUpdater>
-<../src/core/ModuleLibrary.cpp>
lib_ldf_mode = off
lib_deps =
@@ -242,6 +304,7 @@ build_src_filter =
-<../lib/uuid-syslog>
-<../lib/eModbus>
-<../lib/OneWire>
-<../lib/OtaUpdater>
-<../src/core/ModuleLibrary.cpp>
lib_ldf_mode = off
lib_deps = Unity