From 3635ac7222124e5b144e7562e8ab3efd9d3f9a01 Mon Sep 17 00:00:00 2001 From: Brandon Harvey <8107750+bharvey88@users.noreply.github.com> Date: Wed, 8 Jul 2026 15:57:42 -0500 Subject: [PATCH] Fix beta manifest fetch and guard force-install against stale manifests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hardware testing surfaced two OTA bugs (thanks Brandon): - GitHub release-asset URLs answer with a redirect whose signed Location header exceeds esp_http_client's 512-byte default rx buffer, so every beta-channel manifest fetch failed with "HTTP_CLIENT: Out of buffer". Set buffer_size_rx: 2048 on all images. - update.perform(force) installs whatever manifest was last fetched successfully. Combined with the fetch failure above, pressing Firmware Update on the Beta channel silently installed the cached STABLE manifest - downgrading the device to the old image (which also wiped its saved settings, including WiFi, on boot). The button now verifies the cached manifest URL matches the selected channel and variant before performing, and refuses with a clear log line otherwise. Version: 26.7.8.6 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- Integrations/ESPHome/Core.yaml | 22 ++++++++++++++++++---- Integrations/ESPHome/MSR-1.yaml | 4 ++++ Integrations/ESPHome/MSR-1_BLE.yaml | 4 ++++ Integrations/ESPHome/MSR-1_Factory.yaml | 4 ++++ 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index 8cc47bf..c306271 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -1,5 +1,5 @@ substitutions: - version: "26.7.8.5" + version: "26.7.8.6" device_description: ${name} made by Apollo Automation - version ${version}. # Default OTA password. Override in your device YAML by re-declaring # `substitutions: { ota_password: !secret _ota_password }` so each @@ -707,9 +707,23 @@ button: # condition to wait on (update.is_available stays false for same-version # variant switches), so give it a fixed window like R_PRO-1/CAST-1 do. - delay: 5s - - update.perform: - id: update_http_request - force_update: true + # perform() installs whatever manifest was last fetched successfully - + # if the refresh above failed (e.g. network blip), that can be the OTHER + # channel's image. Refuse instead of installing the wrong firmware. + - lambda: |- + const bool want_beta = id(firmware_channel).current_option() == "Beta"; + const bool want_ble = id(firmware_ble).current_option() == "Enabled"; + const std::string &url = id(update_http_request).update_info.firmware_url; + const bool url_beta = url.find("/releases/download/") != std::string::npos; + const bool url_ble = url.find("ble") != std::string::npos; + if (url.empty() || url_beta != want_beta || url_ble != want_ble) { + ESP_LOGE("firmware", + "Cached manifest (%s) does not match the selected channel/variant - " + "the manifest refresh likely failed. Not installing; press again.", + url.empty() ? "" : url.c_str()); + } else { + id(update_http_request).perform(true); + } # Only reached if the update did not start (e.g. manifest unreachable). - lambda: |- #ifdef USE_ESP32_BLE diff --git a/Integrations/ESPHome/MSR-1.yaml b/Integrations/ESPHome/MSR-1.yaml index 0b83d1f..bbf591f 100644 --- a/Integrations/ESPHome/MSR-1.yaml +++ b/Integrations/ESPHome/MSR-1.yaml @@ -47,6 +47,10 @@ web_server: http_request: verify_ssl: true + # GitHub release-asset downloads answer with a redirect whose signed + # Location header exceeds the 512-byte default and fails with + # "HTTP_CLIENT: Out of buffer". + buffer_size_rx: 2048 safe_mode: diff --git a/Integrations/ESPHome/MSR-1_BLE.yaml b/Integrations/ESPHome/MSR-1_BLE.yaml index 86aa45a..d846901 100644 --- a/Integrations/ESPHome/MSR-1_BLE.yaml +++ b/Integrations/ESPHome/MSR-1_BLE.yaml @@ -47,6 +47,10 @@ bluetooth_proxy: http_request: verify_ssl: true + # GitHub release-asset downloads answer with a redirect whose signed + # Location header exceeds the 512-byte default and fails with + # "HTTP_CLIENT: Out of buffer". + buffer_size_rx: 2048 safe_mode: diff --git a/Integrations/ESPHome/MSR-1_Factory.yaml b/Integrations/ESPHome/MSR-1_Factory.yaml index 0b14b27..d74805b 100644 --- a/Integrations/ESPHome/MSR-1_Factory.yaml +++ b/Integrations/ESPHome/MSR-1_Factory.yaml @@ -45,6 +45,10 @@ ota: http_request: verify_ssl: true + # GitHub release-asset downloads answer with a redirect whose signed + # Location header exceeds the 512-byte default and fails with + # "HTTP_CLIENT: Out of buffer". + buffer_size_rx: 2048 safe_mode: