Config: show vehicle asleep state instead of value errors (#31859)
This commit is contained in:
parent
0cf708a40d
commit
eed3aece14
8 changed files with 83 additions and 7 deletions
|
|
@ -100,16 +100,16 @@ export default {
|
|||
!PHASE_TAGS.includes(name) &&
|
||||
!FORECAST_TAGS.includes(name)
|
||||
)
|
||||
.map(([name, { value, error, warning, muted }]) => {
|
||||
return { name, value, error, warning, muted };
|
||||
.map(([name, { value, error, warning, muted, asleep }]) => {
|
||||
return { name, value, error, warning, muted, asleep };
|
||||
});
|
||||
},
|
||||
phaseEntries() {
|
||||
return Object.entries(this.tags)
|
||||
.filter(([name]) => PHASE_TAGS.includes(name))
|
||||
.sort(([a], [b]) => a.localeCompare(b))
|
||||
.map(([name, { value, error, warning, muted }]) => {
|
||||
return { name, value, error, warning, muted };
|
||||
.map(([name, { value, error, warning, muted, asleep }]) => {
|
||||
return { name, value, error, warning, muted, asleep };
|
||||
});
|
||||
},
|
||||
hasPhaseEntries() {
|
||||
|
|
@ -182,6 +182,9 @@ export default {
|
|||
: "text-nowrap flex-shrink-0";
|
||||
},
|
||||
valueClasses(entry) {
|
||||
if (entry.asleep) {
|
||||
return "value--muted";
|
||||
}
|
||||
if (entry.error) {
|
||||
return "value--error";
|
||||
}
|
||||
|
|
@ -195,6 +198,9 @@ export default {
|
|||
},
|
||||
fmtDeviceValue(entry) {
|
||||
const { name, value } = entry;
|
||||
if (entry.asleep) {
|
||||
return this.$t("config.deviceValue.asleep");
|
||||
}
|
||||
if (value === null || value === undefined) {
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@
|
|||
"deviceValue": {
|
||||
"activeClients": "Aktive Clients",
|
||||
"amount": "Anzahl",
|
||||
"asleep": "schläft",
|
||||
"broker": "Broker",
|
||||
"bucket": "Bucket",
|
||||
"capacity": "Kapazität",
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@
|
|||
"deviceValue": {
|
||||
"activeClients": "Active clients",
|
||||
"amount": "Amount",
|
||||
"asleep": "sleeping",
|
||||
"broker": "Broker",
|
||||
"bucket": "Bucket",
|
||||
"capacity": "Capacity",
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
)
|
||||
|
||||
type errorPlugin struct {
|
||||
*getter
|
||||
err error
|
||||
}
|
||||
|
||||
|
|
@ -32,10 +33,19 @@ func NewErrorFromConfig(other map[string]any) (Plugin, error) {
|
|||
o := &errorPlugin{
|
||||
err: err,
|
||||
}
|
||||
o.getter = defaultGetters(o, 1)
|
||||
|
||||
return o, nil
|
||||
}
|
||||
|
||||
var _ StringGetter = (*errorPlugin)(nil)
|
||||
|
||||
func (o *errorPlugin) StringGetter() (func() (string, error), error) {
|
||||
return func() (string, error) {
|
||||
return "", o.err
|
||||
}, nil
|
||||
}
|
||||
|
||||
var _ IntSetter = (*errorPlugin)(nil)
|
||||
|
||||
func (o *errorPlugin) IntSetter(param string) (func(int64) error, error) {
|
||||
|
|
|
|||
|
|
@ -247,6 +247,7 @@ func deviceInstanceFromMergedConfig[T any](ctx context.Context, id int, class te
|
|||
type testResult = struct {
|
||||
Value any `json:"value"`
|
||||
Error string `json:"error"`
|
||||
Asleep bool `json:"asleep,omitempty"`
|
||||
}
|
||||
|
||||
func hasFeature(instance any, f api.Feature) bool {
|
||||
|
|
@ -266,8 +267,13 @@ func testInstance(ctx context.Context, instance any) map[string]testResult {
|
|||
if errors.Is(err, api.ErrNotAvailable) {
|
||||
return
|
||||
}
|
||||
// asleep is a valid vehicle state, not an error
|
||||
if errors.Is(err, api.ErrAsleep) {
|
||||
tr.Asleep = true
|
||||
} else {
|
||||
tr.Error = err.Error()
|
||||
}
|
||||
}
|
||||
resMu.Lock()
|
||||
res[key] = tr
|
||||
resMu.Unlock()
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/api/globalconfig"
|
||||
"github.com/evcc-io/evcc/plugin/mqtt"
|
||||
"github.com/evcc-io/evcc/util/config"
|
||||
|
|
@ -66,6 +67,24 @@ func TestInstanceParallelProbes(t *testing.T) {
|
|||
require.NotContains(t, res, "power", "blocking getter must be abandoned")
|
||||
}
|
||||
|
||||
// asleepVehicle returns api.ErrAsleep from its getters.
|
||||
type asleepVehicle struct{}
|
||||
|
||||
func (v asleepVehicle) Soc() (float64, error) {
|
||||
return 0, api.ErrAsleep
|
||||
}
|
||||
|
||||
func (v asleepVehicle) Range() (int64, error) {
|
||||
return 0, api.ErrAsleep
|
||||
}
|
||||
|
||||
// TestInstanceAsleep ensures asleep is flagged as state, not as error.
|
||||
func TestInstanceAsleep(t *testing.T) {
|
||||
res := testInstance(context.Background(), asleepVehicle{})
|
||||
assert.Equal(t, testResult{Value: 0.0, Asleep: true}, res["soc"])
|
||||
assert.Equal(t, testResult{Value: int64(0), Asleep: true}, res["range"])
|
||||
}
|
||||
|
||||
func TestConfigReqUnmarshal(t *testing.T) {
|
||||
var req configReq
|
||||
require.NoError(t, json.Unmarshal([]byte(`{
|
||||
|
|
|
|||
8
tests/vehicle-asleep.evcc.yaml
Normal file
8
tests/vehicle-asleep.evcc.yaml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
vehicles:
|
||||
- name: sleepy
|
||||
type: custom
|
||||
title: Sleepy Car
|
||||
capacity: 68
|
||||
soc:
|
||||
source: error
|
||||
error: ErrAsleep
|
||||
25
tests/vehicle-asleep.spec.ts
Normal file
25
tests/vehicle-asleep.spec.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import { start, stop, baseUrl } from "./evcc";
|
||||
|
||||
test.use({ baseURL: baseUrl() });
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await start("vehicle-asleep.evcc.yaml");
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await stop();
|
||||
});
|
||||
|
||||
test.describe("asleep vehicle", async () => {
|
||||
test("config: values show sleeping state instead of errors", async ({ page }) => {
|
||||
await page.goto("/#/config");
|
||||
|
||||
const vehicle = page.getByTestId("vehicle");
|
||||
await expect(vehicle).toHaveCount(1);
|
||||
await expect(vehicle).toContainText("Sleepy Car");
|
||||
await expect(vehicle.getByTestId("device-tag-capacity")).toContainText("68.0 kWh");
|
||||
await expect(vehicle.getByTestId("device-tag-soc")).toContainText("sleeping");
|
||||
await expect(page.getByTestId("header")).toBeVisible();
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue