diff --git a/Web App/web/src/i18n/da.json b/Web App/web/src/i18n/da.json index b157d82..53b7750 100644 --- a/Web App/web/src/i18n/da.json +++ b/Web App/web/src/i18n/da.json @@ -117,6 +117,14 @@ "live": "Live data", "settings": "Indstillinger", "settingsTitle": "Laderindstillinger", + "apply": "Anvend", + "turnOn": "Slå til", + "turnOff": "Slå fra", + "limitFloorHint": "{amps} A er bunden — derunder holder laderen pause i stedet for at lade langsomt.", + "boostHint": "Kun den aktuelle session; laderen rydder det, når sessionen slutter.", + "timeoutHint": "Mindst {n} sekunder. Laderen falder tilbage til sin egen strategi, hvis intet skriver inden for tiden.", + "settingsReported": "Rapporteret, kan ikke indstilles", + "settingsReportedHint": "Laderen rapporterer disse; Modbus-kortet har intet register til at skrive dem. Ret dem i Anker-appen.", "device": "Enhed", "alarms": "Alarmer", "phase": "Fase", diff --git a/Web App/web/src/i18n/en.json b/Web App/web/src/i18n/en.json index cf77f6b..dde8d20 100644 --- a/Web App/web/src/i18n/en.json +++ b/Web App/web/src/i18n/en.json @@ -103,6 +103,14 @@ "live": "Live data", "settings": "Settings", "settingsTitle": "Charger settings", + "apply": "Apply", + "turnOn": "Turn on", + "turnOff": "Turn off", + "limitFloorHint": "{amps} A is the floor — below it the charger pauses rather than charging slowly.", + "boostHint": "The current session only; the charger clears it when the session ends.", + "timeoutHint": "At least {n} seconds. The charger falls back to its own strategy if nothing writes within it.", + "settingsReported": "Reported, not settable", + "settingsReportedHint": "The charger reports these; the Modbus map has no register to write them. Change them in the Anker app.", "device": "Device", "alarms": "Alarms", "phase": "Phase", diff --git a/Web App/web/src/i18n/pl.json b/Web App/web/src/i18n/pl.json index 431dc03..04712b9 100644 --- a/Web App/web/src/i18n/pl.json +++ b/Web App/web/src/i18n/pl.json @@ -119,6 +119,14 @@ "live": "Dane na żywo", "settings": "Ustawienia", "settingsTitle": "Ustawienia ładowarki", + "apply": "Zastosuj", + "turnOn": "Włącz", + "turnOff": "Wyłącz", + "limitFloorHint": "{amps} A to dolna granica — poniżej ładowarka wstrzymuje ładowanie, zamiast ładować wolniej.", + "boostHint": "Tylko bieżąca sesja; ładowarka kasuje to po jej zakończeniu.", + "timeoutHint": "Co najmniej {n} sekund. Bez zapisu w tym czasie ładowarka wraca do własnej strategii.", + "settingsReported": "Raportowane, nieustawialne", + "settingsReportedHint": "Ładowarka je raportuje; mapa Modbus nie ma rejestru do ich zapisu. Zmień je w aplikacji Anker.", "device": "Urządzenie", "alarms": "Alarmy", "phase": "Faza", diff --git a/Web App/web/src/views/Charging.vue b/Web App/web/src/views/Charging.vue index 78bab9d..cd3782c 100644 --- a/Web App/web/src/views/Charging.vue +++ b/Web App/web/src/views/Charging.vue @@ -379,6 +379,55 @@ const modbusSettings = computed(() => { ]); }); +// --- What can actually be set ------------------------------------------------- +// +// Only the control block is writable: the current ceiling, boost, the timeout +// and the phase count (21001-21005), plus the start/stop command the control +// card sends. Everything else in the settings readback — charging mode, the two +// balancing flags, the LED — lives in the measurement registers, which the +// charger reports and the Anker app sets. So this card offers controls for the +// four and shows the rest as what they are: a readback. +const draftAmps = ref(16); +const draftSeconds = ref(120); +const draftPhase = ref(0); + +// Seeded from the charger, not from the last thing typed. refreshCtl runs after +// every write, so the form ends up showing what the charger took — which is not +// always what was asked for, since it clamps the current to its own rating. +function syncSettingsDraft() { + const set = mb.value.settings || {}; + if (isSet(set.maxCurrentA)) draftAmps.value = Math.round(set.maxCurrentA); + if (isSet(set.timeoutSeconds)) draftSeconds.value = set.timeoutSeconds; + if (isSet(set.phaseSetting)) draftPhase.value = set.phaseSetting; +} + +const boostOn = computed(() => !!(mb.value.settings || {}).boost); + +// The charger pauses below 6 A rather than charging slowly, and the server +// refuses that case outright, so the slider does not offer it. The ceiling comes +// from the charger's own rating where it reports one. +const LIMIT_FLOOR = 6; +const limitCeiling = computed(() => Math.round(mb.value.maxCurrentA || 32)); + +// The timeout the charger falls back on its own strategy after. The spec's floor +// is "more than five seconds"; a minute of slack above it is a sane lower bound +// for a control that is set by hand. +const TIMEOUT_FLOOR = 6; + +// The settings rows there is no register to write. Same labels and formatting as +// the readings card's settings block, minus the four that have controls above. +const modbusSettingsReported = computed(() => { + const s = mb.value; + const set = s.settings || {}; + return rows([ + ["lastCommand", enumLabel("command", set.lastCommand)], + ["chargingMode", enumLabel("chargingMode", s.chargingMode)], + ["loadBalancing", yesNo(s.loadBalancing)], + ["solarBalancing", yesNo(s.solarBalancing)], + ["ledBrightness", isSet(s.ledBrightness) ? `${s.ledBrightness} %` : null], + ]); +}); + const modbusDevice = computed(() => { const s = mb.value; return rows([ @@ -701,6 +750,7 @@ async function refreshCtl() { // one sitting in the field, where saving would move it to the wrong charger. modbusHost.value = ctl.value?.modbusHost || ""; modbusPort.value = ctl.value?.modbusPort || 502; + syncSettingsDraft(); } catch (e) { ctlError.value = e.message; ctl.value = null; @@ -1121,13 +1171,104 @@ onMounted(async () => {
{{ t("charging.modbus.limitFloorHint", { amps: LIMIT_FLOOR }) }}
+ +{{ t("charging.modbus.boostSet") }}
+{{ t("charging.modbus.boostHint") }}
+{{ t("charging.modbus.timeoutHint", { n: TIMEOUT_FLOOR }) }}
+{{ t("charging.modbus.settingsReportedHint") }}
+{{ ctlError }}