From f025dc100fa19321c46ab68e9774250aeae41ba8 Mon Sep 17 00:00:00 2001 From: tajniak81 <13187254+tajniak81@users.noreply.github.com> Date: Tue, 1 Sep 2026 18:26:21 +0200 Subject: [PATCH] The local mode, offered by the menu that picks the mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modbus TCP has been a working control path since the server learned to dial the charger, and the Charging page has asked for the address it needs — but the Control mode selector never listed it. The mode could be reached only by writing it through the API, which is to say not at all. Both selectors now offer it, and both stop offering what it does not use: the OCPP provisioning card and its "Use this one" button are gated on the modes where the charger dials us, and Modbus gets a line saying where its address is asked for instead. On the phone that gate is more than tidiness — the field is a DropdownButtonFormField, so a mode saved from the web left it holding a value none of its items matched. Strings added in en/da/pl for both apps. The mode hint no longer says control happens "over OCPP", because it no longer always does. Co-Authored-By: Claude Opus 5 --- Phone App/assets/i18n/da.json | 4 +++- Phone App/assets/i18n/en.json | 4 +++- Phone App/assets/i18n/pl.json | 4 +++- Phone App/lib/models.dart | 4 ++-- Phone App/lib/screens/settings_screen.dart | 21 ++++++++++++++++----- Web App/web/src/i18n/da.json | 4 +++- Web App/web/src/i18n/en.json | 4 +++- Web App/web/src/i18n/pl.json | 4 +++- Web App/web/src/views/Settings.vue | 22 +++++++++++++++++++--- 9 files changed, 55 insertions(+), 16 deletions(-) diff --git a/Phone App/assets/i18n/da.json b/Phone App/assets/i18n/da.json index b1b50b1..185caa0 100644 --- a/Phone App/assets/i18n/da.json +++ b/Phone App/assets/i18n/da.json @@ -321,13 +321,15 @@ "country": "Land", "countryHint": "Landekode på to bogstaver for din Anker-konto (f.eks. DE, GB, US).", "controlMode": "Styringstilstand", - "controlModeHint": "Hvordan DriverVault styrer laderen over OCPP.", + "controlModeHint": "Hvordan DriverVault styrer laderen.", "controlOff": "Fra (kun overvågning)", "controlOwn": "Eget CSMS (fuld styring)", "controlProxy": "Proxy-CSMS (videresendelse + styring)", + "controlModbus": "Modbus TCP (lokalt netværk)", "controlTitle": "Laderstyring (OCPP)", "controlOwnHint": "Laderen forbinder direkte til DriverVault som sit centralsystem. Peg laderens OCPP-backend på endepunktet nedenfor.", "controlProxyHint": "DriverVault videresender til Ankers sky og kan indsætte kommandoer. Peg laderens OCPP-backend på endepunktet nedenfor.", + "controlModbusHint": "DriverVault kontakter selv laderen på dit lokale netværk, så der er ingen adresse at pege laderen mod her. Slå Modbus TCP til i Anker-appen, og indtast den adresse, den viser, ved siden af laderens betjening på Opladning-siden.", "controlProvisionSteps": "I Anker-appen (eller laderens OCPP-indstillinger) sættes OCPP-backend-URL'en til endepunktet og autorisationsnøglen til tokenet ovenfor.", "chargerSerial": "Laderens serienummer", "controlCheck": "Tjek status", diff --git a/Phone App/assets/i18n/en.json b/Phone App/assets/i18n/en.json index e44cb91..5f5fbb6 100644 --- a/Phone App/assets/i18n/en.json +++ b/Phone App/assets/i18n/en.json @@ -201,13 +201,15 @@ "country": "Country", "countryHint": "Two-letter country code of your Anker account (e.g. DE, GB, US).", "controlMode": "Control mode", - "controlModeHint": "How DriverVault controls the charger over OCPP.", + "controlModeHint": "How DriverVault controls the charger.", "controlOff": "Off (monitoring only)", "controlOwn": "Own CSMS (full control)", "controlProxy": "Proxy CSMS (relay + control)", + "controlModbus": "Modbus TCP (local network)", "controlTitle": "Charger control (OCPP)", "controlOwnHint": "The charger connects directly to DriverVault as its Central System. Point the charger's OCPP backend at the endpoint below.", "controlProxyHint": "DriverVault relays to Anker's cloud and can inject commands. Point the charger's OCPP backend at the endpoint below.", + "controlModbusHint": "DriverVault dials the charger on your local network, so there is nothing to point at an endpoint here. Enable Modbus TCP in the Anker app, then enter the address it shows beside the charger's controls on the Charging page.", "controlProvisionSteps": "In the Anker app (or the charger's OCPP settings), set the OCPP backend URL to the endpoint and the authorization key to the token above.", "chargerSerial": "Charger serial", "controlCheck": "Check status", diff --git a/Phone App/assets/i18n/pl.json b/Phone App/assets/i18n/pl.json index 859542f..074b44b 100644 --- a/Phone App/assets/i18n/pl.json +++ b/Phone App/assets/i18n/pl.json @@ -325,13 +325,15 @@ "country": "Kraj", "countryHint": "Dwuliterowy kod kraju Twojego konta Anker (np. DE, GB, US).", "controlMode": "Tryb sterowania", - "controlModeHint": "Sposób, w jaki DriverVault steruje ładowarką przez OCPP.", + "controlModeHint": "Sposób, w jaki DriverVault steruje ładowarką.", "controlOff": "Wyłączone (tylko monitorowanie)", "controlOwn": "Własny CSMS (pełne sterowanie)", "controlProxy": "CSMS pośredniczący (przekazywanie + sterowanie)", + "controlModbus": "Modbus TCP (sieć lokalna)", "controlTitle": "Sterowanie ładowarką (OCPP)", "controlOwnHint": "Ładowarka łączy się bezpośrednio z DriverVault jako swoim systemem centralnym. Ustaw backend OCPP ładowarki na poniższy adres.", "controlProxyHint": "DriverVault przekazuje ruch do chmury Anker i może wysyłać własne polecenia. Ustaw backend OCPP ładowarki na poniższy adres.", + "controlModbusHint": "DriverVault sam łączy się z ładowarką w sieci lokalnej, więc nie ma tu adresu, który trzeba jej podać. Włącz Modbus TCP w aplikacji Anker, a potem wpisz pokazany adres obok sterowania ładowarką na stronie Ładowanie.", "controlProvisionSteps": "W aplikacji Anker (lub w ustawieniach OCPP ładowarki) ustaw adres backendu OCPP na powyższy endpoint, a klucz autoryzacji na powyższy token.", "chargerSerial": "Numer seryjny ładowarki", "controlCheck": "Sprawdź status", diff --git a/Phone App/lib/models.dart b/Phone App/lib/models.dart index 1f0d9f7..626b318 100644 --- a/Phone App/lib/models.dart +++ b/Phone App/lib/models.dart @@ -992,7 +992,7 @@ class IntegrationView { final String orgId; // "" when the user has no organization final bool canEditOrg; // the caller is an org admin final bool isSuperadmin; // manages the shared layer elsewhere (read-only here) - final String controlMode; // Anker only: effective OCPP mode (off|own|proxy) + final String controlMode; // Anker only: effective control mode (off|own|proxy|modbus) final Map scopes; // "user" and optionally "org" const IntegrationView({ @@ -1049,7 +1049,7 @@ class AnkerControl { final bool hasToken; // a per-charger token has been generated final String tokenHint; // last chars of the token, for display final bool connected; // the charger is connected to the control backend - final String controlMode; // off | own | proxy + final String controlMode; // off | own | proxy | modbus final String connectorStatus; // OCPP connector status, e.g. "Charging" final int meterWh; // last meter reading in watt-hours diff --git a/Phone App/lib/screens/settings_screen.dart b/Phone App/lib/screens/settings_screen.dart index 2de5bbb..01e1318 100644 --- a/Phone App/lib/screens/settings_screen.dart +++ b/Phone App/lib/screens/settings_screen.dart @@ -1588,6 +1588,7 @@ class _IntegrationsTab extends StatelessWidget { ("off", "settings.integrations.controlOff"), ("own", "settings.integrations.controlOwn"), ("proxy", "settings.integrations.controlProxy"), + ("modbus", "settings.integrations.controlModbus"), ], ), ], @@ -2008,13 +2009,23 @@ class _IntegrationCardState extends State<_IntegrationCard> { ), ), - // The chargers on the account. With a control mode active the list lives - // inside the provisioning card below, where picking one fills the serial. - if (_c.anker && view.enabled && view.controlMode == "off") + // The chargers on the account. In an OCPP mode the list lives inside the + // provisioning card below, where picking one fills the serial; Modbus has + // no such card, so there it stays out here. + if (_c.anker && view.enabled && (view.controlMode == "off" || view.controlMode == "modbus")) const Padding(padding: EdgeInsets.only(top: 16), child: _AnkerChargers()), - // OCPP control provisioning (Anker only, when a control mode is active). - if (_c.anker && view.controlMode != "off") + // Modbus is reached rather than provisioned: what it needs is the + // charger's own address, which is asked for beside the controls. + if (_c.anker && view.enabled && view.controlMode == "modbus") + Padding( + padding: const EdgeInsets.only(top: 16), + child: Text(t("settings.integrations.controlModbusHint"), + style: TextStyle(fontSize: 12, color: muted)), + ), + + // OCPP control provisioning (Anker only, in the modes the charger dials). + if (_c.anker && (view.controlMode == "own" || view.controlMode == "proxy")) Padding( padding: const EdgeInsets.only(top: 16), child: _AnkerControlProvision(controlMode: view.controlMode), diff --git a/Web App/web/src/i18n/da.json b/Web App/web/src/i18n/da.json index 568b930..2020511 100644 --- a/Web App/web/src/i18n/da.json +++ b/Web App/web/src/i18n/da.json @@ -325,13 +325,15 @@ "country": "Land", "countryHint": "Landekode på to bogstaver for din Anker-konto (f.eks. DE, GB, US).", "controlMode": "Styringstilstand", - "controlModeHint": "Hvordan DriverVault styrer laderen over OCPP.", + "controlModeHint": "Hvordan DriverVault styrer laderen.", "controlOff": "Fra (kun overvågning)", "controlOwn": "Eget CSMS (fuld styring)", "controlProxy": "Proxy-CSMS (videresendelse + styring)", + "controlModbus": "Modbus TCP (lokalt netværk)", "controlTitle": "Laderstyring (OCPP)", "controlOwnHint": "Laderen forbinder direkte til DriverVault som sit centralsystem. Peg laderens OCPP-backend på endepunktet nedenfor.", "controlProxyHint": "DriverVault videresender til Ankers sky og kan indsætte kommandoer. Peg laderens OCPP-backend på endepunktet nedenfor.", + "controlModbusHint": "DriverVault kontakter selv laderen på dit lokale netværk, så der er ingen adresse at pege laderen mod her. Slå Modbus TCP til i Anker-appen, og indtast den adresse, den viser, ved siden af laderens betjening på Opladning-siden.", "controlProvisionSteps": "I Anker-appen (eller laderens OCPP-indstillinger) sættes OCPP-backend-URL'en til endepunktet og autorisationsnøglen til tokenet ovenfor.", "chargerSerial": "Laderens serienummer", "controlCheck": "Tjek status", diff --git a/Web App/web/src/i18n/en.json b/Web App/web/src/i18n/en.json index 24782b6..f6f7bf9 100644 --- a/Web App/web/src/i18n/en.json +++ b/Web App/web/src/i18n/en.json @@ -324,13 +324,15 @@ "country": "Country", "countryHint": "Two-letter country code of your Anker account (e.g. DE, GB, US).", "controlMode": "Control mode", - "controlModeHint": "How DriverVault controls the charger over OCPP.", + "controlModeHint": "How DriverVault controls the charger.", "controlOff": "Off (monitoring only)", "controlOwn": "Own CSMS (full control)", "controlProxy": "Proxy CSMS (relay + control)", + "controlModbus": "Modbus TCP (local network)", "controlTitle": "Charger control (OCPP)", "controlOwnHint": "The charger connects directly to DriverVault as its Central System. Point the charger's OCPP backend at the endpoint below.", "controlProxyHint": "DriverVault relays to Anker's cloud and can inject commands. Point the charger's OCPP backend at the endpoint below.", + "controlModbusHint": "DriverVault dials the charger on your local network, so there is nothing to point at an endpoint here. Enable Modbus TCP in the Anker app, then enter the address it shows beside the charger's controls on the Charging page.", "controlProvisionSteps": "In the Anker app (or the charger's OCPP settings), set the OCPP backend URL to the endpoint and the authorization key to the token above.", "chargerSerial": "Charger serial", "controlCheck": "Check status", diff --git a/Web App/web/src/i18n/pl.json b/Web App/web/src/i18n/pl.json index 7007799..7cf79bc 100644 --- a/Web App/web/src/i18n/pl.json +++ b/Web App/web/src/i18n/pl.json @@ -329,13 +329,15 @@ "country": "Kraj", "countryHint": "Dwuliterowy kod kraju Twojego konta Anker (np. DE, GB, US).", "controlMode": "Tryb sterowania", - "controlModeHint": "Sposób, w jaki DriverVault steruje ładowarką przez OCPP.", + "controlModeHint": "Sposób, w jaki DriverVault steruje ładowarką.", "controlOff": "Wyłączone (tylko monitorowanie)", "controlOwn": "Własny CSMS (pełne sterowanie)", "controlProxy": "CSMS pośredniczący (przekazywanie + sterowanie)", + "controlModbus": "Modbus TCP (sieć lokalna)", "controlTitle": "Sterowanie ładowarką (OCPP)", "controlOwnHint": "Ładowarka łączy się bezpośrednio z DriverVault jako swoim systemem centralnym. Ustaw backend OCPP ładowarki na poniższy adres.", "controlProxyHint": "DriverVault przekazuje ruch do chmury Anker i może wysyłać własne polecenia. Ustaw backend OCPP ładowarki na poniższy adres.", + "controlModbusHint": "DriverVault sam łączy się z ładowarką w sieci lokalnej, więc nie ma tu adresu, który trzeba jej podać. Włącz Modbus TCP w aplikacji Anker, a potem wpisz pokazany adres obok sterowania ładowarką na stronie Ładowanie.", "controlProvisionSteps": "W aplikacji Anker (lub w ustawieniach OCPP ładowarki) ustaw adres backendu OCPP na powyższy endpoint, a klucz autoryzacji na powyższy token.", "chargerSerial": "Numer seryjny ładowarki", "controlCheck": "Sprawdź status", diff --git a/Web App/web/src/views/Settings.vue b/Web App/web/src/views/Settings.vue index 42ec9a0..0f40308 100644 --- a/Web App/web/src/views/Settings.vue +++ b/Web App/web/src/views/Settings.vue @@ -507,6 +507,12 @@ function fillAnkerForm() { // Effective OCPP control mode (off | own | proxy) — gates the control panel. const ankerControlMode = computed(() => anker.value?.controlMode || "off"); +// Only the OCPP modes are provisioned here. Modbus has no token and no endpoint +// to hand the charger — the one thing it needs is the charger's own address, +// which is asked for beside the controls on the Charging page. +const ankerControlIsOcpp = computed( + () => ankerControlMode.value === "own" || ankerControlMode.value === "proxy", +); // --- Anker Solix OCPP control (per-charger provisioning + connection status) --- const ankerCtlSerial = ref(""); @@ -1501,6 +1507,7 @@ onBeforeUnmount(() => { +

{{ ankerSourceLabel('controlMode') }}

{{ t("settings.integrations.controlModeHint") }}

@@ -1569,7 +1576,7 @@ onBeforeUnmount(() => { {{ ankerStateLabel(c.statusDesc) }}