Consolidate firmware UI; server learns board from the device, not a picker
Build and push server image / build-and-push (push) Successful in 37s

All firmware-related controls (manual upload, Gitea repo URL,
auto-update checkbox, detected board, Update frame button) now live in
one "Firmware update" card instead of being split across the main
Settings form and a separate card.

The board variant used to pick a Gitea release asset was a dropdown
the user had to set by hand and could get wrong. The device now
reports it itself via a new X-Frame-Board header (CONFIG_FRAME_BOARD_NAME,
"devkit" by default, "xiao" in sdkconfig.xiao) on every /frame/config
poll, stored as device_board_variant -- the server learns it instead.
Update checks/applies are gated on the board being known, since there's
nothing to fetch until a device has checked in at least once.
This commit is contained in:
2026-07-21 21:58:59 -04:00
parent ad1fa99064
commit 7ea5c9a4fb
7 changed files with 128 additions and 60 deletions
+15
View File
@@ -1,5 +1,20 @@
menu "ESPresso Frame Configuration"
config FRAME_BOARD_NAME
string "Board variant name, reported to the server"
default "devkit"
help
Sent as the X-Frame-Board request header on every
GET /frame/config poll, so the server can learn which board
this device is and automatically fetch the right OTA build
from a configured Gitea repo's releases -- no manual "which
board" picker in the web UI. Must match one of the asset
names .gitea/workflows/firmware-release-build.yml publishes
(firmware-<name>.bin): "devkit" (this default, for the
plain ESP32-C6-DevKitC-1 build) or "xiao" (set via
sdkconfig.xiao for the Seeed XIAO ESP32-C6 build -- see
build_for_board.sh).
config FRAME_XIAO_ANTENNA_INIT
bool "Select onboard antenna on Seeed XIAO ESP32-C6 (RF switch init)"
default n
+8 -3
View File
@@ -342,9 +342,13 @@ static bool json_extract_string(const char *json, const char *key, char *out, si
/* GETs the server's /frame/config -- doubles as both the reachability
* check (any completed HTTP response means the socket-level connection
* succeeded), the source of the server-configurable refresh interval,
* and (via the X-Frame-Version request header / firmware_version
* response field) the device's OTA update check -- piggybacked on a
* request already made every wake, no extra round trip. */
* and (via the X-Frame-Version/X-Frame-Board request headers and
* firmware_version response field) the device's OTA update check --
* piggybacked on a request already made every wake, no extra round
* trip. X-Frame-Board lets the server learn which board this device is
* (CONFIG_FRAME_BOARD_NAME) so it can pick the right Gitea release
* asset itself, instead of a user manually selecting a board in the
* web UI. */
static frame_server_config_t fetch_frame_config(const frame_config_t *cfg)
{
frame_server_config_t result = {
@@ -364,6 +368,7 @@ static frame_server_config_t fetch_frame_config(const frame_config_t *cfg)
};
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_set_header(client, "X-Frame-Version", esp_app_get_description()->version);
esp_http_client_set_header(client, "X-Frame-Board", CONFIG_FRAME_BOARD_NAME);
esp_err_t err = esp_http_client_open(client, 0);
if (err != ESP_OK) {
+2
View File
@@ -8,6 +8,8 @@ CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_xiao.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions_xiao.csv"
CONFIG_FRAME_BOARD_NAME="xiao"
# Powers the XIAO's RF switch and selects its onboard antenna -- without
# this the softAP/STA radio doesn't reliably reach the antenna at all.
# See the Kconfig help text (FRAME_XIAO_ANTENNA_INIT) for why.