Loadpoint: fix config error for disabled loadpoints (#32880)

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: andig <cpuidle@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Michael Geers <michael@geers.tv>
This commit is contained in:
github-actions[bot] 2026-08-17 07:30:49 +00:00 • committed by GitHub
parent 47fd73be33
commit 64d48e5800
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 21 additions and 2 deletions

View file

@ -13,6 +13,7 @@ import (
"github.com/evcc-io/evcc/util" "github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/config" "github.com/evcc-io/evcc/util/config"
"github.com/evcc-io/evcc/util/templates" "github.com/evcc-io/evcc/util/templates"
"github.com/go-viper/mapstructure/v2"
"github.com/gorilla/mux" "github.com/gorilla/mux"
) )
@ -119,8 +120,9 @@ func loadpointConfig(dev config.Device[loadpoint.API]) (loadpointFullConfig, err
return loadpointFullConfig{}, err return loadpointFullConfig{}, err
} }
// non-strict: runtime settings (mode, ...) are persisted alongside the config
var static loadpoint.StaticConfig var static loadpoint.StaticConfig
if err := util.DecodeOther(staticMap, &static); err != nil { if err := mapstructure.Decode(staticMap, &static); err != nil {
return loadpointFullConfig{}, err return loadpointFullConfig{}, err
} }

View file

@ -25,6 +25,7 @@ func TestLoadpointConfigDisabledNilInstance(t *testing.T) {
"charger": "wallbox", "charger": "wallbox",
"meter": "lp-meter", "meter": "lp-meter",
"title": "Garage", "title": "Garage",
"mode": "pv", // runtime setting persisted by the settings adapter
}, },
} }

View file

@ -59,6 +59,21 @@ test.describe("disable / enable", async () => {
await page.reload(); await page.reload();
await createLoadpoint(page, "Garage"); await createLoadpoint(page, "Garage");
// restart to bring both loadpoints live
await restart();
await page.reload();
// switch charge mode on dashboard; runtime setting is persisted next to the loadpoint config
await page.goto("/");
const modeButton = page
.getByTestId("loadpoint")
.nth(0)
.getByTestId("mode")
.getByRole("button", { name: "Fast" });
await modeButton.click();
await expect(modeButton).toHaveClass(/active/);
await page.goto("/#/config");
const target = page.getByTestId("loadpoint").nth(0); const target = page.getByTestId("loadpoint").nth(0);
await toggleLoadpointDisable(page, 0, "Disable"); await toggleLoadpointDisable(page, 0, "Disable");
@ -66,10 +81,11 @@ test.describe("disable / enable", async () => {
// card shows disabled state // card shows disabled state
await expect(disabledBadge(target)).toBeVisible(); await expect(disabledBadge(target)).toBeVisible();
// restart, no fatal // restart, no fatal, both loadpoints still listed
await restart(); await restart();
await page.reload(); await page.reload();
await expectNoFatal(page); await expectNoFatal(page);
await expect(page.getByTestId("loadpoint")).toHaveCount(2);
await expect(disabledBadge(target)).toBeVisible(); await expect(disabledBadge(target)).toBeVisible();
// re-enable by clicking the disabled card // re-enable by clicking the disabled card