From 8e4c22cfcfe2488e6ad8d07a6becb635fbf0335a Mon Sep 17 00:00:00 2001 From: tajniak81 <13187254+tajniak81@users.noreply.github.com> Date: Thu, 3 Sep 2026 22:05:40 +0200 Subject: [PATCH] The settings card takes a second look, because the charger answers late MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Measured on an A5191 rather than guessed at. The settings frame is not lost and it is not missed: it lands about half a minute after the read that asked for it, by which time that read has long returned. The value goes into the server's state and stays there — six polls afterwards all carried the same settingsAt, served from cache in a dozen milliseconds. What was missing was the second look. Nothing on the page took one, so a card that came up before the answer arrived stayed empty until something else happened to refresh it. That is the whole of "it doesn't always load". So a refresh that comes back without the settings half queues another, at six seconds, twelve, twenty-four, forty-five, and then stops. Bounded because the message the server asks with is one the reference reads as carrying an Anker bug: a charger that never answers is a real possibility, and a page left open all day must not poll one for ever. The patience resets per charger, and the chase stops on an error and on unmount. The previous attempt at this treated it as a wait that was too short and lengthened it from four seconds to twelve. That was the wrong half of the problem — the delay is thirty-odd — and waiting it out inside a UI request would be a poor trade. The longer wait is left where it is; it was not wrong, only insufficient. Co-Authored-By: Claude Opus 5 --- Web App/web/src/views/Charging.vue | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/Web App/web/src/views/Charging.vue b/Web App/web/src/views/Charging.vue index 045176a..a3ff4cd 100644 --- a/Web App/web/src/views/Charging.vue +++ b/Web App/web/src/views/Charging.vue @@ -1781,12 +1781,58 @@ async function refreshCtl() { modbusHost.value = ctl.value?.modbusHost || ""; modbusPort.value = ctl.value?.modbusPort || 502; syncSettingsDraft(); + chaseSettings(); } catch (e) { ctlError.value = e.message; ctl.value = null; + stopSettingsRetry(); } } +// --- Waiting for the half of the snapshot that answers late ------------------- +// +// A snapshot has two halves on two messages. The telemetry comes from the +// trigger and is there by the time the read returns; the settings come when the +// charger gets round to answering the request for them, which on this A5191 was +// measured at around half a minute — long after the read that asked has gone. +// The frame is not lost: it lands in the server's state and the next read +// carries it. But nothing on this page took a next read, so a settings card that +// came up empty stayed empty until something else happened to refresh it, which +// is what "it doesn't always load" was. +// +// So a refresh that comes back without them queues another look, at widening +// gaps, and then stops. Stopping matters: the message the server asks with is +// one the reference reads as carrying an Anker bug, so a charger that never +// answers it is a real possibility, and a page left open all day must not poll +// one for ever. +const SETTINGS_RETRY_MS = [6000, 12000, 24000, 45000]; +let settingsRetryAt = 0; +let settingsRetryFor = ""; +let settingsRetryTimer = null; + +function stopSettingsRetry() { + clearTimeout(settingsRetryTimer); + settingsRetryTimer = null; +} + +function chaseSettings() { + const sn = ctlSerial.value.trim(); + // A different charger is a different question, and gets its own patience. + if (sn !== settingsRetryFor) { + settingsRetryFor = sn; + settingsRetryAt = 0; + } + stopSettingsRetry(); + if (!sn || !ctlReadsDevice.value || dev.value.settings) { + settingsRetryAt = 0; + return; + } + const wait = SETTINGS_RETRY_MS[settingsRetryAt]; + if (wait === undefined) return; // asked enough times; the Refresh button remains + settingsRetryAt++; + settingsRetryTimer = setTimeout(refreshCtl, wait); +} + // --- The charger's address on the local network (Modbus mode) --- // Enabled on the device in the Anker app under Settings > Integrations > Modbus // TCP, which is where the address to type here comes from. @@ -1899,6 +1945,7 @@ onMounted(async () => { onUnmounted(() => { stopLivePoll(); + stopSettingsRetry(); document.removeEventListener("visibilitychange", onPageVisibility); });