The settings card stops emptying when one message is late
A snapshot has two halves and they travel separately: telemetry comes from the trigger, the settings only when the charger has something to say about itself. A read can land with the first and not the second — most often the first read after a reconnect — and the card was seeded from that answer alone, so it collapsed to the one control telemetry happens to carry. That is the state of one message, not the state of the charger. Three things, from the outside in. The card keeps what the charger has reported, per serial, across reads. A value stays until another replaces it. They are its own last word either way, and the same ones the server fills a grouped command's siblings from when a caller leaves them out. A charger that goes quiet is no longer written off for good. The miss counter decides whether a read waits for the settings frame at all, and it only ever rose: three unanswered requests early on and no later read waited again, however freely the charger answered afterwards. The comment said "recently enough"; the code said "ever". Answering clears it now. And the first settings are worth the wait a settings write already gives them. Stale settings and never-reported settings were both allowed four seconds. Stale has something to fall back on; never-reported is the empty card, so it gets the full wait — still bounded by the miss counter, so a charger that truly never answers costs it three times and no more. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c65ce0c081
commit
4d51a34c44
@@ -706,18 +706,35 @@ const mqttDraft = ref({});
|
||||
const mqttBase = ref({});
|
||||
const mqttBusy = ref("");
|
||||
|
||||
// The settings the charger has reported, kept per serial across reads.
|
||||
//
|
||||
// The two halves of a snapshot arrive on different messages: the telemetry comes
|
||||
// from the trigger, the settings only when the charger has something to say
|
||||
// about itself. A read can land with the first and not the second — most often
|
||||
// the first read after a reconnect, before any settings frame has arrived — and
|
||||
// seeding the controls from that answer alone emptied the card of everything the
|
||||
// charger had already told us. Which is not the state of the charger; it is the
|
||||
// state of one message.
|
||||
//
|
||||
// So a value the charger has reported stays until it reports another. The values
|
||||
// are its own last word either way, and the same ones the server fills a grouped
|
||||
// command's siblings from when a caller leaves them out.
|
||||
const mqttSeen = ref({}); // serial → the last value each setting was reported with
|
||||
|
||||
function syncMqttSettings() {
|
||||
const draft = {};
|
||||
const sn = ctlSerial.value.trim();
|
||||
const seen = { ...(mqttSeen.value[sn] || {}) };
|
||||
for (const block of MQTT_SETTING_BLOCKS) {
|
||||
for (const f of block.fields) {
|
||||
for (const [key, at] of fieldEntries(f)) {
|
||||
const v = snapshotValue(at);
|
||||
if (isSet(v) && v !== "") draft[key] = v;
|
||||
if (isSet(v) && v !== "") seen[key] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
mqttDraft.value = draft;
|
||||
mqttBase.value = { ...draft };
|
||||
mqttSeen.value = { ...mqttSeen.value, [sn]: seen };
|
||||
mqttDraft.value = { ...seen };
|
||||
mqttBase.value = { ...seen };
|
||||
}
|
||||
|
||||
// Only the settings the charger has actually reported get a control. A value it
|
||||
|
||||
Reference in New Issue
Block a user