diff --git a/assets/js/components/ChargingPlans/Arrival.vue b/assets/js/components/ChargingPlans/Arrival.vue index 896020a57..d19a35c95 100644 --- a/assets/js/components/ChargingPlans/Arrival.vue +++ b/assets/js/components/ChargingPlans/Arrival.vue @@ -99,7 +99,7 @@ export default defineComponent({ computed: { modeOptions(): SelectOption[] { return [ - { value: "", name: "---" }, + { value: "", name: this.$t("config.loadpoint.defaultModeKeep") }, ...[OFF, PV, MINPV, NOW].map((mode) => ({ value: mode, name: this.$t(`main.mode.${mode}`), diff --git a/cmd/setup.go b/cmd/setup.go index 1a359617f..cfdfca3ab 100644 --- a/cmd/setup.go +++ b/cmd/setup.go @@ -500,6 +500,10 @@ func configureVehicles(static []config.Named, names ...string) error { return fmt.Errorf("cannot create vehicle '%s': %w", cc.Name, err) } + if _, ok := instance.OnIdentified().GetMode(); ok { + log.WARN.Printf("vehicle '%s': default charge 'mode' is deprecated, please configure via UI (charging plan > arrival)", cc.Name) + } + mu.Lock() defer mu.Unlock() devs1 = append(devs1, config.NewStaticDevice(cc, instance)) @@ -525,6 +529,16 @@ func configureVehicles(static []config.Named, names ...string) error { return nil } + // migrate deprecated mode property to vehicle mode setting + if mode, ok := cc.Other["mode"].(string); ok && mode != "" { + key := fmt.Sprintf("vehicle.%s.%s", cc.Name, keys.Mode) + if _, err := settings.String(key); err != nil { + if _, err := api.ChargeModeString(mode); err == nil { + settings.SetString(key, mode) + } + } + } + instance, err := vehicleInstance(cc) if err != nil { return fmt.Errorf("cannot create vehicle '%s': %w", cc.Name, err) diff --git a/i18n/de.json b/i18n/de.json index 499fb46c4..36619fedb 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -439,6 +439,7 @@ "heating": "Wird beim Systemstart gesetzt." }, "defaultModeHelpKeep": "Zuletzt ausgewählter Modus wird beibehalten.", + "defaultModeKeep": "beibehalten", "defaultModeLabel": "Standard-Modus", "delete": "Löschen", "electricalSubtitle": "Im Zweifelsfall Elektriker fragen.", diff --git a/i18n/en.json b/i18n/en.json index eb6c63b8e..b13f91013 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -439,6 +439,7 @@ "heating": "Is set when on system start." }, "defaultModeHelpKeep": "Keeps the last selected mode.", + "defaultModeKeep": "keep as is", "defaultModeLabel": "Default mode", "delete": "Delete", "electricalSubtitle": "When in doubt, ask your electrician.", diff --git a/tests/config-vehicles.spec.ts b/tests/config-vehicles.spec.ts index 76ee21e84..92c1c97c1 100644 --- a/tests/config-vehicles.spec.ts +++ b/tests/config-vehicles.spec.ts @@ -145,7 +145,7 @@ test.describe("vehicles", async () => { await expect(vehicleModal.getByLabel("Battery capacity")).toBeVisible(); await page.getByRole("button", { name: "Show advanced settings" }).click(); - await expect(vehicleModal.getByLabel("Default charging mode")).toBeVisible(); + await expect(vehicleModal.getByLabel("Default charging mode")).not.toBeVisible(); // deprecated await expect(vehicleModal.getByLabel("Maximum number of phases")).toBeVisible(); await expect(vehicleModal.getByLabel("Minimum current")).toBeVisible(); await expect(vehicleModal.getByLabel("Maximum current")).toBeVisible(); @@ -154,7 +154,7 @@ test.describe("vehicles", async () => { await expect(vehicleModal.getByLabel("RFID identification")).toBeVisible(); await page.getByRole("button", { name: "Hide advanced settings" }).click(); - await expect(vehicleModal.getByLabel("Default charging mode")).not.toBeVisible(); + await expect(vehicleModal.getByLabel("Maximum number of phases")).not.toBeVisible(); // polestar template await vehicleModal.getByLabel("Manufacturer").selectOption("Polestar"); @@ -165,7 +165,27 @@ test.describe("vehicles", async () => { await page.getByRole("button", { name: "Show advanced settings" }).click(); await expect(vehicleModal.getByLabel("Cache optional")).toBeVisible(); - await expect(vehicleModal.getByLabel("Default charging mode")).toBeVisible(); + await expect(vehicleModal.getByLabel("Default charging mode")).not.toBeVisible(); // deprecated + }); + + test("migrate deprecated mode property to default mode setting", async ({ page }) => { + await start("config-one-lp.evcc.yaml", "vehicle-mode-migrate.sql"); + + await page.goto("/"); + + const lp = page.getByTestId("loadpoint").first(); + await lp.getByTestId("change-vehicle").locator("select").selectOption("Grey Car"); + + // migrated mode is applied on vehicle selection + await expect(lp.getByTestId("mode").getByRole("button", { name: "Fast" })).toHaveClass( + /active/ + ); + + await lp.getByTestId("charging-plan").getByRole("button", { name: "none" }).click(); + const modal = page.getByTestId("charging-plan-modal"); + await expectModalVisible(modal); + await modal.getByRole("link", { name: "Arrival" }).click(); + await expect(modal.getByRole("combobox", { name: "Default mode" })).toHaveValue("now"); }); test("save and restore rfid identifiers", async ({ page }) => { diff --git a/tests/vehicle-mode-migrate.sql b/tests/vehicle-mode-migrate.sql new file mode 100644 index 000000000..572f8b6bf --- /dev/null +++ b/tests/vehicle-mode-migrate.sql @@ -0,0 +1,15 @@ +BEGIN; + +CREATE TABLE `configs` ( + `id` integer PRIMARY KEY AUTOINCREMENT + , `class` integer + , `type` text + , `title` text + , `icon` text + , `product` text + , `value` text +); + +INSERT INTO configs(class, type, value) VALUES(3, 'template', '{"template":"offline","title":"Grey Car","mode":"now"}'); + +COMMIT; diff --git a/util/templates/defaults.yaml b/util/templates/defaults.yaml index e470c4a39..929474887 100644 --- a/util/templates/defaults.yaml +++ b/util/templates/defaults.yaml @@ -130,6 +130,7 @@ params: example: 10s type: duration - name: mode + deprecated: true description: de: Standardlademodus en: Default charging mode