Skip to content

OTA: upload a custom firmware.bin from the web UI - #175

Open
fl4p wants to merge 2 commits into
dchristl:masterfrom
fl4p:upload-firmware-button
Open

OTA: upload a custom firmware.bin from the web UI#175
fl4p wants to merge 2 commits into
dchristl:masterfrom
fl4p:upload-firmware-button

Conversation

@fl4p

@fl4p fl4p commented May 23, 2026

Copy link
Copy Markdown

/ota only fetches a hardcoded GitHub URL — breaks any workflow that wants to flash a dev build or a fork without USB access.

POST /uploadfw accepts the firmware as the raw request body (no multipart). The handler streams 4 KB chunks straight into esp_ota_write() on the inactive partition, calls esp_ota_set_boot_partition(), schedules a 2s restart via the existing restartByTimerinS(). Lock-aware. NVS untouched, settings survive.

pages/ota.html adds a file picker + a confirm-on-click button + an inline progress bar; XHR with Content-Type: application/octet-stream.

Tested live: 1.4 MB upload → HTTP 200 in 8.8s → reboot in ~1s → device back on the same IP with all settings.

Complements #176 (edit the OTA URL instead of replacing the path). First commit is a build-fix shared with #174/#176.

claude added 2 commits May 23, 2026 08:23
Builds against framework-espidf 5.5.0 fail with implicit-declaration
errors for GPIO_IS_VALID_GPIO and gpio_wakeup_enable in deep_sleep /
light_sleep. driver/rtc_io.h no longer pulls in driver/gpio.h
transitively on this IDF version.
The existing OTA flow fetches an HTTPS image from a hardcoded GitHub URL,
which is unusable when developing patches against a fork. Add a file
picker + raw-binary POST upload to the OTA page.

Frontend: ota.html grows a "Upload custom firmware" section with file
input, a flash button, and an inline progress bar. Submission uses
fetch/XHR with the File object as the request body — no multipart
parsing on the device side.

Backend: src/urihandler/uploadfwhandler.c streams the body in 4 KB
chunks straight through esp_ota_write() to the inactive OTA slot, calls
esp_ota_set_boot_partition() on success, and schedules a 2-second
restart via the existing restartByTimer infrastructure. Lock-aware
(redirects to /lock when UI is locked). NVS is not touched, so settings
survive.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants