The last message in the map, and it reboots the charger

0108 was the one thing in the MQTT inventory nobody had wired: the device
power mode, whose single documented value restarts the charger. It is the
only way to reboot a charger that is on neither a CSMS nor the local
network — which is most of them — so the cloud transport sends it now,
and "reset" reaches it too, since that is what the OCPP path has always
called the same act.

Nothing waits for a confirmation: the device that would send it is the
device rebooting, so the command answers at once and says the charger
drops off the cloud for about a minute. The gate is unchanged and now
covers both spellings — an explicit confirm plus a password step-up,
audited either way. Modbus still refuses, because no register does this,
but its refusal now names both transports that can rather than only the
CSMS.

Both clients already had the reset button and its password prompt; they
were hidden in every mode that reads the device, which is why the cloud
never showed one. Modbus is now the only mode without it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tajniak81
2026-09-02 23:15:12 +02:00
co-authored by Claude Opus 5
parent b2d333a63f
commit 4ff6242c8f
17 changed files with 159 additions and 21 deletions
+1
View File
@@ -97,6 +97,7 @@
"reset": "Genstart laderen",
"resetConfirm": "Genstart denne lader nu? En igangværende opladning bliver afbrudt. Indtast din adgangskode igen for at bekræfte.",
"resetPassword": "Din kontoadgangskode",
"restartCloudHint": "Laderen genstarter i stedet for at svare og forsvinder fra skyen i cirka et minut.",
"connectHint": "Indtast laderens serienummer og opdater. Laderen skal være forbundet til DriverVaults OCPP-backend (opsættes under Indstillinger → Integrationer).",
"address": "Laderens adresse på dette netværk",
"addressPlaceholder": "IP-adresse (f.eks. 192.168.1.40)",
+1
View File
@@ -83,6 +83,7 @@
"reset": "Reset charger",
"resetConfirm": "Reboot this charger now? Any active charging session will be interrupted. Re-enter your password to confirm.",
"resetPassword": "Your account password",
"restartCloudHint": "The charger reboots rather than answering, and drops off the cloud for about a minute.",
"connectHint": "Enter your charger's serial and refresh. The charger must be connected to DriverVault's OCPP backend (set up in Settings → Integrations).",
"address": "Charger address on this network",
"addressPlaceholder": "IP address (e.g. 192.168.1.40)",
+1
View File
@@ -99,6 +99,7 @@
"reset": "Zrestartuj ładowarkę",
"resetConfirm": "Zrestartować teraz tę ładowarkę? Trwająca sesja ładowania zostanie przerwana. Wpisz ponownie hasło, aby potwierdzić.",
"resetPassword": "Hasło do Twojego konta",
"restartCloudHint": "Ładowarka zrestartuje się zamiast odpowiedzieć i zniknie z chmury na około minutę.",
"connectHint": "Wpisz numer seryjny ładowarki i odśwież. Ładowarka musi być połączona z backendem OCPP DriverVault (konfiguracja w Ustawienia → Integracje).",
"address": "Adres ładowarki w tej sieci",
"addressPlaceholder": "Adres IP (np. 192.168.1.40)",
+18 -6
View File
@@ -1082,9 +1082,16 @@ async function doAction(action, body) {
}
}
// Reset reboots the charger — a destructive action the server gates behind an
// explicit confirmation AND a password re-authentication (step-up). Reveal the
// inline password prompt; the actual call happens in confirmReset().
// Rebooting the charger. Two transports can: OCPP sends a reset, and the cloud
// sends the charger's own restart message — which is the only way to reboot a
// charger that is on neither a CSMS nor the local network. The register map has
// no such register, so the button is absent in Modbus mode rather than failing
// when pressed.
//
// Either way the server gates it behind an explicit confirmation AND a password
// re-authentication (step-up). Reveal the inline password prompt; the actual
// call happens in confirmReset().
const ctlCanRestart = computed(() => !ctlReadsDevice.value || ctlIsCloud.value);
const resetPrompt = ref(false);
const resetPassword = ref("");
@@ -1416,10 +1423,12 @@ onMounted(async () => {
{{ t("charging.control.skipDelay") }}
</button>
<!-- Reset reboots the charger over OCPP; neither the register map nor
the cloud has an equivalent, so the button is not offered there. -->
<!-- Rebooting the charger: an OCPP reset, or the cloud's own restart
message, which is the way to reach a charger that is on neither a
CSMS nor the LAN. No register does it, so Modbus is the one mode
without the button. -->
<button
v-if="!ctlReadsDevice && !resetPrompt"
v-if="ctlCanRestart && !resetPrompt"
class="dh-btn dh-btn-ghost mt-3 w-full"
:disabled="ctlBusy === 'reset'"
@click="askReset"
@@ -1429,6 +1438,9 @@ onMounted(async () => {
<!-- Step-up: destructive reset requires re-entering the password. -->
<div v-else-if="resetPrompt" class="mt-3 rounded-control border border-danger/40 bg-danger-soft p-3">
<p class="text-xs font-medium text-danger">{{ t("charging.control.resetConfirm") }}</p>
<!-- Over the cloud there is nothing to confirm it with: the charger
that would answer is the one rebooting. -->
<p v-if="ctlIsCloud" class="mt-1 text-[11px] text-danger">{{ t("charging.control.restartCloudHint") }}</p>
<input
v-model="resetPassword"
type="password"