Skip to content

Add OTA firmware upload via web interface#233

Open
W-Floyd wants to merge 4 commits into
CarlosDerSeher:developfrom
W-Floyd:feat/web-ota
Open

Add OTA firmware upload via web interface#233
W-Floyd wants to merge 4 commits into
CarlosDerSeher:developfrom
W-Floyd:feat/web-ota

Conversation

@W-Floyd

@W-Floyd W-Floyd commented Jun 7, 2026

Copy link
Copy Markdown
image

Adds an OTA Update tab to the web UI, gated behind CONFIG_SNAPCLIENT_WEB_OTA (default y). Features:

  • POST /api/ota/upload: streams the firmware binary to the inactive OTA partition in 4 KB chunks, stops snapclient beforehand, validates with esp_ota_end(), sets the boot partition, and restarts. Sets Connection: close on the response to avoid a spurious httpd recv warning.

  • GET /api/ota/status: returns running firmware info (version, project name, build date, IDF version, SHA256) via esp_app_get_description(), so the frontend can confirm the new image booted after restart.

  • ota-update.html: side-by-side current/selected firmware cards. The selected .bin is parsed entirely in the browser by scanning for the esp_app_desc magic word (0xABCD5432) and reading the fixed struct layout, giving an immediate preview with SHA256 match/diff indicator before upload. After flashing, polls /api/ota/status until the device responds and confirms the new firmware is running.

  • Kconfig: CONFIG_SNAPCLIENT_WEB_OTA bool under "HTTP Server Setting", default y. All C code, route registrations, and embedded file refs are guarded by this flag. The OTA tab is shown/hidden via the existing capabilities mechanism (web_ota_enabled field in /capabilities).

Adds an OTA Update tab to the web UI, gated behind CONFIG_SNAPCLIENT_WEB_OTA
(default y). Features:

- POST /api/ota/upload: streams the firmware binary to the inactive OTA
  partition in 4 KB chunks, stops snapclient beforehand, validates with
  esp_ota_end(), sets the boot partition, and restarts. Sets
  Connection: close on the response to avoid a spurious httpd recv warning.

- GET /api/ota/status: returns running firmware info (version, project
  name, build date, IDF version, SHA256) via esp_app_get_description(),
  so the frontend can confirm the new image booted after restart.

- ota-update.html: side-by-side current/selected firmware cards. The
  selected .bin is parsed entirely in the browser by scanning for the
  esp_app_desc magic word (0xABCD5432) and reading the fixed struct
  layout, giving an immediate preview with SHA256 match/diff indicator
  before upload. After flashing, polls /api/ota/status until the device
  responds and confirms the new firmware is running.

- Kconfig: CONFIG_SNAPCLIENT_WEB_OTA bool under "HTTP Server Setting",
  default y. All C code, route registrations, and embedded file refs
  are guarded by this flag. The OTA tab is shown/hidden via the existing
  capabilities mechanism (web_ota_enabled field in /capabilities).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@CarlosDerSeher

CarlosDerSeher commented Jun 7, 2026

Copy link
Copy Markdown
Owner

I like it. How does this integrate with the existing OTA implementation? Should we somehow merge this or drop the other one?

W-Floyd and others added 2 commits June 8, 2026 00:03
Remove the redundant "same as running" label from the Current Firmware
card (it's always true there). Also fix the post-flash success banner
showing "different" by updating currentSha256 before rendering the meta.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Show error when device restarts with same SHA256 as before (OTA rolled back)
- Show warning when no pre-upload baseline exists (can't verify outcome)
- Fix SHA256 label always showing "same as running" by updating currentSha256
  after renderMeta() so the comparison is against the pre-upload firmware

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@W-Floyd

W-Floyd commented Jun 8, 2026

Copy link
Copy Markdown
Author

It's independent of existing OTA. Seeing as this can be called using curl as well, I see no reason to keep old OTA mechanism once this is to you're liking. Obviously lots of Claude, but it's been working well for me so far.

@W-Floyd

W-Floyd commented Jun 8, 2026

Copy link
Copy Markdown
Author

Not something in this branch, or even to merge, but I have a OTA pull mechanism I'm using here.
image

@CarlosDerSeher

Copy link
Copy Markdown
Owner

Could you seperate the ota code to another c/h file maybe ? I fear the ui_http c file will be hard to read if it increases more in the future.

Splits all OTA API handler code out of ui_http_server.c into a
dedicated ota_handlers.c / ota_handlers.h pair as requested by
maintainer. ui_http_server.c now delegates route registration via
a single ota_register_handlers(server) call.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
return ESP_OK;
}

static void restart_task(void *pv) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this to be a task?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy-paste carryover from https://github.com/CarlosDerSeher/snapclient/blob/master/components/ui_http_server/ui_http_server.c#L608-L615. Not certain, but I don't think we need it to be a task in either place.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Should be OK for now though

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