The settings card takes a second look, because the charger answers late

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 <noreply@anthropic.com>
This commit is contained in:
tajniak81
2026-09-03 22:05:40 +02:00
co-authored by Claude Opus 5
parent 4bcf1305be
commit 8e4c22cfcf
+47
View File
@@ -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);
});
</script>