mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 22:02:17 +01:00
refactor: name release assets from the board's chip model
Review follow-up for #72. - releaseAssetName() takes ConfigSettings::chipModel ("", "s3", "c3", "c6"), so GitOTA no longer keeps its own chip switch. C3 keeps its name for when the build comes back. - hasFS is set only when this board's own LittleFS image is in the release. isFsAsset() is gone; it also matched the old unsuffixed littlefs.bin, which the updater no longer asks for. - releaseAssetName() returns void: no caller checked the result and every name fits currentFile. - Both manual-upload hints name this board's file. - KNOWN_ISSUES: the "Main" install can't work, the repo holds no .bin files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
ab7eae3d94
commit
8196bd20e6
6 changed files with 35 additions and 55 deletions
|
|
@ -4834,7 +4834,8 @@ class Firmware {
|
||||||
updateFirmware() {
|
updateFirmware() {
|
||||||
let div = this.createFileUploader('/updateFirmware');
|
let div = this.createFileUploader('/updateFirmware');
|
||||||
let inst = div.querySelector('div[id=divInstText]');
|
let inst = div.querySelector('div[id=divInstText]');
|
||||||
let html = '<div style="font-size:14px;margin-bottom:20px;">Select a binary file [SomfyController.ino.esp32.bin] containing the device firmware then press the Upload File button.</div>';
|
let chip = document.getElementById('divContainer').getAttribute('data-chipmodel') || '';
|
||||||
|
let html = `<div style="font-size:14px;margin-bottom:20px;">Select a binary file [SomfyController.ino.esp32${chip}.bin] containing the device firmware then press the Upload File button.</div>`;
|
||||||
if (this.isMobile()) {
|
if (this.isMobile()) {
|
||||||
html += `<div style="width:100%;color:red;text-align:center;font-weight:bold;"><span style="margin-top:7px;width:100%;background:yellow;padding:3px;display:inline-block;border-radius:5px;background:white;">WARNING<span></div>`;
|
html += `<div style="width:100%;color:red;text-align:center;font-weight:bold;"><span style="margin-top:7px;width:100%;background:yellow;padding:3px;display:inline-block;border-radius:5px;background:white;">WARNING<span></div>`;
|
||||||
html += '<hr/><div style="font-size:14px;margin-bottom:10px;">This browser does not support automatic backups. It is highly recommended that you back up your configuration using the backup button before proceeding.</div>';
|
html += '<hr/><div style="font-size:14px;margin-bottom:10px;">This browser does not support automatic backups. It is highly recommended that you back up your configuration using the backup button before proceeding.</div>';
|
||||||
|
|
@ -4849,7 +4850,8 @@ class Firmware {
|
||||||
let div = this.createFileUploader('/updateApplication');
|
let div = this.createFileUploader('/updateApplication');
|
||||||
general.reloadApp = true;
|
general.reloadApp = true;
|
||||||
let inst = div.querySelector('div[id=divInstText]');
|
let inst = div.querySelector('div[id=divInstText]');
|
||||||
inst.innerHTML = '<div style="font-size:14px;">Select a binary file [SomfyController.littlefs.<chip>.bin, e.g. SomfyController.littlefs.esp32.bin] containing the littlefs data for the application then press the Upload File button.</div>';
|
let chip = document.getElementById('divContainer').getAttribute('data-chipmodel') || '';
|
||||||
|
inst.innerHTML = `<div style="font-size:14px;">Select a binary file [SomfyController.littlefs.esp32${chip}.bin] containing the littlefs data for the application then press the Upload File button.</div>`;
|
||||||
if (this.isMobile()) {
|
if (this.isMobile()) {
|
||||||
inst.innerHTML += `<div style="width:100%;color:red;text-align:center;font-weight:bold;"><span style="margin-top:7px;width:100%;background:yellow;padding:3px;display:inline-block;border-radius:5px;background:white;">WARNING<span></div>`;
|
inst.innerHTML += `<div style="width:100%;color:red;text-align:center;font-weight:bold;"><span style="margin-top:7px;width:100%;background:yellow;padding:3px;display:inline-block;border-radius:5px;background:white;">WARNING<span></div>`;
|
||||||
inst.innerHTML += '<hr/><div style="font-size:14px;margin-bottom:10px;">This browser does not support automatic backups. It is highly recommended that you back up your configuration using the backup button before proceeding.</div>';
|
inst.innerHTML += '<hr/><div style="font-size:14px;margin-bottom:10px;">This browser does not support automatic backups. It is highly recommended that you back up your configuration using the backup button before proceeding.</div>';
|
||||||
|
|
|
||||||
|
|
@ -267,3 +267,10 @@ On 2026-10-19 the log shows `web GET /controller from 192.168.1.197 total took 2
|
||||||
- **Fixed: a command for an unknown shade left no trace.** `handleShadeCommand`, `handleTiltCommand` and `handleGroupCommand` in [src/entryPoints/Web.cpp](../src/entryPoints/Web.cpp) now log a `not found` warning. On 2026-10-18 Home Assistant sent 10 commands to a device that had no shades yet, and the log showed only the response times.
|
- **Fixed: a command for an unknown shade left no trace.** `handleShadeCommand`, `handleTiltCommand` and `handleGroupCommand` in [src/entryPoints/Web.cpp](../src/entryPoints/Web.cpp) now log a `not found` warning. On 2026-10-18 Home Assistant sent 10 commands to a device that had no shades yet, and the log showed only the response times.
|
||||||
- **Fixed: `last ping 0ms ago` meant the client never pinged.** The disconnect line in [src/outputs/SocketEmitter.cpp](../src/outputs/SocketEmitter.cpp) now says `never pinged`. Browsers don't ping, so they always showed it.
|
- **Fixed: `last ping 0ms ago` meant the client never pinged.** The disconnect line in [src/outputs/SocketEmitter.cpp](../src/outputs/SocketEmitter.cpp) now says `never pinged`. Browsers don't ping, so they always showed it.
|
||||||
- **Open: `.gz does not exist` errors are noise.** `serveStatic` tries `<file>.gz` first. For files stored without one (`appversion`, `icon.png`), LittleFS logs an `E`-level `does not exist, no permits for creation` line on every request. The fix would be for `minify.py` to gzip the plain files too. `setTryGzipFirst(false)` doesn't help: the error comes from `exists()` probing the missing variant, so it would only move the noise to the gzip-only files.
|
- **Open: `.gz does not exist` errors are noise.** `serveStatic` tries `<file>.gz` first. For files stored without one (`appversion`, `icon.png`), LittleFS logs an `E`-level `does not exist, no permits for creation` line on every request. The fix would be for `minify.py` to gzip the plain files too. `setTryGzipFirst(false)` doesn't help: the error comes from `exists()` probing the missing variant, so it would only move the noise to the gzip-only files.
|
||||||
|
|
||||||
|
## Installing "Main" from the update dialog always fails
|
||||||
|
|
||||||
|
**Status:** open. Found 2026-10-20 while reviewing PR #72.
|
||||||
|
**Location:** `GitUpdater::beginUpdate` in [src/GitOTA.cpp](../src/GitOTA.cpp).
|
||||||
|
|
||||||
|
The update dialog offers a "Main" entry next to the releases. For it, the updater downloads from `https://raw.githubusercontent.com/cjkas/ESPSomfy-RTS/master/`, but the repository holds no `.bin` files, so the firmware download 404s. Nothing is written and the device keeps running, so it does no harm, but the option can't work. Either drop the entry or point it at a build that publishes per-chip images.
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
#include <Update.h>
|
#include <Update.h>
|
||||||
#include <HTTPClient.h>
|
#include <HTTPClient.h>
|
||||||
#include <esp_task_wdt.h>
|
#include <esp_task_wdt.h>
|
||||||
#include <esp_chip_info.h>
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "ConfigSettings.h"
|
#include "ConfigSettings.h"
|
||||||
#include "GitOTA.h"
|
#include "GitOTA.h"
|
||||||
|
|
@ -43,7 +42,9 @@ void GitRelease::setReleaseProperty(const char *key, const char *val) {
|
||||||
void GitRelease::setAssetProperty(const char *key, const char *val) {
|
void GitRelease::setAssetProperty(const char *key, const char *val) {
|
||||||
if(strcmp(key, "name") == 0) {
|
if(strcmp(key, "name") == 0) {
|
||||||
//Serial.println(val);
|
//Serial.println(val);
|
||||||
if(isFsAsset(val)) this->hasFS = true;
|
char fsFile[64];
|
||||||
|
releaseAssetName(fsFile, sizeof(fsFile), "littlefs", settings.chipModel);
|
||||||
|
if(strcmp(val, fsFile) == 0) this->hasFS = true;
|
||||||
else if(strstr(val, "ino.esp32.bin")) {
|
else if(strstr(val, "ino.esp32.bin")) {
|
||||||
if(strlen(this->hwVersions)) strcat(this->hwVersions, ",");
|
if(strlen(this->hwVersions)) strcat(this->hwVersions, ",");
|
||||||
strcat(this->hwVersions, "32");
|
strcat(this->hwVersions, "32");
|
||||||
|
|
@ -353,19 +354,6 @@ void GitUpdater::emitDownloadProgress(uint8_t num, size_t total, size_t loaded,
|
||||||
sockEmit.loop();
|
sockEmit.loop();
|
||||||
webServer.loop();
|
webServer.loop();
|
||||||
}
|
}
|
||||||
// The chip part of this board's release asset names.
|
|
||||||
static const char *chipName() {
|
|
||||||
esp_chip_info_t ci;
|
|
||||||
esp_chip_info(&ci);
|
|
||||||
switch(ci.model) {
|
|
||||||
case esp_chip_model_t::CHIP_ESP32S3: return "esp32s3";
|
|
||||||
case esp_chip_model_t::CHIP_ESP32S2: return "esp32s2";
|
|
||||||
case esp_chip_model_t::CHIP_ESP32C3: return "esp32c3";
|
|
||||||
case esp_chip_model_t::CHIP_ESP32C6: return "esp32c6";
|
|
||||||
default: return "esp32";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GitUpdater::beginUpdate(const char *version) {
|
bool GitUpdater::beginUpdate(const char *version) {
|
||||||
ESP_LOGI(TAG, "Begin update called...");
|
ESP_LOGI(TAG, "Begin update called...");
|
||||||
if(strcmp(version, "Main") == 0) strcpy(this->baseUrl, "https://raw.githubusercontent.com/cjkas/ESPSomfy-RTS/master/");
|
if(strcmp(version, "Main") == 0) strcpy(this->baseUrl, "https://raw.githubusercontent.com/cjkas/ESPSomfy-RTS/master/");
|
||||||
|
|
@ -373,14 +361,14 @@ bool GitUpdater::beginUpdate(const char *version) {
|
||||||
|
|
||||||
strcpy(this->targetRelease, version);
|
strcpy(this->targetRelease, version);
|
||||||
this->emitUpdateCheck();
|
this->emitUpdateCheck();
|
||||||
releaseAssetName(this->currentFile, sizeof(this->currentFile), "ino", chipName());
|
releaseAssetName(this->currentFile, sizeof(this->currentFile), "ino", settings.chipModel);
|
||||||
this->partition = U_FLASH;
|
this->partition = U_FLASH;
|
||||||
this->lockFS = this->cancelled = false;
|
this->lockFS = this->cancelled = false;
|
||||||
this->error = 0;
|
this->error = 0;
|
||||||
this->error = this->downloadFile();
|
this->error = this->downloadFile();
|
||||||
if(this->error == 0 && !this->cancelled) {
|
if(this->error == 0 && !this->cancelled) {
|
||||||
somfy.commit();
|
somfy.commit();
|
||||||
releaseAssetName(this->currentFile, sizeof(this->currentFile), "littlefs", chipName());
|
releaseAssetName(this->currentFile, sizeof(this->currentFile), "littlefs", settings.chipModel);
|
||||||
this->partition = U_SPIFFS;
|
this->partition = U_SPIFFS;
|
||||||
this->lockFS = true;
|
this->lockFS = true;
|
||||||
this->error = this->downloadFile();
|
this->error = this->downloadFile();
|
||||||
|
|
@ -400,7 +388,7 @@ bool GitUpdater::beginUpdate(const char *version) {
|
||||||
}
|
}
|
||||||
bool GitUpdater::recoverFilesystem() {
|
bool GitUpdater::recoverFilesystem() {
|
||||||
sprintf(this->baseUrl, "https://github.com/cjkas/ESPSomfy-RTS/releases/download/%s/", settings.fwVersion.name);
|
sprintf(this->baseUrl, "https://github.com/cjkas/ESPSomfy-RTS/releases/download/%s/", settings.fwVersion.name);
|
||||||
releaseAssetName(this->currentFile, sizeof(this->currentFile), "littlefs", chipName());
|
releaseAssetName(this->currentFile, sizeof(this->currentFile), "littlefs", settings.chipModel);
|
||||||
this->status = GIT_UPDATING;
|
this->status = GIT_UPDATING;
|
||||||
this->partition = U_SPIFFS;
|
this->partition = U_SPIFFS;
|
||||||
this->lockFS = true;
|
this->lockFS = true;
|
||||||
|
|
|
||||||
|
|
@ -150,13 +150,8 @@ bool worthRoaming(bool connected, int currentRssi, int apRssi, int minGain) {
|
||||||
bool otaProven(bool networkUp, unsigned long uptimeMs, unsigned long minUptimeMs) {
|
bool otaProven(bool networkUp, unsigned long uptimeMs, unsigned long minUptimeMs) {
|
||||||
return networkUp && uptimeMs >= minUptimeMs;
|
return networkUp && uptimeMs >= minUptimeMs;
|
||||||
}
|
}
|
||||||
bool releaseAssetName(char *buf, size_t size, const char *kind, const char *chip) {
|
void releaseAssetName(char *buf, size_t size, const char *kind, const char *chipModel) {
|
||||||
int n = snprintf(buf, size, "SomfyController.%s.%s.bin", kind, chip);
|
snprintf(buf, size, "SomfyController.%s.esp32%s.bin", kind, chipModel);
|
||||||
return n >= 0 && (size_t)n < size;
|
|
||||||
}
|
|
||||||
bool isFsAsset(const char *name) {
|
|
||||||
size_t len = strlen(name);
|
|
||||||
return strstr(name, ".littlefs.") && len >= 4 && strcmp(name + len - 4, ".bin") == 0;
|
|
||||||
}
|
}
|
||||||
const char *wifiAuthModeName(uint8_t authMode) {
|
const char *wifiAuthModeName(uint8_t authMode) {
|
||||||
switch(authMode) {
|
switch(authMode) {
|
||||||
|
|
|
||||||
10
src/Utils.h
10
src/Utils.h
|
|
@ -86,12 +86,10 @@ heap_emit_t heapEmitTarget(uint8_t num, uint32_t sinceLastMs, uint32_t intervalM
|
||||||
// update has proven itself: it has run for minUptimeMs and the network is
|
// update has proven itself: it has run for minUptimeMs and the network is
|
||||||
// up. Until then a reset rolls back to the previous firmware.
|
// up. Until then a reset rolls back to the previous firmware.
|
||||||
bool otaProven(bool networkUp, unsigned long uptimeMs, unsigned long minUptimeMs);
|
bool otaProven(bool networkUp, unsigned long uptimeMs, unsigned long minUptimeMs);
|
||||||
// A release asset's name: "SomfyController.<kind>.<chip>.bin", kind "ino" for
|
// A release asset's name: "SomfyController.<kind>.esp32<chipModel>.bin", kind
|
||||||
// the firmware or "littlefs" for the web UI image, chip e.g. "esp32s3". False
|
// "ino" for the firmware or "littlefs" for the web UI image, chipModel as in
|
||||||
// when it doesn't fit in size.
|
// ConfigSettings ("" for the ESP32, "s3", "c3", "c6").
|
||||||
bool releaseAssetName(char *buf, size_t size, const char *kind, const char *chip);
|
void releaseAssetName(char *buf, size_t size, const char *kind, const char *chipModel);
|
||||||
// Whether a release asset is a LittleFS image, for any chip.
|
|
||||||
bool isFsAsset(const char *name);
|
|
||||||
// How well loop() keeps up: the passes it made per second and its longest
|
// How well loop() keeps up: the passes it made per second and its longest
|
||||||
// pass, over the window since the last memStatus broadcast. Only the loop
|
// pass, over the window since the last memStatus broadcast. Only the loop
|
||||||
// task calls record(), rate(), maxUs() and publish(). publish() closes the
|
// task calls record(), rate(), maxUs() and publish(). publish() closes the
|
||||||
|
|
|
||||||
|
|
@ -273,31 +273,23 @@ static void test_otaProven_not_without_network() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* releaseAssetName / isFsAsset
|
* releaseAssetName
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
static void test_releaseAssetName_matches_the_release_workflow() {
|
static void test_releaseAssetName_matches_the_release_workflow() {
|
||||||
// .github/workflows/build.yaml fwname and fsname.
|
// .github/workflows/build.yaml fwname and fsname, from ConfigSettings::chipModel.
|
||||||
char buf[64];
|
char buf[64];
|
||||||
TEST_ASSERT_TRUE(releaseAssetName(buf, sizeof(buf), "ino", "esp32"));
|
releaseAssetName(buf, sizeof(buf), "ino", "");
|
||||||
TEST_ASSERT_EQUAL_STRING("SomfyController.ino.esp32.bin", buf);
|
TEST_ASSERT_EQUAL_STRING("SomfyController.ino.esp32.bin", buf);
|
||||||
TEST_ASSERT_TRUE(releaseAssetName(buf, sizeof(buf), "littlefs", "esp32s3"));
|
releaseAssetName(buf, sizeof(buf), "littlefs", "s3");
|
||||||
TEST_ASSERT_EQUAL_STRING("SomfyController.littlefs.esp32s3.bin", buf);
|
TEST_ASSERT_EQUAL_STRING("SomfyController.littlefs.esp32s3.bin", buf);
|
||||||
|
releaseAssetName(buf, sizeof(buf), "littlefs", "c6");
|
||||||
|
TEST_ASSERT_EQUAL_STRING("SomfyController.littlefs.esp32c6.bin", buf);
|
||||||
}
|
}
|
||||||
static void test_releaseAssetName_too_small_buffer() {
|
static void test_releaseAssetName_keeps_c3() {
|
||||||
char buf[16];
|
// C3 is out of the IDF 5.5 builds for now (ADR 0003) but is coming back.
|
||||||
TEST_ASSERT_FALSE(releaseAssetName(buf, sizeof(buf), "littlefs", "esp32c6"));
|
char buf[64];
|
||||||
TEST_ASSERT_EQUAL(sizeof(buf) - 1, strlen(buf));
|
releaseAssetName(buf, sizeof(buf), "ino", "c3");
|
||||||
}
|
TEST_ASSERT_EQUAL_STRING("SomfyController.ino.esp32c3.bin", buf);
|
||||||
static void test_isFsAsset_per_chip_images() {
|
|
||||||
TEST_ASSERT_TRUE(isFsAsset("SomfyController.littlefs.esp32.bin"));
|
|
||||||
TEST_ASSERT_TRUE(isFsAsset("SomfyController.littlefs.esp32c6.bin"));
|
|
||||||
TEST_ASSERT_TRUE(isFsAsset("SomfyController.littlefs.bin"));
|
|
||||||
}
|
|
||||||
static void test_isFsAsset_not_the_other_assets() {
|
|
||||||
TEST_ASSERT_FALSE(isFsAsset("SomfyController.ino.esp32.bin"));
|
|
||||||
TEST_ASSERT_FALSE(isFsAsset("SomfyController.onboard.esp32.bin.zip"));
|
|
||||||
TEST_ASSERT_FALSE(isFsAsset("SomfyController.littlefs.bin.sha256"));
|
|
||||||
TEST_ASSERT_FALSE(isFsAsset(""));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
|
|
@ -431,9 +423,7 @@ int main(int argc, char **argv) {
|
||||||
RUN_TEST(test_otaProven_not_before_the_minimum_uptime);
|
RUN_TEST(test_otaProven_not_before_the_minimum_uptime);
|
||||||
RUN_TEST(test_otaProven_not_without_network);
|
RUN_TEST(test_otaProven_not_without_network);
|
||||||
RUN_TEST(test_releaseAssetName_matches_the_release_workflow);
|
RUN_TEST(test_releaseAssetName_matches_the_release_workflow);
|
||||||
RUN_TEST(test_releaseAssetName_too_small_buffer);
|
RUN_TEST(test_releaseAssetName_keeps_c3);
|
||||||
RUN_TEST(test_isFsAsset_per_chip_images);
|
|
||||||
RUN_TEST(test_isFsAsset_not_the_other_assets);
|
|
||||||
RUN_TEST(test_wifiAuthModeName_matches_the_idf_enum);
|
RUN_TEST(test_wifiAuthModeName_matches_the_idf_enum);
|
||||||
RUN_TEST(test_wifiAuthModeName_unknown_past_the_shared_values);
|
RUN_TEST(test_wifiAuthModeName_unknown_past_the_shared_values);
|
||||||
RUN_TEST(test_heapEmitTarget_one_client_always_gets_it);
|
RUN_TEST(test_heapEmitTarget_one_client_always_gets_it);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue