Skip to content

Commit

Permalink
Improve heating UI (evcc-io#11837)
Browse files Browse the repository at this point in the history
  • Loading branch information
naltatis authored Jan 24, 2024
1 parent 61039b8 commit 19ea3fb
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 5 deletions.
6 changes: 4 additions & 2 deletions assets/js/components/LimitSocSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,18 @@ export default {
heating: Boolean,
},
emits: ["limit-soc-updated"],
computed: {
options: function () {
const result = [];
for (let soc = 20; soc <= 100; soc += 5) {
for (let soc = 20; soc <= 100; soc += this.step) {
let text = this.fmtSocOption(soc, this.rangePerSoc, distanceUnit(), this.heating);
result.push({ soc, text });
}
return result;
},
step: function () {
return this.heating ? 1 : 5;
},
title: function () {
return this.heating
? this.$t("main.vehicle.tempLimit")
Expand Down
2 changes: 2 additions & 0 deletions assets/js/components/Vehicle.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
:label="vehicleSocTitle"
:value="formattedSoc"
:extraValue="range ? `${fmtNumber(range, 0)} ${rangeUnit}` : null"
data-testid="current-soc"
align="start"
/>
<LabelAndValue
Expand All @@ -29,6 +30,7 @@
:label="$t('main.loadpoint.charged')"
:value="fmtEnergy(chargedEnergy)"
:extraValue="chargedSoc"
data-testid="current-energy"
align="start"
/>
<ChargingPlan
Expand Down
6 changes: 5 additions & 1 deletion assets/js/components/VehicleSoc.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
type="range"
min="0"
max="100"
step="5"
:step="step"
:value="visibleLimitSoc"
class="slider"
:class="{ 'slider--active': sliderActive }"
Expand All @@ -85,6 +85,7 @@ export default {
vehicleTargetSoc: Number,
enabled: Boolean,
charging: Boolean,
heating: Boolean,
minSoc: Number,
effectivePlanSoc: Number,
effectiveLimitSoc: Number,
Expand All @@ -105,6 +106,9 @@ export default {
};
},
computed: {
step: function () {
return this.heating ? 1 : 5;
},
vehicleSocDisplayWidth: function () {
if (this.socBasedCharging) {
if (this.vehicleSoc >= 0) {
Expand Down
9 changes: 9 additions & 0 deletions assets/js/components/VehicleStatus.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
</template>

<script>
import { DEFAULT_LOCALE } from "../i18n";
import formatter from "../mixins/formatter";
import { CO2_TYPE } from "../units";
Expand All @@ -16,6 +17,7 @@ export default {
enabled: Boolean,
connected: Boolean,
charging: Boolean,
heating: Boolean,
effectivePlanTime: String,
planProjectedStart: String,
planActive: Boolean,
Expand Down Expand Up @@ -51,6 +53,13 @@ export default {
},
message: function () {
const t = (key, data) => {
if (this.heating) {
// check for special heating status translation
const name = `main.heatingStatus.${key}`;
if (this.$te(name, DEFAULT_LOCALE)) {
return this.$t(name, data);
}
}
return this.$t(`main.vehicleStatus.${key}`, data);
};
Expand Down
6 changes: 4 additions & 2 deletions assets/js/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export const LOCALES = {
"zh-Hans": ["Chinese (Simplified)", "简体中文"],
};

export const DEFAULT_LOCALE = "en";

function getBrowserLocale() {
const navigatorLocale =
navigator.languages !== undefined ? navigator.languages[0] : navigator.language;
Expand Down Expand Up @@ -72,8 +74,8 @@ export default function setupI18n() {
legacy: true,
silentFallbackWarn: true,
silentTranslationWarn: true,
locale: "en",
fallbackLocale: "en",
locale: DEFAULT_LOCALE,
fallbackLocale: DEFAULT_LOCALE,
messages: { en },
});
setI18nLanguage(i18n.global, getLocale());
Expand Down
6 changes: 6 additions & 0 deletions i18n/de.toml
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ pvExport = "Einspeisung"
pvProduction = "Erzeugung"
selfConsumption = "Eigenverbrauch"

[main.heatingStatus]
charging = "Heize …"
cheapEnergyCharging = "Heize mit günstiger Energie: {price} (Grenze {limit})"
cleanEnergyCharging = "Heize mit sauberer Energie: {co2} (Grenze {limit})"
waitForVehicle = "Bereit. Warte auf Heizung …"

[main.loadpoint]
avgPrice = "⌀ Preis"
charged = "Geladen"
Expand Down
6 changes: 6 additions & 0 deletions i18n/en.toml
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ pvExport = "Grid export"
pvProduction = "Production"
selfConsumption = "Self-consumption"

[main.heatingStatus]
charging = "Heating…"
cheapEnergyCharging = "Heating with cheap energy: {price} (limit {limit})"
cleanEnergyCharging = "Heating with clean energy: {co2} (limit {limit})"
waitForVehicle = "Ready. Waiting for heater…"

[main.loadpoint]
avgPrice = "⌀ Price"
charged = "Charged"
Expand Down
51 changes: 51 additions & 0 deletions tests/heating.evcc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
interval: 10s

site:
title: Hello World
meters:
grid: grid

meters:
- name: grid
type: custom
power:
source: js
script: |
1000
- name: charger_meter
type: custom
power:
source: js
script: |
500
loadpoints:
- title: Water Heater
charger: charger
meter: charger_meter
mode: now

chargers:
- name: charger
icon: waterheater
type: custom
enable:
source: js
script:
enabled:
source: js
script: |
true
status:
source: js
script: |
"C"
maxcurrent:
source: js
script: |
16
soc:
source: js
script: |
55
features: [integrateddevice, heating]
27 changes: 27 additions & 0 deletions tests/heating.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { test, expect } = require("@playwright/test");
const { start, stop } = require("./evcc");

test.beforeAll(async () => {
await start("heating.evcc.yaml");
});
test.afterAll(async () => {
await stop();
});

test.beforeEach(async ({ page }) => {
await page.goto("/");
});

test.describe("loadpoint", async () => {
test("initial values", async ({ page }) => {
await expect(page.getByTestId("current-soc")).toContainText("55.0°C");
await expect(page.getByTestId("limit-soc")).toContainText("100.0°C");
});

test("change limit in 1° steps", async ({ page }) => {
await page.getByTestId("limit-soc").getByRole("combobox").selectOption("69.0°C");
await expect(page.getByTestId("limit-soc")).toContainText("69.0°C");
page.reload();
await expect(page.getByTestId("limit-soc")).toContainText("69.0°C");
});
});

0 comments on commit 19ea3fb

Please sign in to comment.