Skip to content

Commit 270a461

Browse files
committed
feat: reliable update detection + on-device install/check (settings + toolbar)
- updateCheck() now retries ~60s after a failed check instead of waiting 6h (a single transient failure used to hide an available update), runs ~15s after boot, and honors a manual 'check now' request. - Settings System 'Firmware' row is interactive: shows 'up to date' / 'checking...' / 'check failed' / '<tag> >' (update available); tap to install when available, else force a re-check. Live-refreshes. - Toolbar update icon/popup already present; now actually appears since detection is reliable. - Also carries the Nexus bars-fill-to-100 + 'DATA UPLINK COMPLETE'.
1 parent a95811a commit 270a461

5 files changed

Lines changed: 39 additions & 8 deletions

File tree

esp32-bms-lvgl/src/events.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,9 @@ static void dataTick_cb(lv_timer_t *t) {
323323
if (++vtick >= 2) { vtick = 0; invArea(0, 36, Wd - 1, 313); }
324324
}
325325
static void wifiTick_cb(lv_timer_t *t) {
326-
if (wifiPoll() && view == V_SETTINGS && !standby) lv_obj_invalidate(scr);
326+
bool ch = wifiPoll();
327+
static int8_t lastChk = 0; static bool lastAvail = false; // repaint Settings when the update state changes (checking → result / update found)
328+
if (updChkState != lastChk || updAvail != lastAvail) { lastChk = updChkState; lastAvail = updAvail; ch = true; }
329+
if (ch && view == V_SETTINGS && !standby) lv_obj_invalidate(scr);
327330
}
328331

esp32-bms-lvgl/src/ota.h

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,16 @@ static bool verNewer(const char *rel, const char *cur) {
3333
}
3434
// Ask GitHub for the latest RELEASE: its tag (= firmware version) and the firmware.bin
3535
// asset URL. updAvail = the released version differs from this build. Runs on core-0.
36-
static void updateCheck() {
37-
if (WiFi.status() != WL_CONNECTED || !timeSynced || otaActive) return; // cert validation needs a real clock
36+
// Returns true if GitHub answered with a valid release (so the caller can back off to the slow
37+
// 6h cadence); false on any network/TLS/parse failure (caller retries soon). updChkState feeds
38+
// the Settings row: 1=checking, 2=up-to-date, -1=check failed.
39+
static bool updateCheck() {
40+
if (WiFi.status() != WL_CONNECTED || !timeSynced || otaActive) return false; // cert validation needs a real clock
41+
updChkState = 1; // checking…
42+
bool got = false;
3843
WiFiClientSecure net; otaTrust(net);
3944
HTTPClient http; http.setConnectTimeout(5000); http.setTimeout(6000);
40-
if (!http.begin(net, "https://api.github.com/repos/holoduke/JKBMS/releases/latest")) return;
45+
if (!http.begin(net, "https://api.github.com/repos/holoduke/JKBMS/releases/latest")) { updChkState = -1; return false; }
4146
http.addHeader("User-Agent", "jkbms-device");
4247
if (http.GET() == 200) {
4348
JsonDocument filter; // keep only the fields we need (the release JSON is big)
@@ -55,10 +60,13 @@ static void updateCheck() {
5560
strncpy(updUrl, url, sizeof(updUrl) - 1); updUrl[sizeof(updUrl) - 1] = 0;
5661
const char *cur = instTag[0] ? instTag : FW_VERSION;
5762
updAvail = verNewer(updTag, cur); // only flag a genuinely NEWER release (not a downgrade)
63+
got = true;
5864
}
5965
}
6066
}
6167
http.end();
68+
updChkState = got ? (updAvail ? 0 : 2) : -1; // available→0 (icon speaks) / up-to-date→2 / failed→-1
69+
return got;
6270
}
6371
// One download+flash attempt of updUrl. Returns true only on a fully written, finalised image.
6472
// Streams the GitHub asset (→ signed CDN redirect) straight into the inactive app slot.
@@ -132,9 +140,15 @@ static void netTask(void *) {
132140
lastPoll = now;
133141
bmsRead(); // history sampling + energy integration run on core 1 (see bmsPoll_cb) to avoid a cross-core race on those buffers
134142
}
135-
if ((!lastUpd && now > 30000) || (lastUpd && now - lastUpd > 21600000UL)) { // GitHub release check ~30s after boot, then every 6h
136-
lastUpd = now; updateCheck();
137-
if (updAvail && autoUpdate) updGo = true; // auto-update enabled → flash it
143+
// GitHub release check: ~15s after boot, then every 6h — but if a check FAILS, retry in
144+
// ~60s instead of waiting 6h (a single transient failure used to hide an update until the
145+
// next 6h window). A manual "check now" (Settings row / web) forces it immediately.
146+
bool due = (!lastUpd && now > 15000) || (lastUpd && now - lastUpd > 21600000UL) || updCheckNow;
147+
if (due) {
148+
updCheckNow = false;
149+
bool ok = updateCheck();
150+
lastUpd = ok ? now : (now - 21600000UL + 60000UL); // ok → 6h; failed → retry in ~60s
151+
if (updAvail && autoUpdate) updGo = true; // auto-update enabled → flash it
138152
}
139153
if (updGo) { updGo = false; selfUpdate(); } // manual "Update now" (web) or auto trigger
140154
vTaskDelay(pdMS_TO_TICKS(20));

esp32-bms-lvgl/src/settings_ui.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ static void sysVal(int i, char *o, size_t n, uint32_t *vc) {
8181
case 20: snprintf(o, n, "%s", webPass); *vc = C_CYAN; break;
8282
case 21: snprintf(o, n, "%s", LANG_NAME[g_lang]); *vc = C_CYAN; break;
8383
case 22: snprintf(o, n, "%s", TZDEFS[tzSel].name); *vc = C_CYAN; break;
84+
case 11: // Firmware row: version + update status (tap to install when available, else re-check)
85+
if (updAvail) { snprintf(o, n, "%s >", updTag); *vc = C_ACCENT; } // newer release → tap to install
86+
else if (updChkState == 1) { snprintf(o, n, "checking..."); *vc = C_CYAN; }
87+
else if (updChkState == -1) { snprintf(o, n, "check failed"); *vc = C_BAD; }
88+
else if (updChkState == 2) { snprintf(o, n, "up to date"); *vc = C_ACCENT; }
89+
else { snprintf(o, n, "v" FW_VERSION); *vc = C_MUTED; }
90+
break;
8491
default: snprintf(o, n, "v" FW_VERSION); *vc = C_MUTED; break;
8592
}
8693
}

esp32-bms-lvgl/src/state.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ static char updTag[24] = ""; // latest release tag on GitHub
1111
static char instTag[24] = ""; // tag we last installed (NVS); empty → compare to FW_VERSION
1212
static char updUrl[160] = ""; // firmware.bin download URL of the latest release
1313
static volatile bool updGo = false; // request: download + flash the latest release now
14+
static volatile bool updCheckNow = false;// request: re-check GitHub for a release right now (Settings "check" / web)
15+
static volatile int8_t updChkState = 0; // 0 idle · 1 checking · 2 up-to-date · -1 check failed (UI feedback)
1416
static volatile int updProgress = -1; // -1 idle · 0..100 flashing % · -2 failed
1517
static bool updPopup = false; // top-bar update icon tapped → details modal
1618
static int updBoxL = 0, updBoxR = 0; // top-bar update-icon hit region

esp32-bms-lvgl/src/touch.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,12 @@ static void handleTap(int x, int y) {
8484
case 20: wifiPass[0] = 0; wifiPassLen = 0; kbMode = 0; kbTarget = KBT_WPASS; kbActive = true; return; // set a new web password
8585
case 21: g_lang = (g_lang + 1) % LANG_COUNT; markCfg(); return; // cycle UI language (dirtyFull already set → full repaint)
8686
case 22: tzSel = (tzSel + 1) % NTZ; applyTz(); break; // cycle timezone (clock strip refreshes on its 15s tick)
87-
default: return; // firmware row: no-op
87+
case 11: // Firmware row: install a detected update now, else force a re-check
88+
if (updProgress != -1) return; // already flashing
89+
if (updAvail && updUrl[0]) { updGo = true; } // → netTask flashes; dataTick repaints when updProgress moves → renderUpdating takes over
90+
else { updCheckNow = true; updChkState = 1; markRowAt(ry); } // manual GitHub re-check
91+
return;
92+
default: return; // (out-of-range) no-op
8893
}
8994
markCfg(); markRowAt(ry);
9095
} else if (subTab == ST_BMS) {

0 commit comments

Comments
 (0)